mirror of
https://github.com/open-cluster-management-io/ocm.git
synced 2026-05-22 00:54:00 +00:00
Merge pull request #31 from haoqing0110/br_placement_prioritizer
add prioritizer with weight
This commit is contained in:
@@ -12,7 +12,17 @@ spec:
|
||||
scope: Namespaced
|
||||
preserveUnknownFields: false
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
- additionalPrinterColumns:
|
||||
- jsonPath: .status.conditions[?(@.type=="PlacementSatisfied")].status
|
||||
name: Succeeded
|
||||
type: string
|
||||
- jsonPath: .status.conditions[?(@.type=="PlacementSatisfied")].reason
|
||||
name: Reason
|
||||
type: string
|
||||
- jsonPath: .status.numberOfSelectedClusters
|
||||
name: SelectedClusters
|
||||
type: integer
|
||||
name: v1alpha1
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
description: "Placement defines a rule to select a set of ManagedClusters
|
||||
@@ -182,6 +192,57 @@ spec:
|
||||
type: object
|
||||
additionalProperties:
|
||||
type: string
|
||||
prioritizerPolicy:
|
||||
description: PrioritizerPolicy defines the policy of the prioritizers.
|
||||
If this field is unset, then default prioritizer mode and configurations
|
||||
are used. Referring to PrioritizerPolicy to see more description
|
||||
about Mode and Configurations.
|
||||
type: object
|
||||
properties:
|
||||
configurations:
|
||||
type: array
|
||||
items:
|
||||
description: PrioritizerConfig represents the configuration
|
||||
of prioritizer
|
||||
type: object
|
||||
required:
|
||||
- name
|
||||
properties:
|
||||
name:
|
||||
description: 'Name is the name of a prioritizer. Below are
|
||||
the valid names: 1) Balance: balance the decisions among
|
||||
the clusters. 2) Steady: ensure the existing decision
|
||||
is stabilized. 3) ResourceRatioCPU & ResourceRatioMemory:
|
||||
sort clusters based on the allocatable to capacity ratio.
|
||||
4) ResourceAllocatableCPU & ResourceAllocatableMemory:
|
||||
sort clusters based on the allocatable.'
|
||||
type: string
|
||||
weight:
|
||||
description: Weight defines the weight of prioritizer. The
|
||||
value must be ranged in [0,10]. Each prioritizer will
|
||||
calculate an integer score of a cluster in the range of
|
||||
[-100, 100]. The final score of a cluster will be sum(weight
|
||||
* prioritizer_score). A higher weight indicates that the
|
||||
prioritizer weights more in the cluster selection, while
|
||||
0 weight indicate thats the prioritizer is disabled.
|
||||
type: integer
|
||||
format: int32
|
||||
default: 1
|
||||
maximum: 10
|
||||
minimum: 0
|
||||
mode:
|
||||
description: Mode is either Exact, Additive, "" where "" is Additive
|
||||
by default. In Additive mode, any prioritizer not explicitly
|
||||
enumerated is enabled in its default Configurations, in which
|
||||
Steady and Balance prioritizers have the weight of 1 while other
|
||||
prioritizers have the weight of 0. Additive doesn't require
|
||||
configuring all prioritizers. The default Configurations may
|
||||
change in the future, and additional prioritization will happen.
|
||||
In Exact mode, any prioritizer not explicitly enumerated is
|
||||
weighted as zero. Exact requires knowing the full set of prioritizers
|
||||
you want, but avoids behavior changes between releases.
|
||||
type: string
|
||||
default: Additive
|
||||
status:
|
||||
description: Status represents the current status of the Placement
|
||||
type: object
|
||||
|
||||
2
go.mod
2
go.mod
@@ -17,6 +17,6 @@ require (
|
||||
k8s.io/client-go v0.21.1
|
||||
k8s.io/component-base v0.21.0
|
||||
k8s.io/klog/v2 v2.8.0
|
||||
open-cluster-management.io/api v0.0.0-20210610125115-f57c747b84aa
|
||||
open-cluster-management.io/api v0.0.0-20210908005819-815ac23c7308
|
||||
sigs.k8s.io/controller-runtime v0.8.3
|
||||
)
|
||||
|
||||
4
go.sum
4
go.sum
@@ -959,8 +959,8 @@ modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk=
|
||||
modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k=
|
||||
modernc.org/strutil v1.0.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs=
|
||||
modernc.org/xc v1.0.0/go.mod h1:mRNCo0bvLjGhHO9WsyuKVU4q0ceiDDDoEeWDJHrNx8I=
|
||||
open-cluster-management.io/api v0.0.0-20210610125115-f57c747b84aa h1:Jw/Jo3Om1xXgdcn6xDfyREkc48nUcW/DqhMHffLCCww=
|
||||
open-cluster-management.io/api v0.0.0-20210610125115-f57c747b84aa/go.mod h1:9qiA5h/8kvPQnJEOlAPHVjRO9a1jCmDhGzvgMBvXEaE=
|
||||
open-cluster-management.io/api v0.0.0-20210908005819-815ac23c7308 h1:itWWudWVTqviZ2H2Arb1yTQ7NMUSPVDmWiVOpXiblOM=
|
||||
open-cluster-management.io/api v0.0.0-20210908005819-815ac23c7308/go.mod h1:9qiA5h/8kvPQnJEOlAPHVjRO9a1jCmDhGzvgMBvXEaE=
|
||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||
|
||||
@@ -2,6 +2,7 @@ package scheduling
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
@@ -16,7 +17,8 @@ import (
|
||||
"open-cluster-management.io/placement/pkg/plugins/steady"
|
||||
)
|
||||
|
||||
type PrioritizeSore map[string]int64
|
||||
// PrioritizerScore defines the score for each cluster
|
||||
type PrioritizerScore map[string]int64
|
||||
|
||||
// Scheduler is an interface for scheduler, it returs the scheduler results
|
||||
type Scheduler interface {
|
||||
@@ -31,8 +33,11 @@ type ScheduleResult interface {
|
||||
// FilterResults returns results for each filter
|
||||
FilterResults() []FilterResult
|
||||
|
||||
// PriorizeResults returns results for each prioritizer
|
||||
PriorizeResults() []PriorizeResult
|
||||
// PrioritizerResults returns results for each prioritizer
|
||||
PrioritizerResults() []PrioritizerResult
|
||||
|
||||
// PrioritizerScores returns total score for each cluster
|
||||
PrioritizerScores() PrioritizerScore
|
||||
|
||||
// Decisions returns the decisions of the schedule
|
||||
Decisions() []clusterapiv1alpha1.ClusterDecision
|
||||
@@ -46,9 +51,12 @@ type FilterResult struct {
|
||||
FilteredClusters []string `json:"filteredClusters"`
|
||||
}
|
||||
|
||||
type PriorizeResult struct {
|
||||
Name string `json:"name"`
|
||||
Scores PrioritizeSore `json:"scores"`
|
||||
// PrioritizerResult defines the result of one prioritizer,
|
||||
// include name, weight, and score of each cluster.
|
||||
type PrioritizerResult struct {
|
||||
Name string `json:"name"`
|
||||
Weight int32 `json:"weight"`
|
||||
Scores PrioritizerScore `json:"scores"`
|
||||
}
|
||||
|
||||
// ScheduleResult is the result for a certain schedule.
|
||||
@@ -58,7 +66,8 @@ type scheduleResult struct {
|
||||
unscheduledDecisions int
|
||||
|
||||
filteredRecords map[string][]*clusterapiv1.ManagedCluster
|
||||
scoreRecords []PriorizeResult
|
||||
scoreRecords []PrioritizerResult
|
||||
scoreSum PrioritizerScore
|
||||
}
|
||||
|
||||
type schedulerHandler struct {
|
||||
@@ -89,9 +98,18 @@ func (s *schedulerHandler) ClusterClient() clusterclient.Interface {
|
||||
return s.clusterClient
|
||||
}
|
||||
|
||||
// Initialize the default prioritizer weight.
|
||||
// Balane and Steady weight 1, others weight 0.
|
||||
// The default weight can be replaced by each placement's PrioritizerConfigs.
|
||||
var defaultPrioritizerConfig = map[string]int32{
|
||||
"Balance": 1,
|
||||
"Steady": 1,
|
||||
}
|
||||
|
||||
type pluginScheduler struct {
|
||||
filters []plugins.Filter
|
||||
prioritizers []plugins.Prioritizer
|
||||
filters []plugins.Filter
|
||||
prioritizers []plugins.Prioritizer
|
||||
prioritizerWeights map[string]int32
|
||||
}
|
||||
|
||||
func NewPluginScheduler(handle plugins.Handle) *pluginScheduler {
|
||||
@@ -103,6 +121,7 @@ func NewPluginScheduler(handle plugins.Handle) *pluginScheduler {
|
||||
balance.New(handle),
|
||||
steady.New(handle),
|
||||
},
|
||||
prioritizerWeights: defaultPrioritizerConfig,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,7 +135,7 @@ func (s *pluginScheduler) Schedule(
|
||||
|
||||
results := &scheduleResult{
|
||||
filteredRecords: map[string][]*clusterapiv1.ManagedCluster{},
|
||||
scoreRecords: []PriorizeResult{},
|
||||
scoreRecords: []PrioritizerResult{},
|
||||
}
|
||||
|
||||
// filter clusters
|
||||
@@ -134,27 +153,38 @@ func (s *pluginScheduler) Schedule(
|
||||
results.filteredRecords[strings.Join(filterPipline, ",")] = filtered
|
||||
}
|
||||
|
||||
// get weight for each prioritizers
|
||||
weights, err := getWeights(s.prioritizerWeights, placement)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// score clusters
|
||||
scoreSum := PrioritizeSore{}
|
||||
scoreSum := PrioritizerScore{}
|
||||
for _, cluster := range filtered {
|
||||
scoreSum[cluster.Name] = 0
|
||||
}
|
||||
for _, p := range s.prioritizers {
|
||||
// If weight is 0 (set to 0 or not defined in map), skip Score().
|
||||
weight := weights[p.Name()]
|
||||
if weight == 0 {
|
||||
results.scoreRecords = append(results.scoreRecords, PrioritizerResult{Name: p.Name(), Weight: weight, Scores: nil})
|
||||
continue
|
||||
}
|
||||
|
||||
score, err := p.Score(ctx, placement, filtered)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
results.scoreRecords = append(results.scoreRecords, PriorizeResult{Name: p.Name(), Scores: score})
|
||||
results.scoreRecords = append(results.scoreRecords, PrioritizerResult{Name: p.Name(), Weight: weight, Scores: score})
|
||||
|
||||
// TODO we currently weigh each prioritizer as equal. We should consider
|
||||
// importance factor for each priotizer when caculating the final score.
|
||||
// Since currently balance plugin has a score range of +/- 100 while the score range of
|
||||
// balacne is 0/100, the balance plugin will trigger the reschedule for rebalancing when
|
||||
// a cluster's decision count is larger than average.
|
||||
// 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.
|
||||
for name, val := range score {
|
||||
scoreSum[name] = scoreSum[name] + val
|
||||
scoreSum[name] = scoreSum[name] + val*int64(weight)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Sort cluster by score, if score is equal, sort by name
|
||||
@@ -167,6 +197,7 @@ func (s *pluginScheduler) Schedule(
|
||||
})
|
||||
|
||||
results.feasibleClusters = filtered
|
||||
results.scoreSum = scoreSum
|
||||
|
||||
// select clusters and generate cluster decisions
|
||||
// TODO: sort the feasible clusters and make sure the selection stable
|
||||
@@ -204,6 +235,34 @@ func selectClusters(placement *clusterapiv1alpha1.Placement, clusters []*cluster
|
||||
return decisions
|
||||
}
|
||||
|
||||
// Get prioritizer weight for the placement.
|
||||
// In Additive and "" mode, will override defaultWeight with what placement has defined and return.
|
||||
// In Exact mode, will return the name and weight defined in placement.
|
||||
func getWeights(defaultWeight map[string]int32, placement *clusterapiv1alpha1.Placement) (map[string]int32, error) {
|
||||
mode := placement.Spec.PrioritizerPolicy.Mode
|
||||
switch {
|
||||
case mode == clusterapiv1alpha1.PrioritizerPolicyModeExact:
|
||||
return mergeWeights(nil, placement.Spec.PrioritizerPolicy.Configurations), nil
|
||||
case mode == clusterapiv1alpha1.PrioritizerPolicyModeAdditive || mode == "":
|
||||
return mergeWeights(defaultWeight, placement.Spec.PrioritizerPolicy.Configurations), nil
|
||||
default:
|
||||
return nil, fmt.Errorf("incorrect prioritizer policy mode: %s", mode)
|
||||
}
|
||||
}
|
||||
|
||||
func mergeWeights(defaultWeight map[string]int32, customizedWeight []clusterapiv1alpha1.PrioritizerConfig) map[string]int32 {
|
||||
weights := make(map[string]int32)
|
||||
// copy the default weight
|
||||
for k, v := range defaultWeight {
|
||||
weights[k] = v
|
||||
}
|
||||
// override the default weight
|
||||
for _, c := range customizedWeight {
|
||||
weights[c.Name] = c.Weight
|
||||
}
|
||||
return weights
|
||||
}
|
||||
|
||||
func (r *scheduleResult) FilterResults() []FilterResult {
|
||||
results := []FilterResult{}
|
||||
for name, r := range r.filteredRecords {
|
||||
@@ -217,10 +276,14 @@ func (r *scheduleResult) FilterResults() []FilterResult {
|
||||
return results
|
||||
}
|
||||
|
||||
func (r *scheduleResult) PriorizeResults() []PriorizeResult {
|
||||
func (r *scheduleResult) PrioritizerResults() []PrioritizerResult {
|
||||
return r.scoreRecords
|
||||
}
|
||||
|
||||
func (r *scheduleResult) PrioritizerScores() PrioritizerScore {
|
||||
return r.scoreSum
|
||||
}
|
||||
|
||||
func (r *scheduleResult) Decisions() []clusterapiv1alpha1.ClusterDecision {
|
||||
return r.scheduledDecisions
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ func TestSchedule(t *testing.T) {
|
||||
clusters []*clusterapiv1.ManagedCluster
|
||||
decisions []runtime.Object
|
||||
expectedFilterResult []FilterResult
|
||||
expectedScoreResult []PriorizeResult
|
||||
expectedScoreResult []PrioritizerResult
|
||||
expectedDecisions []clusterapiv1alpha1.ClusterDecision
|
||||
expectedUnScheduled int
|
||||
}{
|
||||
@@ -44,18 +44,20 @@ func TestSchedule(t *testing.T) {
|
||||
},
|
||||
expectedFilterResult: []FilterResult{
|
||||
{
|
||||
Name: "predicate",
|
||||
Name: "Predicate",
|
||||
FilteredClusters: []string{"cluster1"},
|
||||
},
|
||||
},
|
||||
expectedScoreResult: []PriorizeResult{
|
||||
expectedScoreResult: []PrioritizerResult{
|
||||
{
|
||||
Name: "balance",
|
||||
Scores: PrioritizeSore{"cluster1": 100},
|
||||
Name: "Balance",
|
||||
Weight: 1,
|
||||
Scores: PrioritizerScore{"cluster1": 100},
|
||||
},
|
||||
{
|
||||
Name: "steady",
|
||||
Scores: PrioritizeSore{"cluster1": 0},
|
||||
Name: "Steady",
|
||||
Weight: 1,
|
||||
Scores: PrioritizerScore{"cluster1": 0},
|
||||
},
|
||||
},
|
||||
clusters: []*clusterapiv1.ManagedCluster{
|
||||
@@ -79,18 +81,20 @@ func TestSchedule(t *testing.T) {
|
||||
},
|
||||
expectedFilterResult: []FilterResult{
|
||||
{
|
||||
Name: "predicate",
|
||||
Name: "Predicate",
|
||||
FilteredClusters: []string{"cluster1"},
|
||||
},
|
||||
},
|
||||
expectedScoreResult: []PriorizeResult{
|
||||
expectedScoreResult: []PrioritizerResult{
|
||||
{
|
||||
Name: "balance",
|
||||
Scores: PrioritizeSore{"cluster1": 100},
|
||||
Name: "Balance",
|
||||
Weight: 1,
|
||||
Scores: PrioritizerScore{"cluster1": 100},
|
||||
},
|
||||
{
|
||||
Name: "steady",
|
||||
Scores: PrioritizeSore{"cluster1": 0},
|
||||
Name: "Steady",
|
||||
Weight: 1,
|
||||
Scores: PrioritizerScore{"cluster1": 0},
|
||||
},
|
||||
},
|
||||
expectedUnScheduled: 2,
|
||||
@@ -121,22 +125,126 @@ func TestSchedule(t *testing.T) {
|
||||
},
|
||||
expectedFilterResult: []FilterResult{
|
||||
{
|
||||
Name: "predicate",
|
||||
Name: "Predicate",
|
||||
FilteredClusters: []string{"cluster1", "cluster2", "cluster3"},
|
||||
},
|
||||
},
|
||||
expectedScoreResult: []PriorizeResult{
|
||||
expectedScoreResult: []PrioritizerResult{
|
||||
{
|
||||
Name: "balance",
|
||||
Scores: PrioritizeSore{"cluster1": 100, "cluster2": 100, "cluster3": 100},
|
||||
Name: "Balance",
|
||||
Weight: 1,
|
||||
Scores: PrioritizerScore{"cluster1": 100, "cluster2": 100, "cluster3": 100},
|
||||
},
|
||||
{
|
||||
Name: "steady",
|
||||
Scores: PrioritizeSore{"cluster1": 100, "cluster2": 100, "cluster3": 0},
|
||||
Name: "Steady",
|
||||
Weight: 1,
|
||||
Scores: PrioritizerScore{"cluster1": 100, "cluster2": 100, "cluster3": 0},
|
||||
},
|
||||
},
|
||||
expectedUnScheduled: 0,
|
||||
},
|
||||
{
|
||||
name: "placement with empty Prioritizer Policy",
|
||||
placement: testinghelpers.NewPlacement(placementNamespace, placementName).WithPrioritizerPolicy("").Build(),
|
||||
initObjs: []runtime.Object{
|
||||
testinghelpers.NewClusterSet(clusterSetName),
|
||||
testinghelpers.NewClusterSetBinding(placementNamespace, clusterSetName),
|
||||
},
|
||||
decisions: []runtime.Object{},
|
||||
expectedDecisions: []clusterapiv1alpha1.ClusterDecision{
|
||||
{ClusterName: "cluster1"},
|
||||
},
|
||||
expectedFilterResult: []FilterResult{
|
||||
{
|
||||
Name: "Predicate",
|
||||
FilteredClusters: []string{"cluster1"},
|
||||
},
|
||||
},
|
||||
expectedScoreResult: []PrioritizerResult{
|
||||
{
|
||||
Name: "Balance",
|
||||
Weight: 1,
|
||||
Scores: PrioritizerScore{"cluster1": 100},
|
||||
},
|
||||
{
|
||||
Name: "Steady",
|
||||
Weight: 1,
|
||||
Scores: PrioritizerScore{"cluster1": 0},
|
||||
},
|
||||
},
|
||||
clusters: []*clusterapiv1.ManagedCluster{
|
||||
testinghelpers.NewManagedCluster("cluster1").WithLabel(clusterSetLabel, clusterSetName).Build(),
|
||||
},
|
||||
expectedUnScheduled: 0,
|
||||
},
|
||||
{
|
||||
name: "placement with additive Prioritizer Policy",
|
||||
placement: testinghelpers.NewPlacement(placementNamespace, placementName).WithPrioritizerPolicy("Additive").WithPrioritizerConfig("Steady", 3).Build(),
|
||||
initObjs: []runtime.Object{
|
||||
testinghelpers.NewClusterSet(clusterSetName),
|
||||
testinghelpers.NewClusterSetBinding(placementNamespace, clusterSetName),
|
||||
},
|
||||
decisions: []runtime.Object{},
|
||||
expectedDecisions: []clusterapiv1alpha1.ClusterDecision{
|
||||
{ClusterName: "cluster1"},
|
||||
},
|
||||
expectedFilterResult: []FilterResult{
|
||||
{
|
||||
Name: "Predicate",
|
||||
FilteredClusters: []string{"cluster1"},
|
||||
},
|
||||
},
|
||||
expectedScoreResult: []PrioritizerResult{
|
||||
{
|
||||
Name: "Balance",
|
||||
Weight: 1,
|
||||
Scores: PrioritizerScore{"cluster1": 100},
|
||||
},
|
||||
{
|
||||
Name: "Steady",
|
||||
Weight: 3,
|
||||
Scores: PrioritizerScore{"cluster1": 0},
|
||||
},
|
||||
},
|
||||
clusters: []*clusterapiv1.ManagedCluster{
|
||||
testinghelpers.NewManagedCluster("cluster1").WithLabel(clusterSetLabel, clusterSetName).Build(),
|
||||
},
|
||||
expectedUnScheduled: 0,
|
||||
},
|
||||
{
|
||||
name: "placement with exact Prioritizer Policy",
|
||||
placement: testinghelpers.NewPlacement(placementNamespace, placementName).WithPrioritizerPolicy("Exact").WithPrioritizerConfig("Steady", 3).Build(),
|
||||
initObjs: []runtime.Object{
|
||||
testinghelpers.NewClusterSet(clusterSetName),
|
||||
testinghelpers.NewClusterSetBinding(placementNamespace, clusterSetName),
|
||||
},
|
||||
decisions: []runtime.Object{},
|
||||
expectedDecisions: []clusterapiv1alpha1.ClusterDecision{
|
||||
{ClusterName: "cluster1"},
|
||||
},
|
||||
expectedFilterResult: []FilterResult{
|
||||
{
|
||||
Name: "Predicate",
|
||||
FilteredClusters: []string{"cluster1"},
|
||||
},
|
||||
},
|
||||
expectedScoreResult: []PrioritizerResult{
|
||||
{
|
||||
Name: "Balance",
|
||||
Weight: 0,
|
||||
Scores: nil,
|
||||
},
|
||||
{
|
||||
Name: "Steady",
|
||||
Weight: 3,
|
||||
Scores: PrioritizerScore{"cluster1": 0},
|
||||
},
|
||||
},
|
||||
clusters: []*clusterapiv1.ManagedCluster{
|
||||
testinghelpers.NewManagedCluster("cluster1").WithLabel(clusterSetLabel, clusterSetName).Build(),
|
||||
},
|
||||
expectedUnScheduled: 0,
|
||||
},
|
||||
{
|
||||
name: "placement with part of decisions scheduled",
|
||||
placement: testinghelpers.NewPlacement(placementNamespace, placementName).WithNOC(4).Build(),
|
||||
@@ -162,18 +270,20 @@ func TestSchedule(t *testing.T) {
|
||||
},
|
||||
expectedFilterResult: []FilterResult{
|
||||
{
|
||||
Name: "predicate",
|
||||
Name: "Predicate",
|
||||
FilteredClusters: []string{"cluster1", "cluster2"},
|
||||
},
|
||||
},
|
||||
expectedScoreResult: []PriorizeResult{
|
||||
expectedScoreResult: []PrioritizerResult{
|
||||
{
|
||||
Name: "balance",
|
||||
Scores: PrioritizeSore{"cluster1": 100, "cluster2": 100},
|
||||
Name: "Balance",
|
||||
Weight: 1,
|
||||
Scores: PrioritizerScore{"cluster1": 100, "cluster2": 100},
|
||||
},
|
||||
{
|
||||
Name: "steady",
|
||||
Scores: PrioritizeSore{"cluster1": 100, "cluster2": 0},
|
||||
Name: "Steady",
|
||||
Weight: 1,
|
||||
Scores: PrioritizerScore{"cluster1": 100, "cluster2": 0},
|
||||
},
|
||||
},
|
||||
expectedUnScheduled: 2,
|
||||
@@ -201,18 +311,20 @@ func TestSchedule(t *testing.T) {
|
||||
},
|
||||
expectedFilterResult: []FilterResult{
|
||||
{
|
||||
Name: "predicate",
|
||||
Name: "Predicate",
|
||||
FilteredClusters: []string{"cluster3", "cluster1", "cluster2"},
|
||||
},
|
||||
},
|
||||
expectedScoreResult: []PriorizeResult{
|
||||
expectedScoreResult: []PrioritizerResult{
|
||||
{
|
||||
Name: "balance",
|
||||
Scores: PrioritizeSore{"cluster1": -100, "cluster2": -100, "cluster3": 100},
|
||||
Name: "Balance",
|
||||
Weight: 1,
|
||||
Scores: PrioritizerScore{"cluster1": -100, "cluster2": -100, "cluster3": 100},
|
||||
},
|
||||
{
|
||||
Name: "steady",
|
||||
Scores: PrioritizeSore{"cluster1": 0, "cluster2": 0, "cluster3": 0},
|
||||
Name: "Steady",
|
||||
Weight: 1,
|
||||
Scores: PrioritizerScore{"cluster1": 0, "cluster2": 0, "cluster3": 0},
|
||||
},
|
||||
},
|
||||
expectedUnScheduled: 0,
|
||||
@@ -250,18 +362,20 @@ func TestSchedule(t *testing.T) {
|
||||
},
|
||||
expectedFilterResult: []FilterResult{
|
||||
{
|
||||
Name: "predicate",
|
||||
Name: "Predicate",
|
||||
FilteredClusters: []string{"cluster3", "cluster1", "cluster2"},
|
||||
},
|
||||
},
|
||||
expectedScoreResult: []PriorizeResult{
|
||||
expectedScoreResult: []PrioritizerResult{
|
||||
{
|
||||
Name: "balance",
|
||||
Scores: PrioritizeSore{"cluster1": 0, "cluster2": -100, "cluster3": 0},
|
||||
Name: "Balance",
|
||||
Weight: 1,
|
||||
Scores: PrioritizerScore{"cluster1": 0, "cluster2": -100, "cluster3": 0},
|
||||
},
|
||||
{
|
||||
Name: "steady",
|
||||
Scores: PrioritizeSore{"cluster1": 0, "cluster2": 0, "cluster3": 100},
|
||||
Name: "Steady",
|
||||
Weight: 1,
|
||||
Scores: PrioritizerScore{"cluster1": 0, "cluster2": 0, "cluster3": 100},
|
||||
},
|
||||
},
|
||||
expectedUnScheduled: 0,
|
||||
@@ -294,7 +408,7 @@ func TestSchedule(t *testing.T) {
|
||||
t.Errorf("expected filter results %v, but got %v", string(expected), string(actual))
|
||||
}
|
||||
|
||||
actual, _ = json.Marshal(result.PriorizeResults())
|
||||
actual, _ = json.Marshal(result.PrioritizerResults())
|
||||
expected, _ = json.Marshal(c.expectedScoreResult)
|
||||
if !reflect.DeepEqual(actual, expected) {
|
||||
t.Errorf("expected score results %v, but got %v", string(expected), string(actual))
|
||||
|
||||
@@ -192,7 +192,7 @@ func (c *schedulingController) sync(ctx context.Context, syncCtx factory.SyncCon
|
||||
return err
|
||||
}
|
||||
|
||||
err = c.bind(ctx, placement, scheduleResult.Decisions())
|
||||
err = c.bind(ctx, placement, scheduleResult.Decisions(), scheduleResult.PrioritizerScores())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -337,6 +337,7 @@ func (c *schedulingController) bind(
|
||||
ctx context.Context,
|
||||
placement *clusterapiv1alpha1.Placement,
|
||||
clusterDecisions []clusterapiv1alpha1.ClusterDecision,
|
||||
clusterScores PrioritizerScore,
|
||||
) error {
|
||||
// sort clusterdecisions by cluster name
|
||||
sort.SliceStable(clusterDecisions, func(i, j int) bool {
|
||||
@@ -368,7 +369,7 @@ func (c *schedulingController) bind(
|
||||
placementDecisionName := fmt.Sprintf("%s-decision-%d", placement.Name, index+1)
|
||||
placementDecisionNames.Insert(placementDecisionName)
|
||||
err := c.createOrUpdatePlacementDecision(
|
||||
ctx, placement, placementDecisionName, decisionSlice)
|
||||
ctx, placement, placementDecisionName, decisionSlice, clusterScores)
|
||||
if err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
@@ -417,6 +418,7 @@ func (c *schedulingController) createOrUpdatePlacementDecision(
|
||||
placement *clusterapiv1alpha1.Placement,
|
||||
placementDecisionName string,
|
||||
clusterDecisions []clusterapiv1alpha1.ClusterDecision,
|
||||
clusterScores PrioritizerScore,
|
||||
) error {
|
||||
if len(clusterDecisions) > maxNumOfClusterDecisions {
|
||||
return fmt.Errorf("the number of clusterdecisions %q exceeds the max limitation %q", len(clusterDecisions), maxNumOfClusterDecisions)
|
||||
@@ -470,5 +472,15 @@ func (c *schedulingController) createOrUpdatePlacementDecision(
|
||||
"DecisionUpdate", "DecisionUpdated",
|
||||
"Decision %s is updated with placement %s in namespace %s", placementDecision.Name, placement.Name, placement.Namespace)
|
||||
|
||||
// update the event with prioritizer score.
|
||||
scoreStr := ""
|
||||
for k, v := range clusterScores {
|
||||
scoreStr += fmt.Sprintf("%s:%d ", k, v)
|
||||
}
|
||||
c.recorder.Eventf(
|
||||
placement, placementDecision, corev1.EventTypeNormal,
|
||||
"ScoreUpdate", "ScoreUpdated",
|
||||
scoreStr)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -560,6 +560,7 @@ func TestBind(t *testing.T) {
|
||||
context.TODO(),
|
||||
testinghelpers.NewPlacement(placementNamespace, placementName).Build(),
|
||||
c.clusterDecisions,
|
||||
nil,
|
||||
)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected err: %v", err)
|
||||
|
||||
@@ -25,9 +25,9 @@ type Debugger struct {
|
||||
|
||||
// DebugResult is the result returned by debugger
|
||||
type DebugResult struct {
|
||||
FilterResults []scheduling.FilterResult `json:"filteredPiplieResults,omitempty"`
|
||||
PrioritizeResults []scheduling.PriorizeResult `json:"prioritizeResults,omitempty"`
|
||||
Error string `json:"error,omitempty"`
|
||||
FilterResults []scheduling.FilterResult `json:"filteredPiplieResults,omitempty"`
|
||||
PrioritizeResults []scheduling.PrioritizerResult `json:"prioritizeResults,omitempty"`
|
||||
Error string `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
func NewDebugger(
|
||||
@@ -62,7 +62,7 @@ func (d *Debugger) Handler(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
scheduleResults, _ := d.scheduler.Schedule(r.Context(), placement, clusters)
|
||||
|
||||
result := DebugResult{FilterResults: scheduleResults.FilterResults(), PrioritizeResults: scheduleResults.PriorizeResults()}
|
||||
result := DebugResult{FilterResults: scheduleResults.FilterResults(), PrioritizeResults: scheduleResults.PrioritizerResults()}
|
||||
|
||||
resultByte, _ := json.Marshal(result)
|
||||
|
||||
|
||||
@@ -24,17 +24,22 @@ type testScheduler struct {
|
||||
|
||||
type testResult struct {
|
||||
filterResults []scheduling.FilterResult
|
||||
prioritizeResults []scheduling.PriorizeResult
|
||||
prioritizeResults []scheduling.PrioritizerResult
|
||||
scoreSum scheduling.PrioritizerScore
|
||||
}
|
||||
|
||||
func (r *testResult) FilterResults() []scheduling.FilterResult {
|
||||
return r.filterResults
|
||||
}
|
||||
|
||||
func (r *testResult) PriorizeResults() []scheduling.PriorizeResult {
|
||||
func (r *testResult) PrioritizerResults() []scheduling.PrioritizerResult {
|
||||
return r.prioritizeResults
|
||||
}
|
||||
|
||||
func (r *testResult) PrioritizerScores() scheduling.PrioritizerScore {
|
||||
return r.scoreSum
|
||||
}
|
||||
|
||||
func (r *testResult) Decisions() []clusterapiv1alpha1.ClusterDecision {
|
||||
return []clusterapiv1alpha1.ClusterDecision{}
|
||||
}
|
||||
@@ -59,7 +64,7 @@ func TestDebugger(t *testing.T) {
|
||||
name string
|
||||
initObjs []runtime.Object
|
||||
filterResults []scheduling.FilterResult
|
||||
prioritizeResults []scheduling.PriorizeResult
|
||||
prioritizeResults []scheduling.PrioritizerResult
|
||||
key string
|
||||
}{
|
||||
{
|
||||
@@ -70,7 +75,7 @@ func TestDebugger(t *testing.T) {
|
||||
testinghelpers.NewManagedCluster("cluster2").Build(),
|
||||
},
|
||||
filterResults: []scheduling.FilterResult{{Name: "filter1", FilteredClusters: []string{"cluster1", "cluster2"}}},
|
||||
prioritizeResults: []scheduling.PriorizeResult{{Name: "prioritize1", Scores: map[string]int64{"cluster1": 100, "cluster2": 0}}},
|
||||
prioritizeResults: []scheduling.PrioritizerResult{{Name: "prioritize1", Scores: map[string]int64{"cluster1": 100, "cluster2": 0}}},
|
||||
key: placementNamespace + "/" + placementName,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -36,6 +36,23 @@ func (b *placementBuilder) WithNOC(noc int32) *placementBuilder {
|
||||
return b
|
||||
}
|
||||
|
||||
func (b *placementBuilder) WithPrioritizerPolicy(mode clusterapiv1alpha1.PrioritizerPolicyModeType) *placementBuilder {
|
||||
b.placement.Spec.PrioritizerPolicy = clusterapiv1alpha1.PrioritizerPolicy{
|
||||
Mode: mode,
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func (b *placementBuilder) WithPrioritizerConfig(name string, weight int32) *placementBuilder {
|
||||
if b.placement.Spec.PrioritizerPolicy.Configurations == nil {
|
||||
b.placement.Spec.PrioritizerPolicy.Configurations = []clusterapiv1alpha1.PrioritizerConfig{}
|
||||
}
|
||||
if len(name) > 0 {
|
||||
b.placement.Spec.PrioritizerPolicy.Configurations = append(b.placement.Spec.PrioritizerPolicy.Configurations, clusterapiv1alpha1.PrioritizerConfig{Name: name, Weight: weight})
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func (b *placementBuilder) WithClusterSets(clusterSets ...string) *placementBuilder {
|
||||
b.placement.Spec.ClusterSets = clusterSets
|
||||
return b
|
||||
|
||||
@@ -2,6 +2,7 @@ package balance
|
||||
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
clusterapiv1 "open-cluster-management.io/api/cluster/v1"
|
||||
@@ -25,11 +26,13 @@ type Balance struct {
|
||||
}
|
||||
|
||||
func New(handle plugins.Handle) *Balance {
|
||||
return &Balance{handle: handle}
|
||||
return &Balance{
|
||||
handle: handle,
|
||||
}
|
||||
}
|
||||
|
||||
func (b *Balance) Name() string {
|
||||
return "balance"
|
||||
return reflect.TypeOf(*b).Name()
|
||||
}
|
||||
|
||||
func (b *Balance) Description() string {
|
||||
|
||||
@@ -2,6 +2,7 @@ package predicate
|
||||
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
@@ -27,7 +28,7 @@ func New(handle plugins.Handle) *Predicate {
|
||||
}
|
||||
|
||||
func (p *Predicate) Name() string {
|
||||
return "predicate"
|
||||
return reflect.TypeOf(*p).Name()
|
||||
}
|
||||
|
||||
func (p *Predicate) Description() string {
|
||||
|
||||
@@ -2,6 +2,7 @@ package steady
|
||||
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/selection"
|
||||
@@ -27,11 +28,13 @@ type Steady struct {
|
||||
}
|
||||
|
||||
func New(handle plugins.Handle) *Steady {
|
||||
return &Steady{handle: handle}
|
||||
return &Steady{
|
||||
handle: handle,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Steady) Name() string {
|
||||
return "steady"
|
||||
return reflect.TypeOf(*s).Name()
|
||||
}
|
||||
|
||||
func (s *Steady) Description() string {
|
||||
|
||||
2
vendor/modules.txt
vendored
2
vendor/modules.txt
vendored
@@ -860,7 +860,7 @@ k8s.io/utils/net
|
||||
k8s.io/utils/path
|
||||
k8s.io/utils/pointer
|
||||
k8s.io/utils/trace
|
||||
# open-cluster-management.io/api v0.0.0-20210610125115-f57c747b84aa
|
||||
# open-cluster-management.io/api v0.0.0-20210908005819-815ac23c7308
|
||||
## explicit
|
||||
open-cluster-management.io/api/client/cluster/clientset/versioned
|
||||
open-cluster-management.io/api/client/cluster/clientset/versioned/fake
|
||||
|
||||
@@ -12,7 +12,17 @@ spec:
|
||||
scope: Namespaced
|
||||
preserveUnknownFields: false
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
- additionalPrinterColumns:
|
||||
- jsonPath: .status.conditions[?(@.type=="PlacementSatisfied")].status
|
||||
name: Succeeded
|
||||
type: string
|
||||
- jsonPath: .status.conditions[?(@.type=="PlacementSatisfied")].reason
|
||||
name: Reason
|
||||
type: string
|
||||
- jsonPath: .status.numberOfSelectedClusters
|
||||
name: SelectedClusters
|
||||
type: integer
|
||||
name: v1alpha1
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
description: "Placement defines a rule to select a set of ManagedClusters
|
||||
@@ -182,6 +192,57 @@ spec:
|
||||
type: object
|
||||
additionalProperties:
|
||||
type: string
|
||||
prioritizerPolicy:
|
||||
description: PrioritizerPolicy defines the policy of the prioritizers.
|
||||
If this field is unset, then default prioritizer mode and configurations
|
||||
are used. Referring to PrioritizerPolicy to see more description
|
||||
about Mode and Configurations.
|
||||
type: object
|
||||
properties:
|
||||
configurations:
|
||||
type: array
|
||||
items:
|
||||
description: PrioritizerConfig represents the configuration
|
||||
of prioritizer
|
||||
type: object
|
||||
required:
|
||||
- name
|
||||
properties:
|
||||
name:
|
||||
description: 'Name is the name of a prioritizer. Below are
|
||||
the valid names: 1) Balance: balance the decisions among
|
||||
the clusters. 2) Steady: ensure the existing decision
|
||||
is stabilized. 3) ResourceRatioCPU & ResourceRatioMemory:
|
||||
sort clusters based on the allocatable to capacity ratio.
|
||||
4) ResourceAllocatableCPU & ResourceAllocatableMemory:
|
||||
sort clusters based on the allocatable.'
|
||||
type: string
|
||||
weight:
|
||||
description: Weight defines the weight of prioritizer. The
|
||||
value must be ranged in [0,10]. Each prioritizer will
|
||||
calculate an integer score of a cluster in the range of
|
||||
[-100, 100]. The final score of a cluster will be sum(weight
|
||||
* prioritizer_score). A higher weight indicates that the
|
||||
prioritizer weights more in the cluster selection, while
|
||||
0 weight indicate thats the prioritizer is disabled.
|
||||
type: integer
|
||||
format: int32
|
||||
default: 1
|
||||
maximum: 10
|
||||
minimum: 0
|
||||
mode:
|
||||
description: Mode is either Exact, Additive, "" where "" is Additive
|
||||
by default. In Additive mode, any prioritizer not explicitly
|
||||
enumerated is enabled in its default Configurations, in which
|
||||
Steady and Balance prioritizers have the weight of 1 while other
|
||||
prioritizers have the weight of 0. Additive doesn't require
|
||||
configuring all prioritizers. The default Configurations may
|
||||
change in the future, and additional prioritization will happen.
|
||||
In Exact mode, any prioritizer not explicitly enumerated is
|
||||
weighted as zero. Exact requires knowing the full set of prioritizers
|
||||
you want, but avoids behavior changes between releases.
|
||||
type: string
|
||||
default: Additive
|
||||
status:
|
||||
description: Status represents the current status of the Placement
|
||||
type: object
|
||||
|
||||
63
vendor/open-cluster-management.io/api/cluster/v1alpha1/types.go
generated
vendored
63
vendor/open-cluster-management.io/api/cluster/v1alpha1/types.go
generated
vendored
@@ -164,6 +164,9 @@ var ReservedClusterClaimNames = [...]string{
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
// +kubebuilder:resource:scope="Namespaced"
|
||||
// +kubebuilder:subresource:status
|
||||
// +kubebuilder:printcolumn:name="Succeeded",type="string",JSONPath=".status.conditions[?(@.type==\"PlacementSatisfied\")].status"
|
||||
// +kubebuilder:printcolumn:name="Reason",type="string",JSONPath=".status.conditions[?(@.type==\"PlacementSatisfied\")].reason"
|
||||
// +kubebuilder:printcolumn:name="SelectedClusters",type="integer",JSONPath=".status.numberOfSelectedClusters"
|
||||
|
||||
// Placement defines a rule to select a set of ManagedClusters from the ManagedClusterSets bound
|
||||
// to the placement namespace.
|
||||
@@ -230,6 +233,12 @@ type PlacementSpec struct {
|
||||
// Predicates represent a slice of predicates to select ManagedClusters. The predicates are ORed.
|
||||
// +optional
|
||||
Predicates []ClusterPredicate `json:"predicates,omitempty"`
|
||||
|
||||
// PrioritizerPolicy defines the policy of the prioritizers.
|
||||
// If this field is unset, then default prioritizer mode and configurations are used.
|
||||
// Referring to PrioritizerPolicy to see more description about Mode and Configurations.
|
||||
// +optional
|
||||
PrioritizerPolicy PrioritizerPolicy `json:"prioritizerPolicy"`
|
||||
}
|
||||
|
||||
// ClusterPredicate represents a predicate to select ManagedClusters.
|
||||
@@ -264,6 +273,55 @@ type ClusterClaimSelector struct {
|
||||
MatchExpressions []metav1.LabelSelectorRequirement `json:"matchExpressions,omitempty"`
|
||||
}
|
||||
|
||||
// PrioritizerPolicy represents the policy of prioritizer
|
||||
type PrioritizerPolicy struct {
|
||||
// Mode is either Exact, Additive, "" where "" is Additive by default.
|
||||
// In Additive mode, any prioritizer not explicitly enumerated is enabled in its default Configurations,
|
||||
// in which Steady and Balance prioritizers have the weight of 1 while other prioritizers have the weight of 0.
|
||||
// Additive doesn't require configuring all prioritizers. The default Configurations may change in the future,
|
||||
// and additional prioritization will happen.
|
||||
// In Exact mode, any prioritizer not explicitly enumerated is weighted as zero.
|
||||
// Exact requires knowing the full set of prioritizers you want, but avoids behavior changes between releases.
|
||||
// +kubebuilder:default:=Additive
|
||||
// +optional
|
||||
Mode PrioritizerPolicyModeType `json:"mode,omitempty"`
|
||||
|
||||
// +optional
|
||||
Configurations []PrioritizerConfig `json:"configurations,omitempty"`
|
||||
}
|
||||
|
||||
// PrioritizerPolicyModeType represents the type of PrioritizerPolicy.Mode
|
||||
type PrioritizerPolicyModeType string
|
||||
|
||||
const (
|
||||
// Valid PrioritizerPolicyModeType value is Exact, Additive.
|
||||
PrioritizerPolicyModeAdditive PrioritizerPolicyModeType = "Additive"
|
||||
PrioritizerPolicyModeExact PrioritizerPolicyModeType = "Exact"
|
||||
)
|
||||
|
||||
// PrioritizerConfig represents the configuration of prioritizer
|
||||
type PrioritizerConfig struct {
|
||||
// Name is the name of a prioritizer. Below are the valid names:
|
||||
// 1) Balance: balance the decisions among the clusters.
|
||||
// 2) Steady: ensure the existing decision is stabilized.
|
||||
// 3) ResourceRatioCPU & ResourceRatioMemory: sort clusters based on the allocatable to capacity ratio.
|
||||
// 4) ResourceAllocatableCPU & ResourceAllocatableMemory: sort clusters based on the allocatable.
|
||||
// +kubebuilder:validation:Required
|
||||
// +required
|
||||
Name string `json:"name"`
|
||||
|
||||
// Weight defines the weight of prioritizer. The value must be ranged in [0,10].
|
||||
// Each prioritizer will calculate an integer score of a cluster in the range of [-100, 100].
|
||||
// The final score of a cluster will be sum(weight * prioritizer_score).
|
||||
// A higher weight indicates that the prioritizer weights more in the cluster selection,
|
||||
// while 0 weight indicate thats the prioritizer is disabled.
|
||||
// +kubebuilder:validation:Minimum:=0
|
||||
// +kubebuilder:validation:Maximum:=10
|
||||
// +kubebuilder:default:=1
|
||||
// +optional
|
||||
Weight int32 `json:"weight,omitempty"`
|
||||
}
|
||||
|
||||
type PlacementStatus struct {
|
||||
// NumberOfSelectedClusters represents the number of selected ManagedClusters
|
||||
// +optional
|
||||
@@ -319,6 +377,11 @@ type PlacementDecision struct {
|
||||
Status PlacementDecisionStatus `json:"status,omitempty"`
|
||||
}
|
||||
|
||||
//The placementDecsion label name holding the placement name
|
||||
const (
|
||||
PlacementLabel string = "cluster.open-cluster-management.io/placement"
|
||||
)
|
||||
|
||||
// PlacementDecisionStatus represents the current status of the PlacementDecision.
|
||||
type PlacementDecisionStatus struct {
|
||||
// Decisions is a slice of decisions according to a placement
|
||||
|
||||
38
vendor/open-cluster-management.io/api/cluster/v1alpha1/zz_generated.deepcopy.go
generated
vendored
38
vendor/open-cluster-management.io/api/cluster/v1alpha1/zz_generated.deepcopy.go
generated
vendored
@@ -497,6 +497,7 @@ func (in *PlacementSpec) DeepCopyInto(out *PlacementSpec) {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
in.PrioritizerPolicy.DeepCopyInto(&out.PrioritizerPolicy)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -532,3 +533,40 @@ func (in *PlacementStatus) DeepCopy() *PlacementStatus {
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *PrioritizerConfig) DeepCopyInto(out *PrioritizerConfig) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PrioritizerConfig.
|
||||
func (in *PrioritizerConfig) DeepCopy() *PrioritizerConfig {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(PrioritizerConfig)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *PrioritizerPolicy) DeepCopyInto(out *PrioritizerPolicy) {
|
||||
*out = *in
|
||||
if in.Configurations != nil {
|
||||
in, out := &in.Configurations, &out.Configurations
|
||||
*out = make([]PrioritizerConfig, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PrioritizerPolicy.
|
||||
func (in *PrioritizerPolicy) DeepCopy() *PrioritizerPolicy {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(PrioritizerPolicy)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
@@ -190,10 +190,11 @@ func (PlacementList) SwaggerDoc() map[string]string {
|
||||
}
|
||||
|
||||
var map_PlacementSpec = map[string]string{
|
||||
"": "PlacementSpec defines the attributes of Placement. An empty PlacementSpec selects all ManagedClusters from the ManagedClusterSets bound to the placement namespace. The containing fields are ANDed.",
|
||||
"clusterSets": "ClusterSets represent the ManagedClusterSets from which the ManagedClusters are selected. If the slice is empty, ManagedClusters will be selected from the ManagedClusterSets bound to the placement namespace, otherwise ManagedClusters will be selected from the intersection of this slice and the ManagedClusterSets bound to the placement namespace.",
|
||||
"numberOfClusters": "NumberOfClusters represents the desired number of ManagedClusters to be selected which meet the placement requirements. 1) If not specified, all ManagedClusters which meet the placement requirements (including ClusterSets,\n and Predicates) will be selected;\n2) Otherwise if the nubmer of ManagedClusters meet the placement requirements is larger than\n NumberOfClusters, a random subset with desired number of ManagedClusters will be selected;\n3) If the nubmer of ManagedClusters meet the placement requirements is equal to NumberOfClusters,\n all of them will be selected;\n4) If the nubmer of ManagedClusters meet the placement requirements is less than NumberOfClusters,\n all of them will be selected, and the status of condition `PlacementConditionSatisfied` will be\n set to false;",
|
||||
"predicates": "Predicates represent a slice of predicates to select ManagedClusters. The predicates are ORed.",
|
||||
"": "PlacementSpec defines the attributes of Placement. An empty PlacementSpec selects all ManagedClusters from the ManagedClusterSets bound to the placement namespace. The containing fields are ANDed.",
|
||||
"clusterSets": "ClusterSets represent the ManagedClusterSets from which the ManagedClusters are selected. If the slice is empty, ManagedClusters will be selected from the ManagedClusterSets bound to the placement namespace, otherwise ManagedClusters will be selected from the intersection of this slice and the ManagedClusterSets bound to the placement namespace.",
|
||||
"numberOfClusters": "NumberOfClusters represents the desired number of ManagedClusters to be selected which meet the placement requirements. 1) If not specified, all ManagedClusters which meet the placement requirements (including ClusterSets,\n and Predicates) will be selected;\n2) Otherwise if the nubmer of ManagedClusters meet the placement requirements is larger than\n NumberOfClusters, a random subset with desired number of ManagedClusters will be selected;\n3) If the nubmer of ManagedClusters meet the placement requirements is equal to NumberOfClusters,\n all of them will be selected;\n4) If the nubmer of ManagedClusters meet the placement requirements is less than NumberOfClusters,\n all of them will be selected, and the status of condition `PlacementConditionSatisfied` will be\n set to false;",
|
||||
"predicates": "Predicates represent a slice of predicates to select ManagedClusters. The predicates are ORed.",
|
||||
"prioritizerPolicy": "PrioritizerPolicy defines the policy of the prioritizers. If this field is unset, then default prioritizer mode and configurations are used. Referring to PrioritizerPolicy to see more description about Mode and Configurations.",
|
||||
}
|
||||
|
||||
func (PlacementSpec) SwaggerDoc() map[string]string {
|
||||
@@ -209,4 +210,23 @@ func (PlacementStatus) SwaggerDoc() map[string]string {
|
||||
return map_PlacementStatus
|
||||
}
|
||||
|
||||
var map_PrioritizerConfig = map[string]string{
|
||||
"": "PrioritizerConfig represents the configuration of prioritizer",
|
||||
"name": "Name is the name of a prioritizer. Below are the valid names: 1) Balance: balance the decisions among the clusters. 2) Steady: ensure the existing decision is stabilized. 3) ResourceRatioCPU & ResourceRatioMemory: sort clusters based on the allocatable to capacity ratio. 4) ResourceAllocatableCPU & ResourceAllocatableMemory: sort clusters based on the allocatable.",
|
||||
"weight": "Weight defines the weight of prioritizer. The value must be ranged in [0,10]. Each prioritizer will calculate an integer score of a cluster in the range of [-100, 100]. The final score of a cluster will be sum(weight * prioritizer_score). A higher weight indicates that the prioritizer weights more in the cluster selection, while 0 weight indicate thats the prioritizer is disabled.",
|
||||
}
|
||||
|
||||
func (PrioritizerConfig) SwaggerDoc() map[string]string {
|
||||
return map_PrioritizerConfig
|
||||
}
|
||||
|
||||
var map_PrioritizerPolicy = map[string]string{
|
||||
"": "PrioritizerPolicy represents the policy of prioritizer",
|
||||
"mode": "Mode is either Exact, Additive, \"\" where \"\" is Additive by default. In Additive mode, any prioritizer not explicitly enumerated is enabled in its default Configurations, in which Steady and Balance prioritizers have the weight of 1 while other prioritizers have the weight of 0. Additive doesn't require configuring all prioritizers. The default Configurations may change in the future, and additional prioritization will happen. In Exact mode, any prioritizer not explicitly enumerated is weighted as zero. Exact requires knowing the full set of prioritizers you want, but avoids behavior changes between releases.",
|
||||
}
|
||||
|
||||
func (PrioritizerPolicy) SwaggerDoc() map[string]string {
|
||||
return map_PrioritizerPolicy
|
||||
}
|
||||
|
||||
// AUTO-GENERATED FUNCTIONS END HERE
|
||||
|
||||
Reference in New Issue
Block a user