Skip to content

Commit 64c29ce

Browse files
authored
feat: add webhook configuration for clusterResourcePlacementDisruptionBudget (#80)
1 parent 3b17212 commit 64c29ce

File tree

7 files changed

+549
-224
lines changed

7 files changed

+549
-224
lines changed

pkg/controllers/clusterresourceplacementeviction/controller_intergration_test.go

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -530,6 +530,177 @@ var _ = Describe("Test ClusterResourcePlacementEviction Controller", func() {
530530
checkEvictionCompleteMetric(customRegistry, "false", "true")
531531
})
532532
})
533+
534+
Context("Eviction with PickAll CRP and Invalid ClusterResourcePlacementBudget", func() {
535+
// This context is used to test the scenarios where the ClusterResourcePlacementDisruptionBudget is misconfigured.
536+
evictionName = fmt.Sprintf(evictionNameTemplate, GinkgoParallelProcess())
537+
crpName := fmt.Sprintf(crpNameTemplate, GinkgoParallelProcess())
538+
crbName := fmt.Sprintf(crbNameTemplate, GinkgoParallelProcess())
539+
540+
BeforeEach(func() {
541+
// Create the CRP.
542+
By("Create ClusterResourcePlacement", func() {
543+
crp := buildTestPickAllCRP(crpName)
544+
crp.Spec.ResourceSelectors = []placementv1beta1.ClusterResourceSelector{
545+
{
546+
Group: "",
547+
Kind: "Namespace",
548+
Version: "v1",
549+
Name: "test-ns",
550+
},
551+
}
552+
Expect(k8sClient.Create(ctx, &crp)).Should(Succeed())
553+
// ensure CRP exists.
554+
Eventually(func() error {
555+
return k8sClient.Get(ctx, types.NamespacedName{Name: crp.Name}, &crp)
556+
}, eventuallyDuration, eventuallyInterval).Should(Succeed())
557+
})
558+
559+
By("Create ClusterResourceBinding", func() {
560+
// Create CRB.
561+
crb := placementv1beta1.ClusterResourceBinding{
562+
ObjectMeta: metav1.ObjectMeta{
563+
Name: crbName,
564+
Labels: map[string]string{placementv1beta1.CRPTrackingLabel: crpName},
565+
},
566+
Spec: placementv1beta1.ResourceBindingSpec{
567+
State: placementv1beta1.BindingStateBound,
568+
ResourceSnapshotName: "test-resource-snapshot",
569+
SchedulingPolicySnapshotName: "test-scheduling-policy-snapshot",
570+
TargetCluster: "test-cluster",
571+
},
572+
}
573+
Expect(k8sClient.Create(ctx, &crb)).Should(Succeed())
574+
// ensure CRB exists.
575+
Eventually(func() error {
576+
return k8sClient.Get(ctx, types.NamespacedName{Name: crb.Name}, &crb)
577+
}, eventuallyDuration, eventuallyInterval).Should(Succeed())
578+
})
579+
580+
By("Create ClusterResourcePlacementEviction", func() {
581+
eviction := buildTestEviction(evictionName, crpName, "test-cluster")
582+
Expect(k8sClient.Create(ctx, eviction)).Should(Succeed())
583+
})
584+
})
585+
586+
AfterEach(func() {
587+
ensureCRPDBRemoved(crpName)
588+
ensureCRBRemoved(crbName)
589+
ensureEvictionRemoved(evictionName)
590+
ensureCRPRemoved(crpName)
591+
})
592+
593+
It("Eviction Blocked - PickAll CRP, PDB with MaxUnavailable set as Percentage, eviction denied due to misconfigured PDB", func() {
594+
By("Create cluster resource placement disruption budget to block eviction", func() {
595+
crpdb := placementv1beta1.ClusterResourcePlacementDisruptionBudget{
596+
ObjectMeta: metav1.ObjectMeta{
597+
Name: crpName,
598+
},
599+
Spec: placementv1beta1.PlacementDisruptionBudgetSpec{
600+
MaxUnavailable: &intstr.IntOrString{
601+
Type: intstr.String,
602+
StrVal: "50%",
603+
},
604+
},
605+
}
606+
Expect(k8sClient.Create(ctx, &crpdb)).To(Succeed(), "Failed to create CRP Disruption Budget %s", crpName)
607+
})
608+
609+
By("should update cluster resource placement eviction status as expected", func() {
610+
crpEvictionStatusUpdatedActual := testutilseviction.StatusUpdatedActual(
611+
ctx, k8sClient, evictionName,
612+
&testutilseviction.IsValidEviction{IsValid: true, Msg: condition.EvictionValidMessage},
613+
&testutilseviction.IsExecutedEviction{IsExecuted: false, Msg: condition.EvictionBlockedMisconfiguredPDBSpecifiedMessage})
614+
Eventually(crpEvictionStatusUpdatedActual, eventuallyDuration, eventuallyInterval).Should(Succeed(), "Failed to update cluster resource placement eviction status as expected")
615+
})
616+
617+
By("Ensure eviction was not successful", func() {
618+
var crb placementv1beta1.ClusterResourceBinding
619+
// check to see CRB was not deleted.
620+
Consistently(func() bool {
621+
return !k8serrors.IsNotFound(k8sClient.Get(ctx, types.NamespacedName{Name: crbName}, &crb))
622+
}, consistentlyDuration, consistentlyInterval).Should(BeTrue())
623+
})
624+
625+
By("Ensure eviction complete metric was emitted", func() {
626+
checkEvictionCompleteMetric(customRegistry, "true", "true")
627+
})
628+
})
629+
630+
It("Eviction Blocked - PickAll CRP, PDB with MaxUnavailable set as Integer, eviction denied due to misconfigured PDB", func() {
631+
By("Create cluster resource placement disruption budget to block eviction", func() {
632+
crpdb := placementv1beta1.ClusterResourcePlacementDisruptionBudget{
633+
ObjectMeta: metav1.ObjectMeta{
634+
Name: crpName,
635+
},
636+
Spec: placementv1beta1.PlacementDisruptionBudgetSpec{
637+
MaxUnavailable: &intstr.IntOrString{
638+
Type: intstr.Int,
639+
IntVal: 1,
640+
},
641+
},
642+
}
643+
Expect(k8sClient.Create(ctx, &crpdb)).To(Succeed(), "Failed to create CRP Disruption Budget %s", crpName)
644+
})
645+
646+
By("should update cluster resource placement eviction status as expected", func() {
647+
crpEvictionStatusUpdatedActual := testutilseviction.StatusUpdatedActual(
648+
ctx, k8sClient, evictionName,
649+
&testutilseviction.IsValidEviction{IsValid: true, Msg: condition.EvictionValidMessage},
650+
&testutilseviction.IsExecutedEviction{IsExecuted: false, Msg: condition.EvictionBlockedMisconfiguredPDBSpecifiedMessage})
651+
Eventually(crpEvictionStatusUpdatedActual, eventuallyDuration, eventuallyInterval).Should(Succeed(), "Failed to update cluster resource placement eviction status as expected")
652+
})
653+
654+
By("Ensure eviction was not successful", func() {
655+
var crb placementv1beta1.ClusterResourceBinding
656+
// check to see CRB was not deleted.
657+
Consistently(func() bool {
658+
return !k8serrors.IsNotFound(k8sClient.Get(ctx, types.NamespacedName{Name: crbName}, &crb))
659+
}, consistentlyDuration, consistentlyInterval).Should(BeTrue())
660+
})
661+
662+
By("Ensure eviction complete metric was emitted", func() {
663+
checkEvictionCompleteMetric(customRegistry, "true", "true")
664+
})
665+
})
666+
667+
It("Eviction Blocked - PickAll CRP, PDB with MinAvailable set as Percentage, eviction denied due to misconfigured PDB", func() {
668+
By("Create cluster resource placement disruption budget to block eviction", func() {
669+
crpdb := placementv1beta1.ClusterResourcePlacementDisruptionBudget{
670+
ObjectMeta: metav1.ObjectMeta{
671+
Name: crpName,
672+
},
673+
Spec: placementv1beta1.PlacementDisruptionBudgetSpec{
674+
MinAvailable: &intstr.IntOrString{
675+
Type: intstr.String,
676+
StrVal: "100%",
677+
},
678+
},
679+
}
680+
Expect(k8sClient.Create(ctx, &crpdb)).To(Succeed(), "Failed to create CRP Disruption Budget %s", crpName)
681+
})
682+
683+
By("should update cluster resource placement eviction status as expected", func() {
684+
crpEvictionStatusUpdatedActual := testutilseviction.StatusUpdatedActual(
685+
ctx, k8sClient, evictionName,
686+
&testutilseviction.IsValidEviction{IsValid: true, Msg: condition.EvictionValidMessage},
687+
&testutilseviction.IsExecutedEviction{IsExecuted: false, Msg: condition.EvictionBlockedMisconfiguredPDBSpecifiedMessage})
688+
Eventually(crpEvictionStatusUpdatedActual, eventuallyDuration, eventuallyInterval).Should(Succeed(), "Failed to update cluster resource placement eviction status as expected")
689+
})
690+
691+
By("Ensure eviction was not successful", func() {
692+
var crb placementv1beta1.ClusterResourceBinding
693+
// check to see CRB was not deleted.
694+
Consistently(func() bool {
695+
return !k8serrors.IsNotFound(k8sClient.Get(ctx, types.NamespacedName{Name: crbName}, &crb))
696+
}, consistentlyDuration, consistentlyInterval).Should(BeTrue())
697+
})
698+
699+
By("Ensure eviction complete metric was emitted", func() {
700+
checkEvictionCompleteMetric(customRegistry, "true", "true")
701+
})
702+
})
703+
})
533704
})
534705

