@@ -159,8 +159,9 @@ func (r *ConditionedReconciler[T]) SetFinalizer(finalizer string, fn func(contex
159159type ctxKey string
160160
161161type ReconcilerContext struct {
162- ForceUpdate bool
163- ForceRequeue bool
162+ ForceUpdate bool
163+ ForceRequeue bool
164+ ReconcileInterval time.Duration
164165}
165166
166167const ctxKeyReconcilerContext = ctxKey ("reconciler-context" )
@@ -173,6 +174,11 @@ func GetReconcilerContext(ctx context.Context) *ReconcilerContext {
173174 return & ReconcilerContext {}
174175}
175176
177+ // ForceStatusUpdate forces a full "Status" update, regardless if conditions have changed.
178+ func ForceStatusUpdate (ctx context.Context ) {
179+ GetReconcilerContext (ctx ).ForceUpdate = true
180+ }
181+
176182// Reconcile reconciles the object with the given request.
177183// implements the `AnyConditionedReconciler` and `reconcile.Reconciler` interfaces.
178184func (r * ConditionedReconciler [T ]) Reconcile (ctx context.Context , req reconcile.Request ) (reconcile.Result , error ) {
@@ -197,21 +203,24 @@ func (r *ConditionedReconciler[T]) Reconcile(ctx context.Context, req reconcile.
197203 }
198204 }
199205
206+ reconcilerCtx := & ReconcilerContext {
207+ ReconcileInterval : r .interval ,
208+ }
209+ condCtx := context .WithValue (ctx , ctxKeyReconcilerContext , reconcilerCtx )
210+
200211 for _ , hook := range r .beforeHooks {
201- if err := hook (ctx , obj ); err != nil {
212+ if err := hook (condCtx , obj ); err != nil {
202213 if errors .Is (err , errStatusSkip ) {
203214 // If the pre-hook returns ErrSkipReconciliation, we skip the reconciliation.
204215 // This is useful for cases where we need to wait for a resource to be ready.
205- return reconcile.Result {RequeueAfter : r . interval }, nil
216+ return reconcile.Result {RequeueAfter : reconcilerCtx . ReconcileInterval }, nil
206217 }
207218
208219 return reconcile.Result {}, err
209220 }
210221 }
211222
212223 conditions := obj .ConditionedStatus ()
213- reconcilerCtx := & ReconcilerContext {}
214- condCtx := context .WithValue (ctx , ctxKeyReconcilerContext , reconcilerCtx )
215224 for _ , condEntry := range r .conditions {
216225 currentCondition := conditions .GetCondition (condEntry .condition )
217226
@@ -224,6 +233,10 @@ func (r *ConditionedReconciler[T]) Reconcile(ctx context.Context, req reconcile.
224233 // NOTE(lxf): if the condition function returns ErrNoop, we skip the condition.
225234 // This is useful for cases where we need to wait for a resource to be ready.
226235 continue
236+ } else if errors .Is (condErr , errStatusSkip ) {
237+ // If the condition function returns ErrSkipReconciliation, we cut the reconciliation short.
238+ conditions .SetConditions (ReadyCondition (condEntry .condition ))
239+ break
227240 } else {
228241 conditions .SetConditions (ErrorCondition (condEntry .condition , "Reconcile" , condErr ))
229242 }
@@ -262,5 +275,5 @@ func (r *ConditionedReconciler[T]) Reconcile(ctx context.Context, req reconcile.
262275 return reconcile.Result {Requeue : true }, nil
263276 }
264277
265- return reconcile.Result {RequeueAfter : r . interval }, nil
278+ return reconcile.Result {RequeueAfter : reconcilerCtx . ReconcileInterval }, nil
266279}
0 commit comments