Skip to content

Commit b9a85d4

Browse files
committed
fix the issue that the binding's suspension persists when the policy deletes the suspension configuration
Signed-off-by: zhzhuang-zju <[email protected]>
1 parent aa0afaf commit b9a85d4

File tree

4 files changed

+134
-27
lines changed

4 files changed

+134
-27
lines changed

pkg/detector/detector.go

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -478,12 +478,7 @@ func (d *ResourceDetector) ApplyPolicy(object *unstructured.Unstructured, object
478478
bindingCopy.Spec.ConflictResolution = binding.Spec.ConflictResolution
479479
bindingCopy.Spec.PreserveResourcesOnDeletion = binding.Spec.PreserveResourcesOnDeletion
480480
bindingCopy.Spec.SchedulePriority = binding.Spec.SchedulePriority
481-
if binding.Spec.Suspension != nil {
482-
if bindingCopy.Spec.Suspension == nil {
483-
bindingCopy.Spec.Suspension = &workv1alpha2.Suspension{}
484-
}
485-
bindingCopy.Spec.Suspension.Suspension = binding.Spec.Suspension.Suspension
486-
}
481+
bindingCopy.Spec.Suspension = util.MergePolicySuspension(bindingCopy.Spec.Suspension, policy.Spec.Suspension)
487482
excludeClusterPolicy(bindingCopy)
488483
return nil
489484
})
@@ -574,12 +569,7 @@ func (d *ResourceDetector) ApplyClusterPolicy(object *unstructured.Unstructured,
574569
bindingCopy.Spec.ConflictResolution = binding.Spec.ConflictResolution
575570
bindingCopy.Spec.PreserveResourcesOnDeletion = binding.Spec.PreserveResourcesOnDeletion
576571
bindingCopy.Spec.SchedulePriority = binding.Spec.SchedulePriority
577-
if binding.Spec.Suspension != nil {
578-
if bindingCopy.Spec.Suspension == nil {
579-
bindingCopy.Spec.Suspension = &workv1alpha2.Suspension{}
580-
}
581-
bindingCopy.Spec.Suspension.Suspension = binding.Spec.Suspension.Suspension
582-
}
572+
bindingCopy.Spec.Suspension = util.MergePolicySuspension(bindingCopy.Spec.Suspension, policy.Spec.Suspension)
583573
return nil
584574
})
585575
return err
@@ -627,12 +617,7 @@ func (d *ResourceDetector) ApplyClusterPolicy(object *unstructured.Unstructured,
627617
bindingCopy.Spec.Failover = binding.Spec.Failover
628618
bindingCopy.Spec.ConflictResolution = binding.Spec.ConflictResolution
629619
bindingCopy.Spec.PreserveResourcesOnDeletion = binding.Spec.PreserveResourcesOnDeletion
630-
if binding.Spec.Suspension != nil {
631-
if bindingCopy.Spec.Suspension == nil {
632-
bindingCopy.Spec.Suspension = &workv1alpha2.Suspension{}
633-
}
634-
bindingCopy.Spec.Suspension.Suspension = binding.Spec.Suspension.Suspension
635-
}
620+
bindingCopy.Spec.Suspension = util.MergePolicySuspension(bindingCopy.Spec.Suspension, policy.Spec.Suspension)
636621
return nil
637622
})
638623
return err

pkg/util/binding.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,3 +110,23 @@ func RescheduleRequired(rescheduleTriggeredAt, lastScheduledTime *metav1.Time) b
110110
}
111111
return rescheduleTriggeredAt.After(lastScheduledTime.Time)
112112
}
113+
114+
// MergePolicySuspension merges the suspension configuration from policy to binding suspension.
115+
func MergePolicySuspension(bindingSuspension *workv1alpha2.Suspension, policySuspension *policyv1alpha1.Suspension) *workv1alpha2.Suspension {
116+
if bindingSuspension == nil && policySuspension == nil {
117+
return nil
118+
}
119+
120+
if policySuspension != nil { // have to sync policy suspension to binding
121+
if bindingSuspension == nil {
122+
bindingSuspension = &workv1alpha2.Suspension{}
123+
}
124+
bindingSuspension.Suspension = *policySuspension
125+
} else { // have to clean suspension previous synced to binding if any
126+
bindingSuspension.Suspension = policyv1alpha1.Suspension{}
127+
if bindingSuspension.Scheduling == nil { // if the scheduling not set, no need to keep an empty struct
128+
bindingSuspension = nil
129+
}
130+
}
131+
return bindingSuspension
132+
}

