in pkg/controllers/updaterun/validation.go [257:320]
func validateDeleteStageStatus(
updatingStageIndex, lastFinishedStageIndex, totalStages int,
toBeDeletedBindings []*placementv1beta1.ClusterResourceBinding,
updateRun *placementv1beta1.ClusterStagedUpdateRun,
) (int, error) {
updateRunRef := klog.KObj(updateRun)
existingDeleteStageStatus := updateRun.Status.DeletionStageStatus
if existingDeleteStageStatus == nil {
unexpectedErr := controller.NewUnexpectedBehaviorError(fmt.Errorf("the clusterStagedUpdateRun has nil deletionStageStatus"))
klog.ErrorS(unexpectedErr, "Failed to find the deletionStageStatus in the clusterStagedUpdateRun", "clusterStagedUpdateRun", updateRunRef)
return -1, fmt.Errorf("%w: %s", errStagedUpdatedAborted, unexpectedErr.Error())
}
// Validate whether toBeDeletedBindings are a subnet of the clusters in the delete stage status.
// We only validate if it's a subnet because we will delete the bindings during the deleteStage execution so they can disappear.
// We only need to check the existence, not the order, because clusters are always sorted by name in the delete stage.
deletingClusterMap := make(map[string]struct{}, len(existingDeleteStageStatus.Clusters))
for _, cluster := range existingDeleteStageStatus.Clusters {
deletingClusterMap[cluster.ClusterName] = struct{}{}
}
for _, binding := range toBeDeletedBindings {
if _, ok := deletingClusterMap[binding.Spec.TargetCluster]; !ok {
unexpectedErr := controller.NewUnexpectedBehaviorError(fmt.Errorf("the cluster `%s` to be deleted is not in the delete stage", binding.Spec.TargetCluster))
klog.ErrorS(unexpectedErr, "Detect new cluster to be unscheduled", "clusterResourceBinding", klog.KObj(binding), "clusterStagedUpdateRun", updateRunRef)
return -1, fmt.Errorf("%w: %s", errStagedUpdatedAborted, unexpectedErr.Error())
}
}
deleteStageFinishedCond := meta.FindStatusCondition(existingDeleteStageStatus.Conditions, string(placementv1beta1.StagedUpdateRunConditionSucceeded))
deleteStageProgressingCond := meta.FindStatusCondition(existingDeleteStageStatus.Conditions, string(placementv1beta1.StagedUpdateRunConditionProgressing))
// Check if there is any active updating stage
if updatingStageIndex != -1 || lastFinishedStageIndex < totalStages-1 {
// There are still stages updating before the delete stage, make sure the delete stage is not active/finished.
if condition.IsConditionStatusTrue(deleteStageFinishedCond, updateRun.Generation) ||
condition.IsConditionStatusFalse(deleteStageFinishedCond, updateRun.Generation) ||
condition.IsConditionStatusTrue(deleteStageProgressingCond, updateRun.Generation) {
unexpectedErr := controller.NewUnexpectedBehaviorError(fmt.Errorf("the delete stage is active, but there are still stages updating, updatingStageIndex: %d, lastFinishedStageIndex: %d", updatingStageIndex, lastFinishedStageIndex))
klog.ErrorS(unexpectedErr, "the delete stage is active, but there are still stages updating", "clusterStagedUpdateRun", updateRunRef)
return -1, fmt.Errorf("%w: %s", errStagedUpdatedAborted, unexpectedErr.Error())
}
// If no stage is updating, continue from the last finished stage.
// We initialized lastFinishedStageIndex to -1, so that from the very beginning, we start from 0, the first stage.
if updatingStageIndex == -1 {
updatingStageIndex = lastFinishedStageIndex + 1
}
return updatingStageIndex, nil
}
klog.InfoS("All stages are finished, continue from the delete stage", "clusterStagedUpdateRun", updateRunRef)
// Check if the delete stage has finished successfully.
if condition.IsConditionStatusTrue(deleteStageFinishedCond, updateRun.Generation) {
klog.InfoS("The delete stage has finished successfully, no more stages to update", "clusterStagedUpdateRun", updateRunRef)
return -1, nil
}
// Check if the delete stage has failed.
if condition.IsConditionStatusFalse(deleteStageFinishedCond, updateRun.Generation) {
failedErr := fmt.Errorf("the delete stage has failed, err: %s", deleteStageFinishedCond.Message)
klog.ErrorS(failedErr, "The delete stage has failed", "stageCond", deleteStageFinishedCond, "clusterStagedUpdateRun", updateRunRef)
return -1, fmt.Errorf("%w: %s", errStagedUpdatedAborted, failedErr.Error())
}
// The delete stage is still updating or just to start.
return totalStages, nil
}