Skip to content

Commit 785ad5d

Browse files
committed
add the ut case for selecting cluster
Signed-off-by: huone1 <[email protected]>
1 parent c69d0e0 commit 785ad5d

File tree

4 files changed

+310
-10
lines changed

4 files changed

+310
-10
lines changed

pkg/scheduler/core/spreadconstraint/group_clusters.go

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,28 +15,29 @@ type GroupClustersInfo struct {
1515
Regions map[string]RegionInfo
1616
Zones map[string]ZoneInfo
1717

18-
// Clusters from globally view, sorted by cluster.Score descending.
18+
// Clusters from global view, sorted by cluster.Score descending.
1919
Clusters []ClusterDetailInfo
2020
}
2121

2222
// ProviderInfo indicate the provider information
2323
type ProviderInfo struct {
2424
Name string
25-
Score int64
2625
AvailableReplicas int64
2726

27+
// Regions under this provider
2828
Regions map[string]struct{}
29-
Zones map[string]struct{}
29+
// Zones under this provider
30+
Zones map[string]struct{}
3031
// Clusters under this provider, sorted by cluster.Score descending.
3132
Clusters []ClusterDetailInfo
3233
}
3334

3435
// RegionInfo indicate the region information
3536
type RegionInfo struct {
3637
Name string
37-
Score int64
3838
AvailableReplicas int64
3939

40+
// Zones under this provider
4041
Zones map[string]struct{}
4142
// Clusters under this region, sorted by cluster.Score descending.
4243
Clusters []ClusterDetailInfo
@@ -45,7 +46,6 @@ type RegionInfo struct {
4546
// ZoneInfo indicate the zone information
4647
type ZoneInfo struct {
4748
Name string
48-
Score int64
4949
AvailableReplicas int64
5050

5151
// Clusters under this zone, sorted by cluster.Score descending.
@@ -142,7 +142,6 @@ func (info *GroupClustersInfo) generateZoneInfo(spreadConstraints []policyv1alph
142142
}
143143

144144
zoneInfo.Clusters = append(zoneInfo.Clusters, clusterInfo)
145-
zoneInfo.Score += clusterInfo.Score
146145
zoneInfo.AvailableReplicas += clusterInfo.AvailableReplicas
147146
info.Zones[zone] = zoneInfo
148147
}
@@ -172,7 +171,6 @@ func (info *GroupClustersInfo) generateRegionInfo(spreadConstraints []policyv1al
172171
regionInfo.Zones[clusterInfo.Cluster.Spec.Zone] = struct{}{}
173172
}
174173
regionInfo.Clusters = append(regionInfo.Clusters, clusterInfo)
175-
regionInfo.Score += clusterInfo.Score
176174
regionInfo.AvailableReplicas += clusterInfo.AvailableReplicas
177175
info.Regions[region] = regionInfo
178176
}
@@ -208,7 +206,6 @@ func (info *GroupClustersInfo) generateProviderInfo(spreadConstraints []policyv1
208206
}
209207

210208
providerInfo.Clusters = append(providerInfo.Clusters, clusterInfo)
211-
providerInfo.Score += clusterInfo.Score
212209
providerInfo.AvailableReplicas += clusterInfo.AvailableReplicas
213210
info.Providers[provider] = providerInfo
214211
}
@@ -225,7 +222,7 @@ func isTopologyIgnored(placement *policyv1alpha1.Placement) bool {
225222
// If the replica division preference is 'static weighted', ignore the declaration specified by spread constraints.
226223
if strategy != nil && strategy.ReplicaSchedulingType == policyv1alpha1.ReplicaSchedulingTypeDivided &&
227224
strategy.ReplicaDivisionPreference == policyv1alpha1.ReplicaDivisionPreferenceWeighted &&
228-
(strategy.WeightPreference == nil || strategy.WeightPreference.DynamicWeight == "") {
225+
(len(strategy.WeightPreference.StaticWeightList) != 0 && strategy.WeightPreference.DynamicWeight == "") {
229226
return true
230227
}
231228

Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
package spreadconstraint
2+
3+
import (
4+
"testing"
5+
6+
"github.com/agiledragon/gomonkey/v2"
7+
8+
clusterv1alpha1 "github.com/karmada-io/karmada/pkg/apis/cluster/v1alpha1"
9+
policyv1alpha1 "github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1"
10+
workv1alpha2 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha2"
11+
"github.com/karmada-io/karmada/pkg/scheduler/framework"
12+
)
13+
14+
func generateClusterScore() framework.ClusterScoreList {
15+
return framework.ClusterScoreList{
16+
{
17+
Cluster: NewClusterWithTopology("member1", "P1", "R1", "Z1"),
18+
Score: 20,
19+
},
20+
{
21+
Cluster: NewClusterWithTopology("member2", "P1", "R1", "Z2"),
22+
Score: 40,
23+
},
24+
{
25+
Cluster: NewClusterWithTopology("member3", "P2", "R1", "Z1"),
26+
Score: 30,
27+
},
28+
{
29+
Cluster: NewClusterWithTopology("member4", "P2", "R2", "Z2"),
30+
Score: 60,
31+
},
32+
}
33+
}
34+
func Test_GroupClustersWithScore(t *testing.T) {
35+
type args struct {
36+
clustersScore framework.ClusterScoreList
37+
placement *policyv1alpha1.Placement
38+
spec *workv1alpha2.ResourceBindingSpec
39+
}
40+
type want struct {
41+
clusters []string
42+
zoneCnt int
43+
regionCnt int
44+
providerCnt int
45+
}
46+
47+
tests := []struct {
48+
name string
49+
args args
50+
want want
51+
}{
52+
{
53+
name: "test SpreadConstraints is nil",
54+
args: args{
55+
clustersScore: generateClusterScore(),
56+
placement: &policyv1alpha1.Placement{},
57+
},
58+
want: want{
59+
clusters: []string{"member4", "member2", "member3", "member1"},
60+
},
61+
},
62+
{
63+
name: "test SpreadConstraints is cluster",
64+
args: args{
65+
clustersScore: generateClusterScore(),
66+
placement: &policyv1alpha1.Placement{
67+
SpreadConstraints: []policyv1alpha1.SpreadConstraint{
68+
{
69+
SpreadByField: policyv1alpha1.SpreadByFieldCluster,
70+
MaxGroups: 1,
71+
MinGroups: 1,
72+
},
73+
},
74+
},
75+
},
76+
want: want{
77+
clusters: []string{"member4", "member2", "member3", "member1"},
78+
},
79+
},
80+
{
81+
name: "test SpreadConstraints is zone",
82+
args: args{
83+
clustersScore: generateClusterScore(),
84+
placement: &policyv1alpha1.Placement{
85+
SpreadConstraints: []policyv1alpha1.SpreadConstraint{
86+
{
87+
SpreadByField: policyv1alpha1.SpreadByFieldZone,
88+
MaxGroups: 1,
89+
MinGroups: 1,
90+
},
91+
},
92+
},
93+
},
94+
want: want{
95+
clusters: []string{"member4", "member2", "member3", "member1"},
96+
zoneCnt: 2,
97+
},
98+
},
99+
{
100+
name: "test SpreadConstraints is region",
101+
args: args{
102+
clustersScore: generateClusterScore(),
103+
placement: &policyv1alpha1.Placement{
104+
SpreadConstraints: []policyv1alpha1.SpreadConstraint{
105+
{
106+
SpreadByField: policyv1alpha1.SpreadByFieldRegion,
107+
MaxGroups: 1,
108+
MinGroups: 1,
109+
},
110+
},
111+
},
112+
},
113+
want: want{
114+
clusters: []string{"member4", "member2", "member3", "member1"},
115+
regionCnt: 2,
116+
},
117+
},
118+
{
119+
name: "test SpreadConstraints is provider",
120+
args: args{
121+
clustersScore: generateClusterScore(),
122+
placement: &policyv1alpha1.Placement{
123+
SpreadConstraints: []policyv1alpha1.SpreadConstraint{
124+
{
125+
SpreadByField: policyv1alpha1.SpreadByFieldProvider,
126+
MaxGroups: 1,
127+
MinGroups: 1,
128+
},
129+
},
130+
},
131+
},
132+
want: want{
133+
clusters: []string{"member4", "member2", "member3", "member1"},
134+
providerCnt: 2,
135+
},
136+
},
137+
{
138+
name: "test SpreadConstraints is provider/region/zone",
139+
args: args{
140+
clustersScore: generateClusterScore(),
141+
placement: &policyv1alpha1.Placement{
142+
SpreadConstraints: []policyv1alpha1.SpreadConstraint{
143+
{
144+
SpreadByField: policyv1alpha1.SpreadByFieldProvider,
145+
MaxGroups: 1,
146+
MinGroups: 1,
147+
},
148+
{
149+
SpreadByField: policyv1alpha1.SpreadByFieldRegion,
150+
MaxGroups: 1,
151+
MinGroups: 1,
152+
},
153+
{
154+
SpreadByField: policyv1alpha1.SpreadByFieldZone,
155+
MaxGroups: 1,
156+
MinGroups: 1,
157+
},
158+
},
159+
},
160+
},
161+
want: want{
162+
clusters: []string{"member4", "member2", "member3", "member1"},
163+
providerCnt: 2,
164+
regionCnt: 2,
165+
zoneCnt: 2,
166+
},
167+
},
168+
}
169+
170+
patches := gomonkey.ApplyFunc(calAvailableReplicas, func(clusters []*clusterv1alpha1.Cluster, spec *workv1alpha2.ResourceBindingSpec) []workv1alpha2.TargetCluster {
171+
availableTargetClusters := make([]workv1alpha2.TargetCluster, len(clusters))
172+
173+
for i := range availableTargetClusters {
174+
availableTargetClusters[i].Name = clusters[i].Name
175+
availableTargetClusters[i].Replicas = 100
176+
}
177+
178+
return availableTargetClusters
179+
})
180+
181+
defer patches.Reset()
182+
183+
for _, tt := range tests {
184+
t.Run(tt.name, func(t *testing.T) {
185+
groupInfo := GroupClustersWithScore(tt.args.clustersScore, tt.args.placement, tt.args.spec)
186+
for i, cluster := range groupInfo.Clusters {
187+
if cluster.Name != tt.want.clusters[i] {
188+
t.Errorf("test %s : the clusters aren't sorted", tt.name)
189+
}
190+
}
191+
192+
if tt.want.zoneCnt != len(groupInfo.Zones) {
193+
t.Errorf("test %s : zoneCnt = %v, want %v", tt.name, len(groupInfo.Zones), tt.want.zoneCnt)
194+
}
195+
if tt.want.regionCnt != len(groupInfo.Regions) {
196+
t.Errorf("test %s : regionCnt = %v, want %v", tt.name, len(groupInfo.Regions), tt.want.regionCnt)
197+
}
198+
if tt.want.providerCnt != len(groupInfo.Providers) {
199+
t.Errorf("test %s : providerCnt = %v, want %v", tt.name, len(groupInfo.Providers), tt.want.providerCnt)
200+
}
201+
})
202+
}
203+
}
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
package spreadconstraint
2+
3+
import (
4+
"reflect"
5+
"testing"
6+
7+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
8+
9+
clusterv1alpha1 "github.com/karmada-io/karmada/pkg/apis/cluster/v1alpha1"
10+
policyv1alpha1 "github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1"
11+
)
12+
13+
// NewClusterWithTopology will build a Cluster with topology.
14+
func NewClusterWithTopology(name, provider, region, zone string) *clusterv1alpha1.Cluster {
15+
return &clusterv1alpha1.Cluster{
16+
ObjectMeta: metav1.ObjectMeta{Name: name},
17+
Spec: clusterv1alpha1.ClusterSpec{
18+
Provider: provider,
19+
Region: region,
20+
Zone: zone,
21+
},
22+
}
23+
}
24+
25+
func generateClusterInfo() []ClusterDetailInfo {
26+
return []ClusterDetailInfo{
27+
{
28+
Name: "member4",
29+
Score: 60,
30+
AvailableReplicas: 101,
31+
Cluster: NewClusterWithTopology("member4", "P2", "R2", "Z2"),
32+
},
33+
{
34+
Name: "member2",
35+
Score: 40,
36+
AvailableReplicas: 101,
37+
Cluster: NewClusterWithTopology("member2", "P1", "R1", "Z2"),
38+
},
39+
{
40+
Name: "member3",
41+
Score: 30,
42+
AvailableReplicas: 101,
43+
Cluster: NewClusterWithTopology("member3", "P2", "R1", "Z1"),
44+
},
45+
{
46+
Name: "member1",
47+
Score: 20,
48+
AvailableReplicas: 101,
49+
Cluster: NewClusterWithTopology("member1", "P1", "R1", "Z1"),
50+
},
51+
}
52+
}
53+
54+
func TestSelectBestClusters(t *testing.T) {
55+
clustetInfos := generateClusterInfo()
56+
type args struct {
57+
placement *policyv1alpha1.Placement
58+
groupClustersInfo *GroupClustersInfo
59+
}
60+
tests := []struct {
61+
name string
62+
args args
63+
want []*clusterv1alpha1.Cluster
64+
wantErr bool
65+
}{
66+
{
67+
name: "select clusters by cluster score",
68+
args: args{
69+
placement: &policyv1alpha1.Placement{
70+
SpreadConstraints: []policyv1alpha1.SpreadConstraint{
71+
{
72+
SpreadByField: policyv1alpha1.SpreadByFieldCluster,
73+
MaxGroups: 2,
74+
MinGroups: 1,
75+
},
76+
},
77+
},
78+
groupClustersInfo: &GroupClustersInfo{
79+
Clusters: clustetInfos,
80+
},
81+
},
82+
want: []*clusterv1alpha1.Cluster{
83+
clustetInfos[0].Cluster,
84+
clustetInfos[1].Cluster,
85+
},
86+
},
87+
}
88+
for _, tt := range tests {
89+
t.Run(tt.name, func(t *testing.T) {
90+
got, err := SelectBestClusters(tt.args.placement, tt.args.groupClustersInfo)
91+
if (err != nil) != tt.wantErr {
92+
t.Errorf("SelectBestClusters() error = %v, wantErr %v", err, tt.wantErr)
93+
return
94+
}
95+
if !reflect.DeepEqual(got, tt.want) {
96+
t.Errorf("SelectBestClusters() = %v, want %v", got, tt.want)
97+
}
98+
})
99+
}
100+
}

pkg/scheduler/core/spreadconstraint/util.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@ package spreadconstraint
33
import (
44
"context"
55
"fmt"
6-
policyv1alpha1 "github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1"
76
"math"
87

98
"k8s.io/klog/v2"
109

1110
clusterv1alpha1 "github.com/karmada-io/karmada/pkg/apis/cluster/v1alpha1"
11+
policyv1alpha1 "github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1"
1212
workv1alpha2 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha2"
1313
estimatorclient "github.com/karmada-io/karmada/pkg/estimator/client"
1414
"github.com/karmada-io/karmada/pkg/util"

0 commit comments

Comments
 (0)