pkg/util/binding_test.go

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323

2424
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2525
"k8s.io/apimachinery/pkg/util/sets"
26+
"k8s.io/utils/ptr"
2627

2728
policyv1alpha1 "github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1"
2829
workv1alpha2 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha2"
@@ -419,3 +420,87 @@ func TestRescheduleRequired(t *testing.T) {
419420
})
420421
}
421422
}
423+
424+
func TestMergePolicySuspension(t *testing.T) {
425+
tests := []struct {
426+
name string
427+
bindingSuspension *workv1alpha2.Suspension
428+
policySuspension *policyv1alpha1.Suspension
429+
want *workv1alpha2.Suspension
430+
}{
431+
{
432+
name: "both nil returns nil",
433+
bindingSuspension: nil,
434+
policySuspension: nil,
435+
want: nil,
436+
},
437+
{
438+
name: "binding suspension only preserves scheduling when policy suspension nil",
439+
bindingSuspension: &workv1alpha2.Suspension{
440+
Scheduling: ptr.To(true),
441+
},
442+
policySuspension: nil,
443+
want: &workv1alpha2.Suspension{
444+
Scheduling: ptr.To(true),
445+
},
446+
},
447+
{
448+
name: "binding suspension only preserves scheduling when policy suspension nil",
449+
bindingSuspension: &workv1alpha2.Suspension{
450+
Suspension: policyv1alpha1.Suspension{
451+
Dispatching: ptr.To(true),
452+
},
453+
Scheduling: ptr.To(true),
454+
},
455+
policySuspension: nil,
456+
want: &workv1alpha2.Suspension{
457+
Scheduling: ptr.To(true),
458+
},
459+
},
460+
{
461+
name: "if the scheduling not set and policy suspension nil, will return nil",
462+
bindingSuspension: &workv1alpha2.Suspension{
463+
Suspension: policyv1alpha1.Suspension{
464+
Dispatching: ptr.To(true),
465+
},
466+
},
467+
policySuspension: nil,
468+
want: nil,
469+
},
470+
{
471+
name: "policy suspension set and no existing binding creates new suspension from policy",
472+
bindingSuspension: nil,
473+
policySuspension: &policyv1alpha1.Suspension{
474+
Dispatching: ptr.To(true),
475+
},
476+
want: &workv1alpha2.Suspension{
477+
Suspension: policyv1alpha1.Suspension{
478+
Dispatching: ptr.To(true),
479+
},
480+
},
481+
},
482+
{
483+
name: "should merge policy suspension and binding suspension",
484+
bindingSuspension: &workv1alpha2.Suspension{
485+
Scheduling: ptr.To(true),
486+
},
487+
policySuspension: &policyv1alpha1.Suspension{
488+
Dispatching: ptr.To(true),
489+
},
490+
want: &workv1alpha2.Suspension{
491+
Suspension: policyv1alpha1.Suspension{
492+
Dispatching: ptr.To(true),
493+
},
494+
Scheduling: ptr.To(true),
495+
},
496+
},
497+
}
498+
for _, tt := range tests {
499+
t.Run(tt.name, func(t *testing.T) {
500+
got := MergePolicySuspension(tt.bindingSuspension, tt.policySuspension)
501+
if !reflect.DeepEqual(got, tt.want) {
502+
t.Errorf("UpdateBindingSuspension() got = %v, want %v", got, tt.want)
503+
}
504+
})
505+
}
506+
}