535706
func buildTestPickNCRP(crpName string, clusterCount int32) placementv1beta1.ClusterResourcePlacement {

pkg/webhook/add_handler.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package webhook
33
import (
44
"github.com/kubefleet-dev/kubefleet/pkg/webhook/clusterresourceoverride"
55
"github.com/kubefleet-dev/kubefleet/pkg/webhook/clusterresourceplacement"
6+
"github.com/kubefleet-dev/kubefleet/pkg/webhook/clusterresourceplacementdisruptionbudget"
67
"github.com/kubefleet-dev/kubefleet/pkg/webhook/clusterresourceplacementeviction"
78
"github.com/kubefleet-dev/kubefleet/pkg/webhook/fleetresourcehandler"
89
"github.com/kubefleet-dev/kubefleet/pkg/webhook/membercluster"
@@ -23,4 +24,5 @@ func init() {
2324
AddToManagerFuncs = append(AddToManagerFuncs, clusterresourceoverride.Add)
2425
AddToManagerFuncs = append(AddToManagerFuncs, resourceoverride.Add)
2526
AddToManagerFuncs = append(AddToManagerFuncs, clusterresourceplacementeviction.Add)
27+
AddToManagerFuncs = append(AddToManagerFuncs, clusterresourceplacementdisruptionbudget.Add)
2628
}

0 commit comments

Comments
 (0)