77
88 . "github.com/onsi/ginkgo/v2"
99 . "github.com/onsi/gomega"
10+
1011 . "github.com/openmcp-project/controller-utils/pkg/testing/matchers"
1112
1213 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -28,7 +29,7 @@ var _ = Describe("Status Updater", func() {
2829 It ("should update an empty status" , func () {
2930 env := testutils .NewEnvironmentBuilder ().WithFakeClient (coScheme ).WithInitObjectPath ("testdata" , "test-02" ).WithDynamicObjectsWithStatus (& CustomObject {}).Build ()
3031 obj := & CustomObject {}
31- Expect (env .Client ().Get (env .Ctx , testutils .ObjectKey ("nostatus" , "default" ), obj )).To (Succeed ())
32+ Expect (env .Client ().Get (env .Ctx , controller .ObjectKey ("nostatus" , "default" ), obj )).To (Succeed ())
3233 rr := controller.ReconcileResult [* CustomObject , ConditionStatus ]{
3334 Object : obj ,
3435 ReconcileError : errors .WithReason (fmt .Errorf ("test error" ), "TestError" ),
@@ -63,6 +64,119 @@ var _ = Describe("Status Updater", func() {
6364 ))
6465 })
6566
67+ It ("should update an existing status" , func () {
68+ env := testutils .NewEnvironmentBuilder ().WithFakeClient (coScheme ).WithInitObjectPath ("testdata" , "test-02" ).WithDynamicObjectsWithStatus (& CustomObject {}).Build ()
69+ obj := & CustomObject {}
70+ Expect (env .Client ().Get (env .Ctx , controller .ObjectKey ("status" , "default" ), obj )).To (Succeed ())
71+ rr := controller.ReconcileResult [* CustomObject , ConditionStatus ]{
72+ Object : obj ,
73+ Conditions : dummyConditions (),
74+ }
75+ su := preconfiguredStatusUpdaterBuilder ().WithPhaseUpdateFunc (func (obj * CustomObject , rr controller.ReconcileResult [* CustomObject , ConditionStatus ]) (CustomObjectPhase , error ) {
76+ return PhaseSucceeded , nil
77+ }).Build ()
78+ now := time .Now ()
79+ res , err := su .UpdateStatus (env .Ctx , env .Client (), rr )
80+ Expect (res ).To (Equal (rr .Result ))
81+ Expect (err ).ToNot (HaveOccurred ())
82+ Expect (env .Client ().Get (env .Ctx , client .ObjectKeyFromObject (obj ), obj )).To (Succeed ())
83+
84+ Expect (obj .Status .Phase ).To (Equal (PhaseSucceeded ))
85+ Expect (obj .Status .ObservedGeneration ).To (Equal (obj .GetGeneration ()))
86+ Expect (obj .Status .Reason ).To (BeEmpty ())
87+ Expect (obj .Status .Message ).To (BeEmpty ())
88+ Expect (obj .Status .LastReconcileTime .Time ).To (BeTemporally ("~" , now , 1 * time .Second ))
89+ Expect (obj .Status .Conditions ).To (ConsistOf (
90+ MatchCondition (NewConditionImpl [ConditionStatus ]().
91+ WithType ("TestConditionTrue" ).
92+ WithStatus (ConditionStatusTrue ).
93+ WithReason ("TestReasonTrue" ).
94+ WithMessage ("TestMessageTrue" ).
95+ WithLastTransitionTime (obj .Status .LastReconcileTime .Time )),
96+ MatchCondition (NewConditionImpl [ConditionStatus ]().
97+ WithType ("TestConditionFalse" ).
98+ WithStatus (ConditionStatusFalse ).
99+ WithReason ("TestReasonFalse" ).
100+ WithMessage ("TestMessageFalse" ).
101+ WithLastTransitionTime (obj .Status .LastReconcileTime .Time )),
102+ ))
103+ })
104+
105+ It ("should not update disabled fields" , func () {
106+ env := testutils .NewEnvironmentBuilder ().WithFakeClient (coScheme ).WithInitObjectPath ("testdata" , "test-02" ).WithDynamicObjectsWithStatus (& CustomObject {}).Build ()
107+ obj := & CustomObject {}
108+ Expect (env .Client ().Get (env .Ctx , controller .ObjectKey ("status" , "default" ), obj )).To (Succeed ())
109+ before := obj .DeepCopy ()
110+ for _ , disabledField := range controller .AllStatusFields () {
111+ By (fmt .Sprintf ("Testing disabled field %s" , disabledField ))
112+ // reset object to remove changes from previous loop executions
113+ modified := obj .DeepCopy ()
114+ obj .Status = before .Status
115+ Expect (env .Client ().Status ().Patch (env .Ctx , obj , client .MergeFrom (modified ))).To (Succeed ())
116+ rr := controller.ReconcileResult [* CustomObject , ConditionStatus ]{
117+ Object : obj ,
118+ Conditions : dummyConditions (),
119+ Reason : "TestReason" ,
120+ Message : "TestMessage" ,
121+ }
122+ su := preconfiguredStatusUpdaterBuilder ().WithPhaseUpdateFunc (func (obj * CustomObject , rr controller.ReconcileResult [* CustomObject , ConditionStatus ]) (CustomObjectPhase , error ) {
123+ return PhaseSucceeded , nil
124+ }).WithoutFields (disabledField ).Build ()
125+ now := time .Now ()
126+ res , err := su .UpdateStatus (env .Ctx , env .Client (), rr )
127+ Expect (res ).To (Equal (rr .Result ))
128+
129+ Expect (err ).ToNot (HaveOccurred ())
130+ Expect (env .Client ().Get (env .Ctx , client .ObjectKeyFromObject (obj ), obj )).To (Succeed ())
131+
132+ if disabledField == controller .STATUS_FIELD_PHASE {
133+ Expect (obj .Status .Phase ).To (Equal (before .Status .Phase ))
134+ } else {
135+ Expect (obj .Status .Phase ).To (Equal (PhaseSucceeded ))
136+ }
137+ if disabledField == controller .STATUS_FIELD_OBSERVED_GENERATION {
138+ Expect (obj .Status .ObservedGeneration ).To (Equal (before .Status .ObservedGeneration ))
139+ } else {
140+ Expect (obj .Status .ObservedGeneration ).To (Equal (obj .GetGeneration ()))
141+ }
142+ if disabledField == controller .STATUS_FIELD_REASON {
143+ Expect (obj .Status .Reason ).To (Equal (before .Status .Reason ))
144+ } else {
145+ Expect (obj .Status .Reason ).To (Equal (rr .Reason ))
146+ }
147+ if disabledField == controller .STATUS_FIELD_MESSAGE {
148+ Expect (obj .Status .Message ).To (Equal (before .Status .Message ))
149+ } else {
150+ Expect (obj .Status .Message ).To (Equal (rr .Message ))
151+ }
152+ if disabledField == controller .STATUS_FIELD_LAST_RECONCILE_TIME {
153+ Expect (obj .Status .LastReconcileTime .Time ).To (Equal (before .Status .LastReconcileTime .Time ))
154+ } else {
155+ Expect (obj .Status .LastReconcileTime .Time ).To (BeTemporally ("~" , now , 1 * time .Second ))
156+ }
157+ if disabledField == controller .STATUS_FIELD_CONDITIONS {
158+ Expect (obj .Status .Conditions ).To (Equal (before .Status .Conditions ))
159+ } else {
160+ Expect (obj .Status .Conditions ).To (ConsistOf (
161+ MatchCondition (NewConditionImpl [ConditionStatus ]().
162+ WithType ("TestConditionTrue" ).
163+ WithStatus (ConditionStatusTrue ).
164+ WithReason ("TestReasonTrue" ).
165+ WithMessage ("TestMessageTrue" ).
166+ WithLastTransitionTime (now ).
167+ WithTimestampTolerance (1 * time .Second )),
168+ MatchCondition (NewConditionImpl [ConditionStatus ]().
169+ WithType ("TestConditionFalse" ).
170+ WithStatus (ConditionStatusFalse ).
171+ WithReason ("TestReasonFalse" ).
172+ WithMessage ("TestMessageFalse" ).
173+ WithLastTransitionTime (now ).
174+ WithTimestampTolerance (1 * time .Second )),
175+ ))
176+ }
177+ }
178+ })
179+
66180})
67181
68182func preconfiguredStatusUpdaterBuilder () * controller.StatusUpdaterBuilder [* CustomObject , CustomObjectPhase , ConditionStatus ] {
0 commit comments