Add integration tests (#91)

Signed-off-by: zhujian <jiazhu@redhat.com>

Signed-off-by: zhujian <jiazhu@redhat.com>
This commit is contained in:
Jian Zhu
2022-11-29 14:14:16 +08:00
committed by GitHub
parent 5d33dd956c
commit 1483a0d2a4
9 changed files with 118 additions and 32 deletions

View File

@@ -81,7 +81,7 @@ func (s *Status) AsError() error {
return errors.New(s.Message())
}
// FailedPlugin returns the failed plugin name.
// Plugin returns the plugin name.
func (s *Status) Plugin() string {
return s.plugin
}

View File

@@ -239,7 +239,7 @@ func (s *pluginScheduler) Schedule(
// The final score is a sum of each prioritizer score * weight.
// A higher weight indicates that the prioritizer weights more in the cluster selection,
// while 0 weight indicate thats the prioritizer is disabled.
// while 0 weight indicate that the prioritizer is disabled.
for name, val := range score {
scoreSum[name] = scoreSum[name] + val*int64(weight)
}

View File

@@ -65,7 +65,7 @@ type schedulingController struct {
recorder kevents.EventRecorder
}
// NewDecisionSchedulingController return an instance of schedulingController
// NewSchedulingController return an instance of schedulingController
func NewSchedulingController(
clusterClient clusterclient.Interface,
clusterInformer clusterinformerv1.ManagedClusterInformer,

View File

@@ -15,7 +15,7 @@ const (
placementLabel = "cluster.open-cluster-management.io/placement"
description = `
Balance prioritizer balance the number of decisions among the clusters. The cluster
with the highest number of decison is given the lowest score, while the empty cluster is given
with the highest number of decision is given the lowest score, while the empty cluster is given
the highest score.
`
)

View File

@@ -29,13 +29,13 @@ const (
// Plugin is the parent type for all the scheduling plugins.
type Plugin interface {
Name() string
// Set is to set the placement for the current scheduling.
// Description of the plugin
Description() string
// RequeueAfter returns the requeue time interval of the placement
RequeueAfter(ctx context.Context, placement *clusterapiv1beta1.Placement) (PluginRequeueResult, *framework.Status)
}
// Fitler defines a filter plugin that filter unsatisfied cluster.
// Filter defines a filter plugin that filter unsatisfied cluster.
type Filter interface {
Plugin
@@ -44,7 +44,7 @@ type Filter interface {
}
// Prioritizer defines a prioritizer plugin that score each cluster. The score is normalized
// as a floating betwween 0 and 1.
// as a floating between 0 and 1.
type Prioritizer interface {
Plugin

View File

@@ -215,12 +215,16 @@ var _ = ginkgo.Describe("Placement", func() {
assertCreatingPlacement(placementName, noc(10), 5)
ginkgo.By("Reduce NOC of the placement")
placement, err := clusterClient.ClusterV1beta1().Placements(namespace).Get(context.Background(), placementName, metav1.GetOptions{})
gomega.Expect(err).ToNot(gomega.HaveOccurred())
noc := int32(6)
placement.Spec.NumberOfClusters = &noc
placement, err = clusterClient.ClusterV1beta1().Placements(namespace).Update(context.Background(), placement, metav1.UpdateOptions{})
gomega.Expect(err).ToNot(gomega.HaveOccurred())
gomega.Eventually(func() error {
placement, err := clusterClient.ClusterV1beta1().Placements(namespace).Get(context.Background(), placementName, metav1.GetOptions{})
if err != nil {
return err
}
noc := int32(6)
placement.Spec.NumberOfClusters = &noc
_, err = clusterClient.ClusterV1beta1().Placements(namespace).Update(context.Background(), placement, metav1.UpdateOptions{})
return err
}, eventuallyTimeout, eventuallyInterval).ShouldNot(gomega.HaveOccurred())
assertNumberOfDecisions(placementName, 5)
assertPlacementStatus(placementName, 5, false)
@@ -255,21 +259,25 @@ var _ = ginkgo.Describe("Placement", func() {
assertCreatingPlacement(placementName, nil, 1)
ginkgo.By("Add cluster predicate")
placement, err := clusterClient.ClusterV1beta1().Placements(namespace).Get(context.Background(), placementName, metav1.GetOptions{})
gomega.Expect(err).ToNot(gomega.HaveOccurred())
placement.Spec.Predicates = []clusterapiv1beta1.ClusterPredicate{
{
RequiredClusterSelector: clusterapiv1beta1.ClusterSelector{
LabelSelector: metav1.LabelSelector{
MatchLabels: map[string]string{
"a": "b",
gomega.Eventually(func() error {
placement, err := clusterClient.ClusterV1beta1().Placements(namespace).Get(context.Background(), placementName, metav1.GetOptions{})
if err != nil {
return err
}
placement.Spec.Predicates = []clusterapiv1beta1.ClusterPredicate{
{
RequiredClusterSelector: clusterapiv1beta1.ClusterSelector{
LabelSelector: metav1.LabelSelector{
MatchLabels: map[string]string{
"a": "b",
},
},
},
},
},
}
placement, err = clusterClient.ClusterV1beta1().Placements(namespace).Update(context.Background(), placement, metav1.UpdateOptions{})
gomega.Expect(err).ToNot(gomega.HaveOccurred())
}
_, err = clusterClient.ClusterV1beta1().Placements(namespace).Update(context.Background(), placement, metav1.UpdateOptions{})
return err
}, eventuallyTimeout, eventuallyInterval).ShouldNot(gomega.HaveOccurred())
assertNumberOfDecisions(placementName, 0)
assertPlacementStatus(placementName, 0, false)

View File

@@ -209,16 +209,17 @@ func assertCreatingClusterSet(clusterSetName string, labels ...string) {
Name: clusterSetName,
Labels: map[string]string{},
},
Spec: clusterapiv1beta2.ManagedClusterSetSpec{},
Spec: clusterapiv1beta2.ManagedClusterSetSpec{
ClusterSelector: clusterapiv1beta2.ManagedClusterSelector{
SelectorType: clusterapiv1beta2.LabelSelector,
LabelSelector: &metav1.LabelSelector{
MatchLabels: map[string]string{},
},
},
},
}
if len(labels) > 0 {
clusterset.Spec.ClusterSelector = clusterapiv1beta2.ManagedClusterSelector{
SelectorType: clusterapiv1beta2.LabelSelector,
LabelSelector: &metav1.LabelSelector{
MatchLabels: map[string]string{},
},
}
for i := 1; i < len(labels); i += 2 {
clusterset.Spec.ClusterSelector.LabelSelector.MatchLabels[labels[i-1]] = labels[i]
}
@@ -301,6 +302,20 @@ func assertCreatingClusters(clusterSetName string, num int, labels ...string) []
return names
}
func assertCleanupClusters() []string {
ginkgo.By("Cleanup all managed clusters")
var clusterNames []string
clusters, err := clusterClient.ClusterV1().ManagedClusters().List(context.Background(), metav1.ListOptions{})
gomega.Expect(err).ToNot(gomega.HaveOccurred())
for _, cluster := range clusters.Items {
clusterNames = append(clusterNames, cluster.Name)
}
assertDeletingClusters(clusterNames...)
return clusterNames
}
func assertUpdatingClusterWithClusterResources(managedClusterName string, res []string) {
ginkgo.By(fmt.Sprintf("Updating ManagedClusters %s cluster resources", managedClusterName))

View File

@@ -66,6 +66,8 @@ var _ = ginkgo.Describe("Placement", func() {
}
err := kubeClient.CoreV1().Namespaces().Delete(context.Background(), namespace, metav1.DeleteOptions{})
gomega.Expect(err).ToNot(gomega.HaveOccurred())
assertCleanupClusters()
})
ginkgo.Context("Scheduling", func() {
@@ -74,6 +76,7 @@ var _ = ginkgo.Describe("Placement", func() {
err = clusterClient.ClusterV1beta1().Placements(namespace).Delete(context.Background(), placementName, metav1.DeleteOptions{})
gomega.Expect(err).ToNot(gomega.HaveOccurred())
assertPlacementDeleted(placementName, namespace)
})
ginkgo.It("Should re-create placementdecisions successfully once placementdecisions are deleted", func() {
@@ -336,6 +339,24 @@ var _ = ginkgo.Describe("Placement", func() {
assertPlacementConditionSatisfied(placementName, namespace, 5, false)
})
ginkgo.It("Should schedule successfully with global clusterset(labelselector type clusterset without label selector)", func() {
assertCreatingClusterSet("global")
assertCreatingClusterSetBinding("global", namespace)
clusters1 := assertCreatingClusters(clusterName+"1", 1)
clusters2 := assertCreatingClusters(clusterName+"2", 1)
assertCreatingPlacementWithDecision(placementName, namespace, noc(2), 2, clusterapiv1beta1.PrioritizerPolicy{}, []clusterapiv1beta1.Toleration{})
assertNumberOfDecisions(placementName, namespace, 2)
assertPlacementConditionSatisfied(placementName, namespace, 2, true)
ginkgo.By("Delete the cluster")
assertDeletingClusters(clusters1...)
assertNumberOfDecisions(placementName, namespace, 1)
assertDeletingClusters(clusters2...)
assertNumberOfDecisions(placementName, namespace, 0)
})
})
})

View File

@@ -178,6 +178,48 @@ var _ = ginkgo.Describe("Prioritizers", func() {
assertClusterNamesOfDecisions(placementName, namespace, []string{clusterNames[0], clusterNames[2]})
})
ginkgo.It("Should schedule successfully based on SchedulePolicy balance", func() {
// cluster settings
clusterResources := make([][]string, 3)
clusterResources[0] = []string{"10", "10", "50", "100"}
clusterResources[1] = []string{"7", "10", "90", "100"}
clusterResources[2] = []string{"9", "10", "80", "100"}
// placement settings
prioritizerPolicy := clusterapiv1beta1.PrioritizerPolicy{
Mode: clusterapiv1beta1.PrioritizerPolicyModeExact,
Configurations: []clusterapiv1beta1.PrioritizerConfig{
{
ScoreCoordinate: &clusterapiv1beta1.ScoreCoordinate{
Type: clusterapiv1beta1.ScoreCoordinateTypeBuiltIn,
BuiltIn: "Balance",
},
Weight: 2,
},
{
ScoreCoordinate: &clusterapiv1beta1.ScoreCoordinate{
Type: clusterapiv1beta1.ScoreCoordinateTypeBuiltIn,
BuiltIn: "ResourceAllocatableCPU",
},
Weight: 1,
},
},
}
//Creating the clusters with resources
assertBindingClusterSet(clusterSet1Name, namespace)
clusterNames := assertCreatingClusters(clusterSet1Name, 3)
for i, name := range clusterNames {
assertUpdatingClusterWithClusterResources(name, clusterResources[i])
}
ginkgo.By("Adding fake placement decisions")
assertCreatingPlacementDecision("fake-1", namespace, []string{clusterNames[0]})
//Checking the result of the placement
assertCreatingPlacementWithDecision(placementName, namespace, noc(2), 2, prioritizerPolicy, []clusterapiv1beta1.Toleration{})
assertClusterNamesOfDecisions(placementName, namespace, []string{clusterNames[1], clusterNames[2]})
})
ginkgo.It("Should re-schedule successfully once a new cluster with resources added/deleted", func() {
// cluster settings
clusterResources := make([][]string, 3)