Skip to content

Commit 587e327

Browse files
author
Ryan Zhang
committed
temp
Signed-off-by: Ryan Zhang <[email protected]>
1 parent 778c9ef commit 587e327

File tree

9 files changed

+768
-221
lines changed

9 files changed

+768
-221
lines changed

.github/.copilot/breadcrumbs/2025-06-24-0900-rollout-controller-binding-interface-refactor.md

Lines changed: 444 additions & 0 deletions
Large diffs are not rendered by default.

pkg/controllers/clusterresourceplacementeviction/controller.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ func (r *Reconciler) validateEviction(ctx context.Context, eviction *placementv1
118118
}
119119

120120
// set default values for CRP.
121-
defaulter.SetDefaultsClusterResourcePlacement(&crp)
121+
defaulter.SetDefaultsPlacement(&crp)
122122

123123
if crp.DeletionTimestamp != nil {
124124
klog.V(2).InfoS(condition.EvictionInvalidDeletingCRPMessage, "clusterResourcePlacementEviction", eviction.Name, "clusterResourcePlacement", eviction.Spec.PlacementName)

pkg/controllers/clusterresourceplacementeviction/controller_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ func TestValidateEviction(t *testing.T) {
258258
// Since default values are applied to the affected CRP in the eviction controller; the
259259
// the same must be done on the expected result as well.
260260
if tc.wantValidationResult.crp != nil {
261-
defaulter.SetDefaultsClusterResourcePlacement(tc.wantValidationResult.crp)
261+
defaulter.SetDefaultsPlacement(tc.wantValidationResult.crp)
262262
}
263263

264264
if diff := cmp.Diff(tc.wantValidationResult, gotValidationResult, validationResultCmpOptions...); diff != "" {

pkg/controllers/rollout/controller.go

Lines changed: 263 additions & 182 deletions
Large diffs are not rendered by default.

pkg/controllers/rollout/controller_test.go

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ func TestWaitForResourcesToCleanUp(t *testing.T) {
264264
for name, tt := range tests {
265265
crp := &fleetv1beta1.ClusterResourcePlacement{}
266266
t.Run(name, func(t *testing.T) {
267-
gotWait, err := waitForResourcesToCleanUp(tt.allBindings, crp)
267+
gotWait, err := waitForResourcesToCleanUp(controller.ConvertCRBArrayToBindingObjs(tt.allBindings), crp)
268268
if (err != nil) != tt.wantErr {
269269
t.Errorf("waitForResourcesToCleanUp test `%s` error = %v, wantErr %v", name, err, tt.wantErr)
270270
return
@@ -618,7 +618,7 @@ func TestUpdateBindings(t *testing.T) {
618618
}
619619
if tt.desiredBindingsSpec != nil {
620620
inputs[i].desiredBinding = tt.bindings[i].DeepCopy()
621-
inputs[i].desiredBinding.Spec = tt.desiredBindingsSpec[i]
621+
inputs[i].desiredBinding.SetBindingSpec(tt.desiredBindingsSpec[i])
622622
}
623623
}
624624
err := r.updateBindings(ctx, inputs)
@@ -2172,7 +2172,7 @@ func TestPickBindingsToRoll(t *testing.T) {
21722172
Name: tt.latestResourceSnapshotName,
21732173
},
21742174
}
2175-
gotUpdatedBindings, gotStaleUnselectedBindings, gotUpToDateBoundBindings, gotNeedRoll, gotWaitTime, err := r.pickBindingsToRoll(context.Background(), tt.allBindings, resourceSnapshot, tt.crp, tt.matchedCROs, tt.matchedROs)
2175+
gotUpdatedBindings, gotStaleUnselectedBindings, gotUpToDateBoundBindings, gotNeedRoll, gotWaitTime, err := r.pickBindingsToRoll(context.Background(), controller.ConvertCRBArrayToBindingObjs(tt.allBindings), resourceSnapshot, tt.crp, tt.matchedCROs, tt.matchedROs)
21762176
if (err != nil) != (tt.wantErr != nil) || err != nil && !errors.Is(err, tt.wantErr) {
21772177
t.Fatalf("pickBindingsToRoll() error = %v, wantErr %v", err, tt.wantErr)
21782178
}
@@ -2183,21 +2183,23 @@ func TestPickBindingsToRoll(t *testing.T) {
21832183
wantTobeUpdatedBindings := make([]toBeUpdatedBinding, len(tt.wantTobeUpdatedBindings))
21842184
for i, index := range tt.wantTobeUpdatedBindings {
21852185
// Unscheduled bindings are only removed in a single rollout cycle.
2186-
if tt.allBindings[index].Spec.State != fleetv1beta1.BindingStateUnscheduled {
2186+
bindingSpec := tt.allBindings[index].GetBindingSpec()
2187+
if bindingSpec.State != fleetv1beta1.BindingStateUnscheduled {
21872188
wantTobeUpdatedBindings[i].currentBinding = tt.allBindings[index]
21882189
wantTobeUpdatedBindings[i].desiredBinding = tt.allBindings[index].DeepCopy()
2189-
wantTobeUpdatedBindings[i].desiredBinding.Spec = tt.wantDesiredBindingsSpec[index]
2190+
wantTobeUpdatedBindings[i].desiredBinding.SetBindingSpec(tt.wantDesiredBindingsSpec[index])
21902191
} else {
21912192
wantTobeUpdatedBindings[i].currentBinding = tt.allBindings[index]
21922193
}
21932194
}
21942195
wantStaleUnselectedBindings := make([]toBeUpdatedBinding, len(tt.wantStaleUnselectedBindings))
21952196
for i, index := range tt.wantStaleUnselectedBindings {
21962197
// Unscheduled bindings are only removed in a single rollout cycle.
2197-
if tt.allBindings[index].Spec.State != fleetv1beta1.BindingStateUnscheduled {
2198+
bindingSpec := tt.allBindings[index].GetBindingSpec()
2199+
if bindingSpec.State != fleetv1beta1.BindingStateUnscheduled {
21982200
wantStaleUnselectedBindings[i].currentBinding = tt.allBindings[index]
21992201
wantStaleUnselectedBindings[i].desiredBinding = tt.allBindings[index].DeepCopy()
2200-
wantStaleUnselectedBindings[i].desiredBinding.Spec = tt.wantDesiredBindingsSpec[index]
2202+
wantStaleUnselectedBindings[i].desiredBinding.SetBindingSpec(tt.wantDesiredBindingsSpec[index])
22012203
} else {
22022204
wantStaleUnselectedBindings[i].currentBinding = tt.allBindings[index]
22032205
}
@@ -2892,7 +2894,7 @@ func TestCheckAndUpdateStaleBindingsStatus(t *testing.T) {
28922894
Client: fakeClient,
28932895
}
28942896
ctx := context.Background()
2895-
if err := r.checkAndUpdateStaleBindingsStatus(ctx, tt.bindings); err != nil {
2897+
if err := r.checkAndUpdateStaleBindingsStatus(ctx, controller.ConvertCRBArrayToBindingObjs(tt.bindings)); err != nil {
28962898
t.Fatalf("checkAndUpdateStaleBindingsStatus() got error %v, want no err", err)
28972899
}
28982900
bindingList := &fleetv1beta1.ClusterResourceBindingList{}
@@ -3168,7 +3170,7 @@ func TestProcessApplyStrategyUpdates(t *testing.T) {
31683170
Client: fakeClient,
31693171
}
31703172

3171-
applyStrategyUpdated, err := r.processApplyStrategyUpdates(ctx, tc.crp, tc.allBindings)
3173+
applyStrategyUpdated, err := r.processApplyStrategyUpdates(ctx, tc.crp, controller.ConvertCRBArrayToBindingObjs(tc.allBindings))
31723174
if err != nil {
31733175
t.Errorf("processApplyStrategyUpdates() error = %v, want no error", err)
31743176
}

pkg/utils/binding/binding.go

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,26 +17,33 @@ limitations under the License.
1717
package binding
1818

1919
import (
20+
"k8s.io/apimachinery/pkg/api/meta"
2021
"k8s.io/klog/v2"
2122

2223
placementv1beta1 "github.com/kubefleet-dev/kubefleet/apis/placement/v1beta1"
2324
"github.com/kubefleet-dev/kubefleet/pkg/utils/condition"
2425
)
2526

26-
// HasBindingFailed checks if ClusterResourceBinding has failed based on its conditions.
27-
func HasBindingFailed(binding *placementv1beta1.ClusterResourceBinding) bool {
27+
// HasBindingFailed checks if BindingObj has failed based on its conditions.
28+
func HasBindingFailed(binding placementv1beta1.BindingObj) bool {
29+
conditions := binding.GetBindingStatus().Conditions
30+
generation := binding.GetGeneration()
31+
2832
for i := condition.OverriddenCondition; i <= condition.AvailableCondition; i++ {
29-
if condition.IsConditionStatusFalse(binding.GetCondition(string(i.ResourceBindingConditionType())), binding.Generation) {
33+
cond := meta.FindStatusCondition(conditions, string(i.ResourceBindingConditionType()))
34+
if condition.IsConditionStatusFalse(cond, generation) {
3035
// TODO: parse the reason of the condition to see if the failure is recoverable/retriable or not
31-
klog.V(2).Infof("binding %s has condition %s with status false", binding.Name, string(i.ResourceBindingConditionType()))
36+
klog.V(2).Infof("binding %s has condition %s with status false", binding.GetName(), string(i.ResourceBindingConditionType()))
3237
return true
3338
}
3439
}
3540
return false
3641
}
3742

3843
// IsBindingDiffReported checks if the binding is in diffReported state.
39-
func IsBindingDiffReported(binding *placementv1beta1.ClusterResourceBinding) bool {
40-
diffReportCondition := binding.GetCondition(string(placementv1beta1.ResourceBindingDiffReported))
41-
return diffReportCondition != nil && diffReportCondition.ObservedGeneration == binding.Generation
44+
func IsBindingDiffReported(binding placementv1beta1.BindingObj) bool {
45+
conditions := binding.GetBindingStatus().Conditions
46+
generation := binding.GetGeneration()
47+
diffReportCondition := meta.FindStatusCondition(conditions, string(placementv1beta1.ResourceBindingDiffReported))
48+
return diffReportCondition != nil && diffReportCondition.ObservedGeneration == generation
4249
}

pkg/utils/controller/placement_resolver.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"strings"
2323

2424
"k8s.io/apimachinery/pkg/types"
25+
ctrl "sigs.k8s.io/controller-runtime"
2526
"sigs.k8s.io/controller-runtime/pkg/client"
2627

2728
fleetv1beta1 "github.com/kubefleet-dev/kubefleet/apis/placement/v1beta1"
@@ -76,6 +77,17 @@ func GetPlacementKeyFromObj(obj fleetv1beta1.PlacementObj) queue.PlacementKey {
7677
}
7778
}
7879

80+
// GetPlacementKeyFromObj generates a PlacementKey from a placement object.
81+
func GetPlacementKeyFromRequest(req ctrl.Request) queue.PlacementKey {
82+
if req.Namespace == "" {
83+
// Cluster-scoped placement
84+
return queue.PlacementKey(req.Name)
85+
} else {
86+
// Namespaced placement
87+
return queue.PlacementKey(req.Namespace + namespaceSeparator + req.Name)
88+
}
89+
}
90+
7991
// ExtractNamespaceNameFromKey resolves a PlacementKey to a (namespace, name) tuple of the placement object.
8092
func ExtractNamespaceNameFromKey(placementKey queue.PlacementKey) (string, string, error) {
8193
keyStr := string(placementKey)

pkg/utils/defaulter/clusterresourceplacement.go

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -42,34 +42,35 @@ const (
4242
DefaultRevisionHistoryLimitValue = 10
4343
)
4444

45-
// SetDefaultsClusterResourcePlacement sets the default values for ClusterResourcePlacement.
46-
func SetDefaultsClusterResourcePlacement(obj *fleetv1beta1.ClusterResourcePlacement) {
47-
if obj.Spec.Policy == nil {
48-
obj.Spec.Policy = &fleetv1beta1.PlacementPolicy{
45+
// SetDefaultsPlacement sets the default values for placement.
46+
func SetDefaultsPlacement(obj fleetv1beta1.PlacementObj) {
47+
spec := obj.GetPlacementSpec()
48+
if spec.Policy == nil {
49+
spec.Policy = &fleetv1beta1.PlacementPolicy{
4950
PlacementType: fleetv1beta1.PickAllPlacementType,
5051
}
5152
}
5253

53-
if obj.Spec.Policy.TopologySpreadConstraints != nil {
54-
for i := range obj.Spec.Policy.TopologySpreadConstraints {
55-
if obj.Spec.Policy.TopologySpreadConstraints[i].MaxSkew == nil {
56-
obj.Spec.Policy.TopologySpreadConstraints[i].MaxSkew = ptr.To(int32(DefaultMaxSkewValue))
54+
if spec.Policy.TopologySpreadConstraints != nil {
55+
for i := range spec.Policy.TopologySpreadConstraints {
56+
if spec.Policy.TopologySpreadConstraints[i].MaxSkew == nil {
57+
spec.Policy.TopologySpreadConstraints[i].MaxSkew = ptr.To(int32(DefaultMaxSkewValue))
5758
}
58-
if obj.Spec.Policy.TopologySpreadConstraints[i].WhenUnsatisfiable == "" {
59-
obj.Spec.Policy.TopologySpreadConstraints[i].WhenUnsatisfiable = fleetv1beta1.DoNotSchedule
59+
if spec.Policy.TopologySpreadConstraints[i].WhenUnsatisfiable == "" {
60+
spec.Policy.TopologySpreadConstraints[i].WhenUnsatisfiable = fleetv1beta1.DoNotSchedule
6061
}
6162
}
6263
}
6364

64-
if obj.Spec.Policy.Tolerations != nil {
65-
for i := range obj.Spec.Policy.Tolerations {
66-
if obj.Spec.Policy.Tolerations[i].Operator == "" {
67-
obj.Spec.Policy.Tolerations[i].Operator = corev1.TolerationOpEqual
65+
if spec.Policy.Tolerations != nil {
66+
for i := range spec.Policy.Tolerations {
67+
if spec.Policy.Tolerations[i].Operator == "" {
68+
spec.Policy.Tolerations[i].Operator = corev1.TolerationOpEqual
6869
}
6970
}
7071
}
7172

72-
strategy := &obj.Spec.Strategy
73+
strategy := &spec.Strategy
7374
if strategy.Type == "" {
7475
strategy.Type = fleetv1beta1.RollingUpdateRolloutStrategyType
7576
}
@@ -88,13 +89,13 @@ func SetDefaultsClusterResourcePlacement(obj *fleetv1beta1.ClusterResourcePlacem
8889
}
8990
}
9091

91-
if obj.Spec.Strategy.ApplyStrategy == nil {
92-
obj.Spec.Strategy.ApplyStrategy = &fleetv1beta1.ApplyStrategy{}
92+
if spec.Strategy.ApplyStrategy == nil {
93+
spec.Strategy.ApplyStrategy = &fleetv1beta1.ApplyStrategy{}
9394
}
94-
SetDefaultsApplyStrategy(obj.Spec.Strategy.ApplyStrategy)
95+
SetDefaultsApplyStrategy(spec.Strategy.ApplyStrategy)
9596

96-
if obj.Spec.RevisionHistoryLimit == nil {
97-
obj.Spec.RevisionHistoryLimit = ptr.To(int32(DefaultRevisionHistoryLimitValue))
97+
if spec.RevisionHistoryLimit == nil {
98+
spec.RevisionHistoryLimit = ptr.To(int32(DefaultRevisionHistoryLimitValue))
9899
}
99100
}
100101

pkg/utils/defaulter/clusterresourceplacement_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ func TestSetDefaultsClusterResourcePlacement(t *testing.T) {
167167
}
168168
for name, tt := range tests {
169169
t.Run(name, func(t *testing.T) {
170-
SetDefaultsClusterResourcePlacement(tt.obj)
170+
SetDefaultsPlacement(tt.obj)
171171
if diff := cmp.Diff(tt.wantObj, tt.obj); diff != "" {
172172
t.Errorf("SetDefaultsClusterResourcePlacement() mismatch (-want +got):\n%s", diff)
173173
}

0 commit comments

Comments
 (0)