test/e2e/suites/base/propagationpolicy_test.go

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1161,7 +1161,7 @@ var _ = ginkgo.Describe("[AdvancedCase] PropagationPolicy testing", func() {
11611161
})
11621162
})
11631163

1164-
var _ = ginkgo.Describe("[Suspension] PropagationPolicy testing", func() {
1164+
var _ = ginkgo.Describe("Suspension: PropagationPolicy testing", func() {
11651165
var policy *policyv1alpha1.PropagationPolicy
11661166
var deployment *appsv1.Deployment
11671167
var targetMember string
@@ -1190,20 +1190,19 @@ var _ = ginkgo.Describe("[Suspension] PropagationPolicy testing", func() {
11901190
func(*appsv1.Deployment) bool {
11911191
return true
11921192
})
1193-
ginkgo.DeferCleanup(func() {
1194-
framework.RemovePropagationPolicy(karmadaClient, policy.Namespace, policy.Name)
1195-
framework.RemoveDeployment(kubeClient, deployment.Namespace, deployment.Name)
1196-
})
1197-
})
1198-
1199-
ginkgo.It("suspend the PP dispatching", func() {
12001193
ginkgo.By("update the pp suspension dispatching to true", func() {
12011194
policy.Spec.Suspension = &policyv1alpha1.Suspension{
12021195
Dispatching: ptr.To(true),
12031196
}
12041197
framework.UpdatePropagationPolicyWithSpec(karmadaClient, policy.Namespace, policy.Name, policy.Spec)
12051198
})
1199+
ginkgo.DeferCleanup(func() {
1200+
framework.RemovePropagationPolicy(karmadaClient, policy.Namespace, policy.Name)
1201+
framework.RemoveDeployment(kubeClient, deployment.Namespace, deployment.Name)
1202+
})
1203+
})
12061204

1205+
ginkgo.It("suspend the PP dispatching", func() {
12071206
ginkgo.By("check RB suspension spec", func() {
12081207
framework.WaitResourceBindingFitWith(karmadaClient, deployment.Namespace, names.GenerateBindingName(deployment.Kind, deployment.Name),
12091208
func(binding *workv1alpha2.ResourceBinding) bool {
@@ -1246,7 +1245,7 @@ var _ = ginkgo.Describe("[Suspension] PropagationPolicy testing", func() {
12461245
})
12471246
})
12481247

1249-
ginkgo.It("suspension resume", func() {
1248+
ginkgo.It("suspension resume by setting policy suspension to a empty structure", func() {
12501249
ginkgo.By("update deployment replicas", func() {
12511250
framework.UpdateDeploymentReplicas(kubeClient, deployment, updateDeploymentReplicas)
12521251
})
@@ -1263,4 +1262,22 @@ var _ = ginkgo.Describe("[Suspension] PropagationPolicy testing", func() {
12631262
})
12641263
})
12651264
})
1265+
1266+
ginkgo.It("suspension resume by setting policy suspension to nil", func() {
1267+
ginkgo.By("update deployment replicas", func() {
1268+
framework.UpdateDeploymentReplicas(kubeClient, deployment, updateDeploymentReplicas)
1269+
})
1270+
1271+
ginkgo.By("resume the propagationPolicy", func() {
1272+
policy.Spec.Suspension = nil
1273+
framework.UpdatePropagationPolicyWithSpec(karmadaClient, policy.Namespace, policy.Name, policy.Spec)
1274+
})
1275+
1276+
ginkgo.By("check deployment replicas", func() {
1277+
framework.WaitDeploymentPresentOnClusterFitWith(targetMember, deployment.Namespace, deployment.Name,
1278+
func(d *appsv1.Deployment) bool {
1279+
return *d.Spec.Replicas == updateDeploymentReplicas
1280+
})
1281+
})
1282+
})
12661283
})

0 commit comments

Comments
 (0)