in pkg/controllers/updaterun/execution.go [290:382]
func (r *Reconciler) checkAfterStageTasksStatus(ctx context.Context, updatingStageIndex int, updateRun *placementv1beta1.ClusterStagedUpdateRun) (bool, time.Duration, error) {
updateRunRef := klog.KObj(updateRun)
updatingStageStatus := &updateRun.Status.StagesStatus[updatingStageIndex]
updatingStage := &updateRun.Status.StagedUpdateStrategySnapshot.Stages[updatingStageIndex]
if updatingStage.AfterStageTasks == nil {
klog.V(2).InfoS("There is no after stage task for this stage", "stage", updatingStage.Name, "clusterStagedUpdateRun", updateRunRef)
return true, 0, nil
}
passed := true
afterStageWaitTime := time.Duration(-1)
for i, task := range updatingStage.AfterStageTasks {
switch task.Type {
case placementv1beta1.AfterStageTaskTypeTimedWait:
waitStartTime := meta.FindStatusCondition(updatingStageStatus.Conditions, string(placementv1beta1.StageUpdatingConditionProgressing)).LastTransitionTime.Time
// Check if the wait time has passed.
waitTime := time.Until(waitStartTime.Add(task.WaitTime.Duration))
if waitTime > 0 {
klog.V(2).InfoS("The after stage task still need to wait", "waitStartTime", waitStartTime, "waitTime", task.WaitTime, "stage", updatingStage.Name, "clusterStagedUpdateRun", updateRunRef)
passed = false
afterStageWaitTime = waitTime
} else {
markAfterStageWaitTimeElapsed(&updatingStageStatus.AfterStageTaskStatus[i], updateRun.Generation)
klog.V(2).InfoS("The after stage wait task has completed", "stage", updatingStage.Name, "clusterStagedUpdateRun", updateRunRef)
}
case placementv1beta1.AfterStageTaskTypeApproval:
// Check if the approval request has been created.
approvalRequest := placementv1beta1.ClusterApprovalRequest{
ObjectMeta: metav1.ObjectMeta{
Name: updatingStageStatus.AfterStageTaskStatus[i].ApprovalRequestName,
Labels: map[string]string{
placementv1beta1.TargetUpdatingStageNameLabel: updatingStage.Name,
placementv1beta1.TargetUpdateRunLabel: updateRun.Name,
placementv1beta1.IsLatestUpdateRunApprovalLabel: "true",
},
},
Spec: placementv1beta1.ApprovalRequestSpec{
TargetUpdateRun: updateRun.Name,
TargetStage: updatingStage.Name,
},
}
requestRef := klog.KObj(&approvalRequest)
if err := r.Client.Create(ctx, &approvalRequest); err != nil {
if apierrors.IsAlreadyExists(err) {
// The approval task already exists.
markAfterStageRequestCreated(&updatingStageStatus.AfterStageTaskStatus[i], updateRun.Generation)
if err = r.Client.Get(ctx, client.ObjectKeyFromObject(&approvalRequest), &approvalRequest); err != nil {
klog.ErrorS(err, "Failed to get the already existing approval request", "approvalRequest", requestRef, "stage", updatingStage.Name, "clusterStagedUpdateRun", updateRunRef)
return false, -1, controller.NewAPIServerError(true, err)
}
if approvalRequest.Spec.TargetStage != updatingStage.Name || approvalRequest.Spec.TargetUpdateRun != updateRun.Name {
unexpectedErr := controller.NewUnexpectedBehaviorError(fmt.Errorf("the approval request task `%s` is targeting update run `%s` and stage `%s` ", approvalRequest.Name, approvalRequest.Spec.TargetStage, approvalRequest.Spec.TargetUpdateRun))
klog.ErrorS(unexpectedErr, "Found an approval request targeting wrong stage", "approvalRequestTask", requestRef, "stage", updatingStage.Name, "clusterStagedUpdateRun", updateRunRef)
return false, -1, fmt.Errorf("%w: %s", errStagedUpdatedAborted, unexpectedErr.Error())
}
approvalAccepted := condition.IsConditionStatusTrue(meta.FindStatusCondition(approvalRequest.Status.Conditions, string(placementv1beta1.ApprovalRequestConditionApprovalAccepted)), approvalRequest.Generation)
approved := condition.IsConditionStatusTrue(meta.FindStatusCondition(approvalRequest.Status.Conditions, string(placementv1beta1.ApprovalRequestConditionApproved)), approvalRequest.Generation)
if !approvalAccepted && !approved {
klog.V(2).InfoS("The approval request has not been approved yet", "approvalRequestTask", requestRef, "stage", updatingStage.Name, "clusterStagedUpdateRun", updateRunRef)
passed = false
continue
}
if approved {
klog.V(2).InfoS("The approval request has been approved", "approvalRequestTask", requestRef, "stage", updatingStage.Name, "clusterStagedUpdateRun", updateRunRef)
if !approvalAccepted {
if err = r.updateApprovalRequestAccepted(ctx, &approvalRequest); err != nil {
klog.ErrorS(err, "Failed to accept the approved approval request", "approvalRequest", requestRef, "stage", updatingStage.Name, "clusterStagedUpdateRun", updateRunRef)
// retriable err
return false, -1, err
}
}
} else {
// Approved state should not change once the approval is accepted.
klog.V(2).InfoS("The approval request has been approval-accepted, ignoring changing back to unapproved", "approvalRequestTask", requestRef, "stage", updatingStage.Name, "clusterStagedUpdateRun", updateRunRef)
}
markAfterStageRequestApproved(&updatingStageStatus.AfterStageTaskStatus[i], updateRun.Generation)
} else {
// retriable error
klog.ErrorS(err, "Failed to create the approval request", "approvalRequest", requestRef, "stage", updatingStage.Name, "clusterStagedUpdateRun", updateRunRef)
return false, -1, controller.NewAPIServerError(false, err)
}
} else {
// The approval request has been created for the first time.
klog.V(2).InfoS("The approval request has been created", "approvalRequestTask", requestRef, "stage", updatingStage.Name, "clusterStagedUpdateRun", updateRunRef)
markAfterStageRequestCreated(&updatingStageStatus.AfterStageTaskStatus[i], updateRun.Generation)
passed = false
}
}
}
if passed {
afterStageWaitTime = 0
}
return passed, afterStageWaitTime, nil
}