@@ -104,15 +104,23 @@ func (r *Reconciler) Reconcile(ctx context.Context, req runtime.Request) (runtim
104104 // Emit the update run status metric based on status conditions in the updateRun.
105105 defer emitUpdateRunStatusMetric (updateRun )
106106
107+ state := updateRun .GetUpdateRunSpec ().State
108+
107109 var updatingStageIndex int
108110 var toBeUpdatedBindings , toBeDeletedBindings []placementv1beta1.BindingObj
109111 updateRunStatus := updateRun .GetUpdateRunStatus ()
110112 initCond := meta .FindStatusCondition (updateRunStatus .Conditions , string (placementv1beta1 .StagedUpdateRunConditionInitialized ))
111- if ! condition .IsConditionStatusTrue (initCond , updateRun .GetGeneration ()) {
112- if condition .IsConditionStatusFalse (initCond , updateRun .GetGeneration ()) {
113+ // Check if initialized regardless of generation.
114+ // The updateRun spec fields are immutable except for the state field. When the state changes,
115+ // the update run generation increments, but we don't need to reinitialize since initialization is a one-time setup.
116+ if ! (initCond != nil && initCond .Status == metav1 .ConditionTrue ) {
117+ // Check if initialization failed for the current generation.
118+ if initCond != nil && initCond .Status == metav1 .ConditionFalse {
113119 klog .V (2 ).InfoS ("The updateRun has failed to initialize" , "errorMsg" , initCond .Message , "updateRun" , runObjRef )
114120 return runtime.Result {}, nil
115121 }
122+
123+ // Initialize the updateRun.
116124 var initErr error
117125 if toBeUpdatedBindings , toBeDeletedBindings , initErr = r .initialize (ctx , updateRun ); initErr != nil {
118126 klog .ErrorS (initErr , "Failed to initialize the updateRun" , "updateRun" , runObjRef )
@@ -122,10 +130,10 @@ func (r *Reconciler) Reconcile(ctx context.Context, req runtime.Request) (runtim
122130 }
123131 return runtime.Result {}, initErr
124132 }
125- updatingStageIndex = 0 // start from the first stage.
126- klog .V (2 ).InfoS ("Initialized the updateRun" , "updateRun" , runObjRef )
133+ updatingStageIndex = 0 // start from the first stage (typically for Initialize or Execute states) .
134+ klog .V (2 ).InfoS ("Initialized the updateRun" , "state" , state , " updateRun" , runObjRef )
127135 } else {
128- klog .V (2 ).InfoS ("The updateRun is initialized" , "updateRun" , runObjRef )
136+ klog .V (2 ).InfoS ("The updateRun is initialized" , "state" , state , " updateRun" , runObjRef )
129137 // Check if the updateRun is finished.
130138 finishedCond := meta .FindStatusCondition (updateRunStatus .Conditions , string (placementv1beta1 .StagedUpdateRunConditionSucceeded ))
131139 if condition .IsConditionStatusTrue (finishedCond , updateRun .GetGeneration ()) || condition .IsConditionStatusFalse (finishedCond , updateRun .GetGeneration ()) {
@@ -151,28 +159,32 @@ func (r *Reconciler) Reconcile(ctx context.Context, req runtime.Request) (runtim
151159 }
152160
153161 // Execute the updateRun.
154- klog .V (2 ).InfoS ("Continue to execute the updateRun" , "updatingStageIndex" , updatingStageIndex , "updateRun" , runObjRef )
155- finished , waitTime , execErr := r .execute (ctx , updateRun , updatingStageIndex , toBeUpdatedBindings , toBeDeletedBindings )
156- if errors .Is (execErr , errStagedUpdatedAborted ) {
157- // errStagedUpdatedAborted cannot be retried.
158- return runtime.Result {}, r .recordUpdateRunFailed (ctx , updateRun , execErr .Error ())
159- }
162+ if state == placementv1beta1 .StateExecuted {
163+ klog .V (2 ).InfoS ("Continue to execute the updateRun" , "state" , state , "updatingStageIndex" , updatingStageIndex , "updateRun" , runObjRef )
164+ finished , waitTime , execErr := r .execute (ctx , updateRun , updatingStageIndex , toBeUpdatedBindings , toBeDeletedBindings )
165+ if errors .Is (execErr , errStagedUpdatedAborted ) {
166+ // errStagedUpdatedAborted cannot be retried.
167+ return runtime.Result {}, r .recordUpdateRunFailed (ctx , updateRun , execErr .Error ())
168+ }
160169
161- if finished {
162- klog .V (2 ).InfoS ("The updateRun is completed" , "updateRun" , runObjRef )
163- return runtime.Result {}, r .recordUpdateRunSucceeded (ctx , updateRun )
164- }
170+ if finished {
171+ klog .V (2 ).InfoS ("The updateRun is completed" , "updateRun" , runObjRef )
172+ return runtime.Result {}, r .recordUpdateRunSucceeded (ctx , updateRun )
173+ }
165174
166- // The execution is not finished yet or it encounters a retriable error.
167- // We need to record the status and requeue.
168- if updateErr := r .recordUpdateRunStatus (ctx , updateRun ); updateErr != nil {
169- return runtime.Result {}, updateErr
170- }
171- klog .V (2 ).InfoS ("The updateRun is not finished yet" , "requeueWaitTime" , waitTime , "execErr" , execErr , "updateRun" , runObjRef )
172- if execErr != nil {
173- return runtime.Result {}, execErr
175+ // The execution is not finished yet or it encounters a retriable error.
176+ // We need to record the status and requeue.
177+ if updateErr := r .recordUpdateRunStatus (ctx , updateRun ); updateErr != nil {
178+ return runtime.Result {}, updateErr
179+ }
180+ klog .V (2 ).InfoS ("The updateRun is not finished yet" , "requeueWaitTime" , waitTime , "execErr" , execErr , "updateRun" , runObjRef )
181+ if execErr != nil {
182+ return runtime.Result {}, execErr
183+ }
184+ return runtime.Result {Requeue : true , RequeueAfter : waitTime }, nil
174185 }
175- return runtime.Result {Requeue : true , RequeueAfter : waitTime }, nil
186+ klog .V (2 ).InfoS ("The updateRun is initialized but not executed, waiting to execute" , "state" , state , "updateRun" , runObjRef )
187+ return runtime.Result {}, nil
176188}
177189
178190// handleDelete handles the deletion of the updateRun object.
0 commit comments