Skip to content

Commit 23c55bc

Browse files
author
Ryan Zhang
committed
fix the code
1 parent e9e49a7 commit 23c55bc

File tree

5 files changed

+185
-44
lines changed

5 files changed

+185
-44
lines changed

pkg/controllers/clusterresourceplacement/controller.go

Lines changed: 63 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -969,6 +969,7 @@ func (r *Reconciler) listSortedResourceSnapshots(ctx context.Context, placementO
969969
}
970970

971971
// setPlacementStatus returns if there is a cluster scheduled by the scheduler.
972+
// it returns true if the cluster schedule succeeded, false otherwise.
972973
func (r *Reconciler) setPlacementStatus(
973974
ctx context.Context,
974975
placementObj fleetv1beta1.PlacementObj,
@@ -997,11 +998,8 @@ func (r *Reconciler) setPlacementStatus(
997998
// TODO: need to track whether we have deleted the resources for the last decisions.
998999
// The undeleted resources on these old clusters could lead to failed synchronized or applied condition.
9991000
// Today, we only track the resources progress if the same cluster is selected again.
1000-
1001-
// For now, only CRP supports placement statuses - namespace-scoped placements would need different handling
1002-
if crp, ok := placementObj.(*fleetv1beta1.ClusterResourcePlacement); ok {
1003-
crp.Status.PlacementStatuses = []fleetv1beta1.ResourcePlacementStatus{}
1004-
}
1001+
klog.V(2).InfoS("Resetting the resource placement status since scheduled condition is unknown", "placement", klog.KObj(placementObj))
1002+
placementStatus.PlacementStatuses = []fleetv1beta1.ResourcePlacementStatus{}
10051003
return false, nil
10061004
}
10071005

@@ -1032,43 +1030,47 @@ func (r *Reconciler) setPlacementStatus(
10321030

10331031
// For clusters that failed to get scheduled, set a resource placement status with the
10341032
// failed to schedule condition for each of them.
1035-
// This is currently CRP-specific functionality
1036-
if crp, ok := placementObj.(*fleetv1beta1.ClusterResourcePlacement); ok {
1037-
allRPS = appendFailedToScheduleResourcePlacementStatuses(allRPS, unselected, failedToScheduleClusterCount, crp)
1038-
1039-
crp.Status.PlacementStatuses = allRPS
1033+
allRPS = appendFailedToScheduleResourcePlacementStatuses(allRPS, unselected, failedToScheduleClusterCount, placementObj)
1034+
placementStatus.PlacementStatuses = allRPS
1035+
klog.V(2).InfoS("Updated placement status for each individual cluster", "selectedNoCluster", len(selected), "unselectedNoCluster", len(unselected), "failedToScheduleClusterCount", failedToScheduleClusterCount, "placement", klog.KObj(placementObj))
10401036

1041-
// Prepare the conditions for the CRP object itself.
1042-
1043-
if len(selected) == 0 {
1044-
// There is no selected cluster at all. It could be that there is no matching cluster
1045-
// given the current scheduling policy; there remains a corner case as well where a cluster
1046-
// has been selected before (with resources being possibly applied), but has now
1047-
// left the fleet. To address this corner case, Fleet here will remove all lingering
1048-
// conditions (any condition type other than CRPScheduled).
1037+
// Prepare the conditions for the placement object itself.
1038+
policy := placementObj.GetPlacementSpec().Policy
1039+
if len(selected) == 0 {
1040+
// There is no selected cluster at all. It could be that there is no matching cluster
1041+
// given the current scheduling policy; there remains a corner case as well where a cluster
1042+
// has been selected before (with resources being possibly applied), but has now
1043+
// left the fleet. To address this corner case, Fleet here will remove all lingering
1044+
// conditions (any condition type other than CRPScheduled).
10491045

1050-
// Note that the scheduled condition has been set earlier in this method.
1051-
crp.Status.Conditions = []metav1.Condition{*crp.GetCondition(string(fleetv1beta1.ClusterResourcePlacementScheduledConditionType))}
1052-
return false, nil
1053-
}
1046+
// Note that the scheduled condition has been set earlier in this method.
1047+
placementStatus.Conditions = []metav1.Condition{*placementObj.GetCondition(getPlacementScheduledConditionType(placementObj))}
1048+
return isPolicySelectingNoClusters(policy), nil
1049+
}
10541050

1055-
if crp.Spec.Strategy.Type == fleetv1beta1.ExternalRolloutStrategyType {
1056-
// For external rollout strategy, if clusters observe different resource snapshot versions,
1057-
// we set RolloutStarted to Unknown without any other conditions since we do not know exactly which version is rolling out.
1058-
// We also need to reset ObservedResourceIndex and selectedResources.
1059-
rolloutStartedUnknown, err := r.determineRolloutStateForPlacementWithExternalRolloutStrategy(ctx, placementObj, selected, allRPS, selectedResourceIDs)
1060-
if err != nil || rolloutStartedUnknown {
1061-
return true, err
1062-
}
1051+
if placementObj.GetPlacementSpec().Strategy.Type == fleetv1beta1.ExternalRolloutStrategyType {
1052+
// For external rollout strategy, if clusters observe different resource snapshot versions,
1053+
// we set RolloutStarted to Unknown without any other conditions since we do not know exactly which version is rolling out.
1054+
// We also need to reset ObservedResourceIndex and selectedResources.
1055+
rolloutStartedUnknown, err := r.determineRolloutStateForPlacementWithExternalRolloutStrategy(ctx, placementObj, selected, allRPS, selectedResourceIDs)
1056+
if err != nil || rolloutStartedUnknown {
1057+
return true, err
10631058
}
1064-
1065-
setCRPConditions(crp, allRPS, rpsSetCondTypeCounter, expectedCondTypes)
10661059
}
1067-
1060+
setCRPConditions(placementObj, allRPS, rpsSetCondTypeCounter, expectedCondTypes)
1061+
klog.V(2).InfoS("Updated placement status for the entire placement", "placement", klog.KObj(placementObj))
10681062
return true, nil
10691063
}
10701064

1071-
// TODO: This currently only works for cluster-scoped placements due to condition type differences
1065+
// isPolicySelectingNoClusters checks if the given placement policy is selecting no clusters by design.
1066+
func isPolicySelectingNoClusters(policy *fleetv1beta1.PlacementPolicy) bool {
1067+
if policy == nil {
1068+
return false
1069+
}
1070+
return (policy.PlacementType == fleetv1beta1.PickNPlacementType && *policy.NumberOfClusters == 0) || (policy.PlacementType == fleetv1beta1.PickFixedPlacementType && len(policy.ClusterNames) == 0)
1071+
}
1072+
1073+
// determineRolloutStateForPlacementWithExternalRolloutStrategy checks the rollout state for the placement with external rollout strategy.
10721074
func (r *Reconciler) determineRolloutStateForPlacementWithExternalRolloutStrategy(
10731075
ctx context.Context,
10741076
placementObj fleetv1beta1.PlacementObj,
@@ -1100,7 +1102,7 @@ func (r *Reconciler) determineRolloutStateForPlacementWithExternalRolloutStrateg
11001102
placementStatus.ObservedResourceIndex = ""
11011103
placementStatus.SelectedResources = []fleetv1beta1.ResourceIdentifier{}
11021104
placementObj.SetConditions(metav1.Condition{
1103-
Type: string(fleetv1beta1.ClusterResourcePlacementRolloutStartedConditionType),
1105+
Type: getPlacementRolloutStartedConditionType(placementObj),
11041106
Status: metav1.ConditionUnknown,
11051107
Reason: condition.RolloutControlledByExternalControllerReason,
11061108
Message: "Rollout is controlled by an external controller and different resource snapshot versions are observed across clusters",
@@ -1121,7 +1123,7 @@ func (r *Reconciler) determineRolloutStateForPlacementWithExternalRolloutStrateg
11211123
placementStatus.ObservedResourceIndex = ""
11221124
placementStatus.SelectedResources = []fleetv1beta1.ResourceIdentifier{}
11231125
placementObj.SetConditions(metav1.Condition{
1124-
Type: string(fleetv1beta1.ClusterResourcePlacementRolloutStartedConditionType),
1126+
Type: getPlacementRolloutStartedConditionType(placementObj),
11251127
Status: metav1.ConditionUnknown,
11261128
Reason: condition.RolloutControlledByExternalControllerReason,
11271129
Message: "Rollout is controlled by an external controller and no resource snapshot name is observed across clusters, probably rollout has not started yet",
@@ -1163,7 +1165,7 @@ func (r *Reconciler) determineRolloutStateForPlacementWithExternalRolloutStrateg
11631165
klog.V(2).InfoS("Placement has External rollout strategy and some cluster is in RolloutStarted Unknown state, set RolloutStarted condition to Unknown",
11641166
"clusterName", allRPS[i].ClusterName, "observedResourceIndex", observedResourceIndex, "placement", klog.KObj(placementObj))
11651167
placementObj.SetConditions(metav1.Condition{
1166-
Type: string(fleetv1beta1.ClusterResourcePlacementRolloutStartedConditionType),
1168+
Type: getPlacementRolloutStartedConditionType(placementObj),
11671169
Status: metav1.ConditionUnknown,
11681170
Reason: condition.RolloutControlledByExternalControllerReason,
11691171
Message: fmt.Sprintf("Rollout is controlled by an external controller and cluster %s is in RolloutStarted Unknown state", allRPS[i].ClusterName),
@@ -1179,6 +1181,28 @@ func (r *Reconciler) determineRolloutStateForPlacementWithExternalRolloutStrateg
11791181
return false, nil
11801182
}
11811183

1184+
// TODO: determine the actual condition type for RP
1185+
// getPlacementScheduledConditionType returns the appropriate scheduled condition type based on the placement type.
1186+
func getPlacementScheduledConditionType(placementObj fleetv1beta1.PlacementObj) string {
1187+
if placementObj.GetNamespace() == "" {
1188+
// Cluster-scoped placement
1189+
return string(fleetv1beta1.ClusterResourcePlacementScheduledConditionType)
1190+
}
1191+
// Namespace-scoped placement
1192+
return string(fleetv1beta1.ClusterResourcePlacementScheduledConditionType)
1193+
}
1194+
1195+
// TODO: determine the actual condition type for RP
1196+
// getPlacementRolloutStartedConditionType returns the appropriate rollout started condition type based on the placement type.
1197+
func getPlacementRolloutStartedConditionType(placementObj fleetv1beta1.PlacementObj) string {
1198+
if placementObj.GetNamespace() == "" {
1199+
// Cluster-scoped placement
1200+
return string(fleetv1beta1.ClusterResourcePlacementRolloutStartedConditionType)
1201+
}
1202+
// Namespace-scoped placement
1203+
return string(fleetv1beta1.ClusterResourcePlacementRolloutStartedConditionType)
1204+
}
1205+
11821206
func buildScheduledCondition(placementObj fleetv1beta1.PlacementObj, latestSchedulingPolicySnapshot fleetv1beta1.PolicySnapshotObj) metav1.Condition {
11831207
scheduledCondition := latestSchedulingPolicySnapshot.GetCondition(string(fleetv1beta1.PolicySnapshotScheduled))
11841208

@@ -1191,15 +1215,15 @@ func buildScheduledCondition(placementObj fleetv1beta1.PlacementObj, latestSched
11911215
scheduledCondition.Status == metav1.ConditionUnknown {
11921216
return metav1.Condition{
11931217
Status: metav1.ConditionUnknown,
1194-
Type: string(fleetv1beta1.ClusterResourcePlacementScheduledConditionType),
1218+
Type: getPlacementScheduledConditionType(placementObj),
11951219
Reason: condition.SchedulingUnknownReason,
11961220
Message: "Scheduling has not completed",
11971221
ObservedGeneration: placementObj.GetGeneration(),
11981222
}
11991223
}
12001224
return metav1.Condition{
12011225
Status: scheduledCondition.Status,
1202-
Type: string(fleetv1beta1.ClusterResourcePlacementScheduledConditionType),
1226+
Type: getPlacementScheduledConditionType(placementObj),
12031227
Reason: scheduledCondition.Reason,
12041228
Message: scheduledCondition.Message,
12051229
ObservedGeneration: placementObj.GetGeneration(),

pkg/controllers/clusterresourceplacement/placement_status_test.go

Lines changed: 119 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -962,7 +962,6 @@ func TestSetPlacementStatus(t *testing.T) {
962962
},
963963
},
964964
},
965-
// TODO special handling when selected cluster is 0
966965
{
967966
name: "the placement scheduling succeeded when numberOfClusters is 0",
968967
policy: &fleetv1beta1.PlacementPolicy{
@@ -1039,7 +1038,7 @@ func TestSetPlacementStatus(t *testing.T) {
10391038
},
10401039
},
10411040
},
1042-
want: false,
1041+
want: true,
10431042
wantStatus: &fleetv1beta1.PlacementStatus{
10441043
SelectedResources: selectedResources,
10451044
ObservedResourceIndex: "0",
@@ -1055,6 +1054,124 @@ func TestSetPlacementStatus(t *testing.T) {
10551054
PlacementStatuses: []fleetv1beta1.ResourcePlacementStatus{},
10561055
},
10571056
},
1057+
1058+
{
1059+
name: "the placement scheduling succeeded when numberOfClusters is 0 but user actually wants to select some",
1060+
policy: &fleetv1beta1.PlacementPolicy{
1061+
PlacementType: fleetv1beta1.PickNPlacementType,
1062+
NumberOfClusters: ptr.To(int32(3)),
1063+
},
1064+
latestPolicySnapshot: &fleetv1beta1.ClusterSchedulingPolicySnapshot{
1065+
ObjectMeta: metav1.ObjectMeta{
1066+
Name: fmt.Sprintf(fleetv1beta1.PolicySnapshotNameFmt, testCRPName, 0),
1067+
Labels: map[string]string{
1068+
fleetv1beta1.PolicyIndexLabel: "0",
1069+
fleetv1beta1.IsLatestSnapshotLabel: "true",
1070+
fleetv1beta1.PlacementTrackingLabel: testCRPName,
1071+
},
1072+
OwnerReferences: []metav1.OwnerReference{
1073+
{
1074+
Name: testCRPName,
1075+
BlockOwnerDeletion: ptr.To(true),
1076+
Controller: ptr.To(true),
1077+
APIVersion: fleetAPIVersion,
1078+
Kind: "ClusterResourcePlacement",
1079+
},
1080+
},
1081+
Annotations: map[string]string{
1082+
fleetv1beta1.NumberOfClustersAnnotation: strconv.Itoa(0),
1083+
},
1084+
Generation: 1,
1085+
},
1086+
Status: fleetv1beta1.SchedulingPolicySnapshotStatus{
1087+
ObservedCRPGeneration: crpGeneration,
1088+
Conditions: []metav1.Condition{
1089+
{
1090+
Status: metav1.ConditionFalse,
1091+
Type: string(fleetv1beta1.PolicySnapshotScheduled),
1092+
Reason: "Scheduled not met",
1093+
Message: "message",
1094+
ObservedGeneration: 1,
1095+
},
1096+
},
1097+
ClusterDecisions: []fleetv1beta1.ClusterDecision{
1098+
{
1099+
ClusterName: "member-1",
1100+
Selected: false,
1101+
Reason: "filtered",
1102+
},
1103+
{
1104+
ClusterName: "member-2",
1105+
Selected: false,
1106+
Reason: "filtered",
1107+
},
1108+
},
1109+
},
1110+
},
1111+
latestResourceSnapshot: &fleetv1beta1.ClusterResourceSnapshot{
1112+
ObjectMeta: metav1.ObjectMeta{
1113+
Name: fmt.Sprintf(fleetv1beta1.ResourceSnapshotNameFmt, testCRPName, 0),
1114+
Labels: map[string]string{
1115+
fleetv1beta1.ResourceIndexLabel: "0",
1116+
fleetv1beta1.PlacementTrackingLabel: testCRPName,
1117+
fleetv1beta1.IsLatestSnapshotLabel: "true",
1118+
},
1119+
OwnerReferences: []metav1.OwnerReference{
1120+
{
1121+
Name: testCRPName,
1122+
BlockOwnerDeletion: ptr.To(true),
1123+
Controller: ptr.To(true),
1124+
APIVersion: fleetAPIVersion,
1125+
Kind: "ClusterResourcePlacement",
1126+
},
1127+
},
1128+
Annotations: map[string]string{
1129+
fleetv1beta1.ResourceGroupHashAnnotation: "hash",
1130+
fleetv1beta1.NumberOfResourceSnapshotsAnnotation: "0",
1131+
},
1132+
},
1133+
},
1134+
want: false,
1135+
wantStatus: &fleetv1beta1.PlacementStatus{
1136+
SelectedResources: selectedResources,
1137+
ObservedResourceIndex: "0",
1138+
Conditions: []metav1.Condition{
1139+
{
1140+
Status: metav1.ConditionFalse,
1141+
Type: string(fleetv1beta1.ClusterResourcePlacementScheduledConditionType),
1142+
Reason: "Scheduled not met",
1143+
ObservedGeneration: crpGeneration,
1144+
LastTransitionTime: metav1.NewTime(currentTime),
1145+
},
1146+
},
1147+
PlacementStatuses: []fleetv1beta1.ResourcePlacementStatus{
1148+
{
1149+
Conditions: []metav1.Condition{
1150+
{
1151+
Status: metav1.ConditionFalse,
1152+
Type: string(fleetv1beta1.ResourceScheduledConditionType),
1153+
Reason: condition.ResourceScheduleFailedReason,
1154+
ObservedGeneration: crpGeneration,
1155+
LastTransitionTime: metav1.NewTime(currentTime),
1156+
Message: "filtered",
1157+
},
1158+
},
1159+
},
1160+
{
1161+
Conditions: []metav1.Condition{
1162+
{
1163+
Status: metav1.ConditionFalse,
1164+
Type: string(fleetv1beta1.ResourceScheduledConditionType),
1165+
Reason: condition.ResourceScheduleFailedReason,
1166+
ObservedGeneration: crpGeneration,
1167+
LastTransitionTime: metav1.NewTime(currentTime),
1168+
Message: "filtered",
1169+
},
1170+
},
1171+
},
1172+
},
1173+
},
1174+
},
10581175
{
10591176
name: "the placement is completed with clusterResourceBindings and works",
10601177
policy: &fleetv1beta1.PlacementPolicy{

pkg/controllers/rollout/controller.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -386,7 +386,6 @@ func (r *Reconciler) pickBindingsToRoll(
386386
bindingSpec := binding.GetBindingSpec()
387387
switch bindingSpec.State {
388388
case placementv1beta1.BindingStateUnscheduled:
389-
// Use updated interface-based bindingutils functions
390389
if bindingutils.HasBindingFailed(binding) {
391390
klog.V(2).InfoS("Found a failed to be ready unscheduled binding", "placement", placementKObj, "binding", bindingKObj)
392391
} else if !bindingutils.IsBindingDiffReported(binding) {
@@ -501,6 +500,7 @@ func determineBindingsToUpdate(
501500
readyBindings, canBeReadyBindings, canBeUnavailableBindings []placementv1beta1.BindingObj,
502501
) ([]toBeUpdatedBinding, []toBeUpdatedBinding) {
503502
toBeUpdatedBindingList := make([]toBeUpdatedBinding, 0)
503+
// TODO: Fix the bug that we don't shrink to zero when there are bindings that are not
504504
// calculate the max number of bindings that can be unavailable according to user specified maxUnavailable
505505
maxNumberToRemove := calculateMaxToRemove(placementObj, targetNumber, readyBindings, canBeUnavailableBindings)
506506
// we can still update the bindings that are failed to apply already regardless of the maxNumberToRemove

pkg/scheduler/framework/framework.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,7 @@ var removeFinalizerAndUpdate = func(ctx context.Context, hubClient client.Client
384384
controllerutil.RemoveFinalizer(binding, placementv1beta1.SchedulerBindingCleanupFinalizer)
385385
err := hubClient.Update(ctx, binding, &client.UpdateOptions{})
386386
if err == nil {
387-
klog.V(2).InfoS("Removed scheduler CRB cleanup finalizer", "binding", klog.KObj(binding))
387+
klog.V(2).InfoS("Removed scheduler binding cleanup finalizer", "binding", klog.KObj(binding))
388388
}
389389
return err
390390
}

test/e2e/placement_pickn_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -492,7 +492,7 @@ var _ = Describe("placing resources using a CRP of PickN placement", func() {
492492
})
493493
})
494494

495-
Context("downscaling to zero", Ordered, func() {
495+
FContext("downscaling to zero", Ordered, func() {
496496
crpName := fmt.Sprintf(crpNameTemplate, GinkgoParallelProcess())
497497

498498
BeforeAll(func() {

0 commit comments

Comments
 (0)