mirror of
https://github.com/open-cluster-management-io/ocm.git
synced 2026-05-21 16:43:48 +00:00
Add integration tests (#91)
Signed-off-by: zhujian <jiazhu@redhat.com> Signed-off-by: zhujian <jiazhu@redhat.com>
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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.
|
||||
`
|
||||
)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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))
|
||||
|
||||
|
||||
@@ -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)
|
||||
})
|
||||
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user