mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-21 02:41:25 +00:00
Use internal config types in scheduling plugin args
Signed-off-by: Aldo Culquicondor <acondor@google.com>
This commit is contained in:
parent
6b153dc920
commit
98d1e241f1
@ -19,7 +19,6 @@ go_library(
|
|||||||
"//pkg/scheduler/apis/config/scheme:go_default_library",
|
"//pkg/scheduler/apis/config/scheme:go_default_library",
|
||||||
"//pkg/scheduler/apis/config/v1alpha2:go_default_library",
|
"//pkg/scheduler/apis/config/v1alpha2:go_default_library",
|
||||||
"//pkg/scheduler/apis/config/validation:go_default_library",
|
"//pkg/scheduler/apis/config/validation:go_default_library",
|
||||||
"//pkg/scheduler/framework/plugins:go_default_library",
|
|
||||||
"//pkg/scheduler/framework/plugins/interpodaffinity:go_default_library",
|
"//pkg/scheduler/framework/plugins/interpodaffinity:go_default_library",
|
||||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||||
|
@ -21,10 +21,8 @@ import (
|
|||||||
|
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||||
kubeschedulerv1alpha2 "k8s.io/kube-scheduler/config/v1alpha2"
|
|
||||||
"k8s.io/kubernetes/pkg/scheduler/algorithmprovider"
|
"k8s.io/kubernetes/pkg/scheduler/algorithmprovider"
|
||||||
kubeschedulerconfig "k8s.io/kubernetes/pkg/scheduler/apis/config"
|
kubeschedulerconfig "k8s.io/kubernetes/pkg/scheduler/apis/config"
|
||||||
"k8s.io/kubernetes/pkg/scheduler/framework/plugins"
|
|
||||||
"k8s.io/kubernetes/pkg/scheduler/framework/plugins/interpodaffinity"
|
"k8s.io/kubernetes/pkg/scheduler/framework/plugins/interpodaffinity"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -129,10 +127,13 @@ func (o *DeprecatedOptions) ApplyTo(cfg *kubeschedulerconfig.KubeSchedulerConfig
|
|||||||
profile.SchedulerName = o.SchedulerName
|
profile.SchedulerName = o.SchedulerName
|
||||||
}
|
}
|
||||||
if o.HardPodAffinitySymmetricWeight != interpodaffinity.DefaultHardPodAffinityWeight {
|
if o.HardPodAffinitySymmetricWeight != interpodaffinity.DefaultHardPodAffinityWeight {
|
||||||
args := kubeschedulerv1alpha2.InterPodAffinityArgs{
|
plCfg := kubeschedulerconfig.PluginConfig{
|
||||||
HardPodAffinityWeight: &o.HardPodAffinitySymmetricWeight,
|
Name: interpodaffinity.Name,
|
||||||
|
Args: &kubeschedulerconfig.InterPodAffinityArgs{
|
||||||
|
HardPodAffinityWeight: o.HardPodAffinitySymmetricWeight,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
profile.PluginConfig = append(profile.PluginConfig, plugins.NewPluginConfig(interpodaffinity.Name, args))
|
profile.PluginConfig = append(profile.PluginConfig, plCfg)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -203,6 +203,9 @@ profiles:
|
|||||||
disabled:
|
disabled:
|
||||||
- name: baz
|
- name: baz
|
||||||
pluginConfig:
|
pluginConfig:
|
||||||
|
- name: InterPodAffinity
|
||||||
|
args:
|
||||||
|
hardPodAffinityWeight: 2
|
||||||
- name: foo
|
- name: foo
|
||||||
args:
|
args:
|
||||||
bar: baz
|
bar: baz
|
||||||
@ -543,6 +546,12 @@ profiles:
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
PluginConfig: []kubeschedulerconfig.PluginConfig{
|
PluginConfig: []kubeschedulerconfig.PluginConfig{
|
||||||
|
{
|
||||||
|
Name: "InterPodAffinity",
|
||||||
|
Args: &kubeschedulerconfig.InterPodAffinityArgs{
|
||||||
|
HardPodAffinityWeight: 2,
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
Name: "foo",
|
Name: "foo",
|
||||||
Args: &runtime.Unknown{
|
Args: &runtime.Unknown{
|
||||||
@ -670,9 +679,7 @@ profiles:
|
|||||||
PluginConfig: []kubeschedulerconfig.PluginConfig{
|
PluginConfig: []kubeschedulerconfig.PluginConfig{
|
||||||
{
|
{
|
||||||
Name: "InterPodAffinity",
|
Name: "InterPodAffinity",
|
||||||
Args: &runtime.Unknown{
|
Args: &kubeschedulerconfig.InterPodAffinityArgs{HardPodAffinityWeight: 5},
|
||||||
Raw: []byte(`{"hardPodAffinityWeight":5}`),
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -45,7 +45,6 @@ go_library(
|
|||||||
"//staging/src/k8s.io/client-go/listers/core/v1:go_default_library",
|
"//staging/src/k8s.io/client-go/listers/core/v1:go_default_library",
|
||||||
"//staging/src/k8s.io/client-go/listers/policy/v1beta1:go_default_library",
|
"//staging/src/k8s.io/client-go/listers/policy/v1beta1:go_default_library",
|
||||||
"//staging/src/k8s.io/client-go/tools/cache:go_default_library",
|
"//staging/src/k8s.io/client-go/tools/cache:go_default_library",
|
||||||
"//staging/src/k8s.io/kube-scheduler/config/v1alpha2:go_default_library",
|
|
||||||
"//vendor/github.com/google/go-cmp/cmp:go_default_library",
|
"//vendor/github.com/google/go-cmp/cmp:go_default_library",
|
||||||
"//vendor/k8s.io/klog:go_default_library",
|
"//vendor/k8s.io/klog:go_default_library",
|
||||||
],
|
],
|
||||||
|
@ -25,7 +25,6 @@ import (
|
|||||||
|
|
||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
|
||||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||||
"k8s.io/client-go/informers"
|
"k8s.io/client-go/informers"
|
||||||
"k8s.io/client-go/kubernetes/fake"
|
"k8s.io/client-go/kubernetes/fake"
|
||||||
@ -1598,90 +1597,58 @@ func TestPluginsConfigurationCompatibility(t *testing.T) {
|
|||||||
pluginConfig: []config.PluginConfig{
|
pluginConfig: []config.PluginConfig{
|
||||||
{
|
{
|
||||||
Name: "NodeResourcesFit",
|
Name: "NodeResourcesFit",
|
||||||
Args: &runtime.Unknown{
|
Args: &config.NodeResourcesFitArgs{
|
||||||
Raw: []byte(`{
|
IgnoredResources: []string{"foo", "bar"},
|
||||||
"ignoredResources": [
|
|
||||||
"foo",
|
|
||||||
"bar"
|
|
||||||
]
|
|
||||||
}`),
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "PodTopologySpread",
|
Name: "PodTopologySpread",
|
||||||
Args: &runtime.Unknown{
|
Args: &config.PodTopologySpreadArgs{
|
||||||
Raw: []byte(`{
|
DefaultConstraints: []v1.TopologySpreadConstraint{
|
||||||
"defaultConstraints": [
|
{
|
||||||
{
|
MaxSkew: 1,
|
||||||
"maxSkew": 1,
|
TopologyKey: "foo",
|
||||||
"topologyKey": "foo",
|
WhenUnsatisfiable: v1.DoNotSchedule,
|
||||||
"whenUnsatisfiable": "DoNotSchedule"
|
},
|
||||||
},
|
{
|
||||||
{
|
MaxSkew: 10,
|
||||||
"maxSkew": 10,
|
TopologyKey: "bar",
|
||||||
"topologyKey": "bar",
|
WhenUnsatisfiable: v1.ScheduleAnyway,
|
||||||
"whenUnsatisfiable": "ScheduleAnyway"
|
},
|
||||||
}
|
},
|
||||||
]
|
|
||||||
}`),
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "RequestedToCapacityRatio",
|
Name: "RequestedToCapacityRatio",
|
||||||
Args: &runtime.Unknown{
|
Args: &config.RequestedToCapacityRatioArgs{
|
||||||
Raw: []byte(`{
|
Shape: []config.UtilizationShapePoint{
|
||||||
"shape":[
|
{Utilization: 5, Score: 5},
|
||||||
"Utilization": 5,
|
},
|
||||||
"Score": 5
|
Resources: []config.ResourceSpec{
|
||||||
],
|
{Name: "cpu", Weight: 10},
|
||||||
"resources":[
|
},
|
||||||
"Name": "cpu",
|
|
||||||
"Weight": 10
|
|
||||||
]
|
|
||||||
}`),
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "InterPodAffinity",
|
Name: "InterPodAffinity",
|
||||||
Args: &runtime.Unknown{
|
Args: &config.InterPodAffinityArgs{
|
||||||
Raw: []byte(`{
|
HardPodAffinityWeight: 100,
|
||||||
"HardPodAffinityWeight": 100
|
|
||||||
}`),
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "NodeLabel",
|
Name: "NodeLabel",
|
||||||
Args: &runtime.Unknown{
|
Args: &config.NodeLabelArgs{
|
||||||
Raw: []byte(`{
|
PresentLabels: []string{"foo", "bar"},
|
||||||
"presentLabels": [
|
AbsentLabels: []string{"apple"},
|
||||||
"foo",
|
PresentLabelsPreference: []string{"dog"},
|
||||||
"bar"
|
AbsentLabelsPreference: []string{"cat"},
|
||||||
],
|
|
||||||
"absentLabels": [
|
|
||||||
"apple"
|
|
||||||
],
|
|
||||||
"presentLabelsPreference": [
|
|
||||||
"dog"
|
|
||||||
],
|
|
||||||
"absentLabelsPreference": [
|
|
||||||
"cat"
|
|
||||||
]
|
|
||||||
}`),
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "ServiceAffinity",
|
Name: "ServiceAffinity",
|
||||||
Args: &runtime.Unknown{
|
Args: &config.ServiceAffinityArgs{
|
||||||
Raw: []byte(`{
|
AffinityLabels: []string{"foo", "bar"},
|
||||||
affinityLabels: [
|
AntiAffinityLabelsPreference: []string{"disk", "flash"},
|
||||||
"foo",
|
|
||||||
"bar"
|
|
||||||
],
|
|
||||||
antiAffinityLabelsPreference: [
|
|
||||||
"disk",
|
|
||||||
"flash"
|
|
||||||
]
|
|
||||||
}`),
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -40,7 +40,6 @@ import (
|
|||||||
policylisters "k8s.io/client-go/listers/policy/v1beta1"
|
policylisters "k8s.io/client-go/listers/policy/v1beta1"
|
||||||
"k8s.io/client-go/tools/cache"
|
"k8s.io/client-go/tools/cache"
|
||||||
"k8s.io/klog"
|
"k8s.io/klog"
|
||||||
schedulerv1alpha2 "k8s.io/kube-scheduler/config/v1alpha2"
|
|
||||||
"k8s.io/kubernetes/pkg/controller/volume/scheduling"
|
"k8s.io/kubernetes/pkg/controller/volume/scheduling"
|
||||||
kubefeatures "k8s.io/kubernetes/pkg/features"
|
kubefeatures "k8s.io/kubernetes/pkg/features"
|
||||||
"k8s.io/kubernetes/pkg/scheduler/algorithmprovider"
|
"k8s.io/kubernetes/pkg/scheduler/algorithmprovider"
|
||||||
@ -162,12 +161,13 @@ func (c *Configurator) create() (*Scheduler, error) {
|
|||||||
if len(ignoredExtendedResources) > 0 {
|
if len(ignoredExtendedResources) > 0 {
|
||||||
for i := range c.profiles {
|
for i := range c.profiles {
|
||||||
prof := &c.profiles[i]
|
prof := &c.profiles[i]
|
||||||
prof.PluginConfig = append(prof.PluginConfig,
|
pc := schedulerapi.PluginConfig{
|
||||||
frameworkplugins.NewPluginConfig(
|
Name: noderesources.FitName,
|
||||||
noderesources.FitName,
|
Args: &schedulerapi.NodeResourcesFitArgs{
|
||||||
schedulerv1alpha2.NodeResourcesFitArgs{IgnoredResources: ignoredExtendedResources},
|
IgnoredResources: ignoredExtendedResources,
|
||||||
),
|
},
|
||||||
)
|
}
|
||||||
|
prof.PluginConfig = append(prof.PluginConfig, pc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -280,9 +280,8 @@ func (c *Configurator) createFromConfig(policy schedulerapi.Policy) (*Scheduler,
|
|||||||
// HardPodAffinitySymmetricWeight in the policy config takes precedence over
|
// HardPodAffinitySymmetricWeight in the policy config takes precedence over
|
||||||
// CLI configuration.
|
// CLI configuration.
|
||||||
if policy.HardPodAffinitySymmetricWeight != 0 {
|
if policy.HardPodAffinitySymmetricWeight != 0 {
|
||||||
v := policy.HardPodAffinitySymmetricWeight
|
args.InterPodAffinityArgs = &schedulerapi.InterPodAffinityArgs{
|
||||||
args.InterPodAffinityArgs = &schedulerv1alpha2.InterPodAffinityArgs{
|
HardPodAffinityWeight: policy.HardPodAffinitySymmetricWeight,
|
||||||
HardPodAffinityWeight: &v,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,7 +18,6 @@ package scheduler
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
"errors"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
@ -161,10 +160,18 @@ func TestCreateFromConfig(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Verify that node label predicate/priority are converted to framework plugins.
|
// Verify that node label predicate/priority are converted to framework plugins.
|
||||||
wantArgs := `{"Name":"NodeLabel","Args":{"presentLabels":["zone"],"absentLabels":["foo"],"presentLabelsPreference":["l1"],"absentLabelsPreference":["l2"]}}`
|
var wantArgs runtime.Object = &schedulerapi.NodeLabelArgs{
|
||||||
|
PresentLabels: []string{"zone"},
|
||||||
|
AbsentLabels: []string{"foo"},
|
||||||
|
PresentLabelsPreference: []string{"l1"},
|
||||||
|
AbsentLabelsPreference: []string{"l2"},
|
||||||
|
}
|
||||||
verifyPluginConvertion(t, nodelabel.Name, []string{"FilterPlugin", "ScorePlugin"}, prof, &factory.profiles[0], 6, wantArgs)
|
verifyPluginConvertion(t, nodelabel.Name, []string{"FilterPlugin", "ScorePlugin"}, prof, &factory.profiles[0], 6, wantArgs)
|
||||||
// Verify that service affinity custom predicate/priority is converted to framework plugin.
|
// Verify that service affinity custom predicate/priority is converted to framework plugin.
|
||||||
wantArgs = `{"Name":"ServiceAffinity","Args":{"affinityLabels":["zone","foo"],"antiAffinityLabelsPreference":["rack","zone"]}}`
|
wantArgs = &schedulerapi.ServiceAffinityArgs{
|
||||||
|
AffinityLabels: []string{"zone", "foo"},
|
||||||
|
AntiAffinityLabelsPreference: []string{"rack", "zone"},
|
||||||
|
}
|
||||||
verifyPluginConvertion(t, serviceaffinity.Name, []string{"FilterPlugin", "ScorePlugin"}, prof, &factory.profiles[0], 6, wantArgs)
|
verifyPluginConvertion(t, serviceaffinity.Name, []string{"FilterPlugin", "ScorePlugin"}, prof, &factory.profiles[0], 6, wantArgs)
|
||||||
// TODO(#87703): Verify all plugin configs.
|
// TODO(#87703): Verify all plugin configs.
|
||||||
})
|
})
|
||||||
@ -172,8 +179,8 @@ func TestCreateFromConfig(t *testing.T) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func verifyPluginConvertion(t *testing.T, name string, extentionPoints []string, prof *profile.Profile, cfg *schedulerapi.KubeSchedulerProfile, wantWeight int32, wantArgs string) {
|
func verifyPluginConvertion(t *testing.T, name string, extensionPoints []string, prof *profile.Profile, cfg *schedulerapi.KubeSchedulerProfile, wantWeight int32, wantArgs runtime.Object) {
|
||||||
for _, extensionPoint := range extentionPoints {
|
for _, extensionPoint := range extensionPoints {
|
||||||
plugin, ok := findPlugin(name, extensionPoint, prof)
|
plugin, ok := findPlugin(name, extensionPoint, prof)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatalf("%q plugin does not exist in framework.", name)
|
t.Fatalf("%q plugin does not exist in framework.", name)
|
||||||
@ -185,12 +192,8 @@ func verifyPluginConvertion(t *testing.T, name string, extentionPoints []string,
|
|||||||
}
|
}
|
||||||
// Verify that the policy config is converted to plugin config.
|
// Verify that the policy config is converted to plugin config.
|
||||||
pluginConfig := findPluginConfig(name, cfg)
|
pluginConfig := findPluginConfig(name, cfg)
|
||||||
encoding, err := json.Marshal(pluginConfig)
|
if diff := cmp.Diff(wantArgs, pluginConfig.Args); diff != "" {
|
||||||
if err != nil {
|
t.Errorf("Config for %v plugin mismatch (-want,+got):\n%s", name, diff)
|
||||||
t.Errorf("Failed to marshal %+v: %v", pluginConfig, err)
|
|
||||||
}
|
|
||||||
if string(encoding) != wantArgs {
|
|
||||||
t.Errorf("Config for %v plugin mismatch. got: %v, want: %v", name, string(encoding), wantArgs)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -250,7 +253,7 @@ func TestCreateFromConfigWithHardPodAffinitySymmetricWeight(t *testing.T) {
|
|||||||
for _, cfg := range factory.profiles[0].PluginConfig {
|
for _, cfg := range factory.profiles[0].PluginConfig {
|
||||||
if cfg.Name == interpodaffinity.Name {
|
if cfg.Name == interpodaffinity.Name {
|
||||||
foundAffinityCfg = true
|
foundAffinityCfg = true
|
||||||
wantArgs := &runtime.Unknown{Raw: []byte(`{"hardPodAffinityWeight":10}`)}
|
wantArgs := &schedulerapi.InterPodAffinityArgs{HardPodAffinityWeight: 10}
|
||||||
|
|
||||||
if diff := cmp.Diff(wantArgs, cfg.Args); diff != "" {
|
if diff := cmp.Diff(wantArgs, cfg.Args); diff != "" {
|
||||||
t.Errorf("wrong InterPodAffinity args (-want, +got): %s", diff)
|
t.Errorf("wrong InterPodAffinity args (-want, +got): %s", diff)
|
||||||
|
@ -31,10 +31,8 @@ go_library(
|
|||||||
"//pkg/scheduler/framework/plugins/volumerestrictions:go_default_library",
|
"//pkg/scheduler/framework/plugins/volumerestrictions:go_default_library",
|
||||||
"//pkg/scheduler/framework/plugins/volumezone:go_default_library",
|
"//pkg/scheduler/framework/plugins/volumezone:go_default_library",
|
||||||
"//pkg/scheduler/framework/v1alpha1:go_default_library",
|
"//pkg/scheduler/framework/v1alpha1:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||||
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||||
"//staging/src/k8s.io/kube-scheduler/config/v1alpha2:go_default_library",
|
|
||||||
"//vendor/k8s.io/klog:go_default_library",
|
"//vendor/k8s.io/klog:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
@ -10,6 +10,7 @@ go_library(
|
|||||||
importpath = "k8s.io/kubernetes/pkg/scheduler/framework/plugins/interpodaffinity",
|
importpath = "k8s.io/kubernetes/pkg/scheduler/framework/plugins/interpodaffinity",
|
||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
deps = [
|
deps = [
|
||||||
|
"//pkg/scheduler/apis/config:go_default_library",
|
||||||
"//pkg/scheduler/framework/v1alpha1:go_default_library",
|
"//pkg/scheduler/framework/v1alpha1:go_default_library",
|
||||||
"//pkg/scheduler/internal/parallelize:go_default_library",
|
"//pkg/scheduler/internal/parallelize:go_default_library",
|
||||||
"//pkg/scheduler/util:go_default_library",
|
"//pkg/scheduler/util:go_default_library",
|
||||||
@ -19,9 +20,7 @@ go_library(
|
|||||||
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
|
||||||
"//staging/src/k8s.io/kube-scheduler/config/v1alpha2:go_default_library",
|
|
||||||
"//vendor/k8s.io/klog:go_default_library",
|
"//vendor/k8s.io/klog:go_default_library",
|
||||||
"//vendor/k8s.io/utils/pointer:go_default_library",
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -33,13 +32,11 @@ go_test(
|
|||||||
],
|
],
|
||||||
embed = [":go_default_library"],
|
embed = [":go_default_library"],
|
||||||
deps = [
|
deps = [
|
||||||
|
"//pkg/scheduler/apis/config:go_default_library",
|
||||||
"//pkg/scheduler/framework/v1alpha1:go_default_library",
|
"//pkg/scheduler/framework/v1alpha1:go_default_library",
|
||||||
"//pkg/scheduler/internal/cache:go_default_library",
|
"//pkg/scheduler/internal/cache:go_default_library",
|
||||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
|
||||||
"//staging/src/k8s.io/kube-scheduler/config/v1alpha2:go_default_library",
|
|
||||||
"//vendor/k8s.io/utils/pointer:go_default_library",
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -22,9 +22,8 @@ import (
|
|||||||
|
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||||
schedulerv1alpha2 "k8s.io/kube-scheduler/config/v1alpha2"
|
"k8s.io/kubernetes/pkg/scheduler/apis/config"
|
||||||
framework "k8s.io/kubernetes/pkg/scheduler/framework/v1alpha1"
|
framework "k8s.io/kubernetes/pkg/scheduler/framework/v1alpha1"
|
||||||
"k8s.io/utils/pointer"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -46,7 +45,7 @@ var _ framework.ScorePlugin = &InterPodAffinity{}
|
|||||||
|
|
||||||
// InterPodAffinity is a plugin that checks inter pod affinity
|
// InterPodAffinity is a plugin that checks inter pod affinity
|
||||||
type InterPodAffinity struct {
|
type InterPodAffinity struct {
|
||||||
args schedulerv1alpha2.InterPodAffinityArgs
|
args config.InterPodAffinityArgs
|
||||||
sharedLister framework.SharedLister
|
sharedLister framework.SharedLister
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
}
|
}
|
||||||
@ -66,26 +65,30 @@ func New(plArgs runtime.Object, h framework.FrameworkHandle) (framework.Plugin,
|
|||||||
if h.SnapshotSharedLister() == nil {
|
if h.SnapshotSharedLister() == nil {
|
||||||
return nil, fmt.Errorf("SnapshotSharedlister is nil")
|
return nil, fmt.Errorf("SnapshotSharedlister is nil")
|
||||||
}
|
}
|
||||||
pl := &InterPodAffinity{
|
args, err := getArgs(plArgs)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := ValidateHardPodAffinityWeight(field.NewPath("hardPodAffinityWeight"), args.HardPodAffinityWeight); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &InterPodAffinity{
|
||||||
|
args: args,
|
||||||
sharedLister: h.SnapshotSharedLister(),
|
sharedLister: h.SnapshotSharedLister(),
|
||||||
}
|
}, nil
|
||||||
if err := framework.DecodeInto(plArgs, &pl.args); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if err := validateArgs(&pl.args); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if pl.args.HardPodAffinityWeight == nil {
|
|
||||||
pl.args.HardPodAffinityWeight = pointer.Int32Ptr(DefaultHardPodAffinityWeight)
|
|
||||||
}
|
|
||||||
return pl, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateArgs(args *schedulerv1alpha2.InterPodAffinityArgs) error {
|
func getArgs(obj runtime.Object) (config.InterPodAffinityArgs, error) {
|
||||||
if args.HardPodAffinityWeight == nil {
|
if obj == nil {
|
||||||
return nil
|
return config.InterPodAffinityArgs{
|
||||||
|
HardPodAffinityWeight: DefaultHardPodAffinityWeight,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
return ValidateHardPodAffinityWeight(field.NewPath("hardPodAffinityWeight"), *args.HardPodAffinityWeight)
|
ptr, ok := obj.(*config.InterPodAffinityArgs)
|
||||||
|
if !ok {
|
||||||
|
return config.InterPodAffinityArgs{}, fmt.Errorf("want args to be of type InterPodAffinityArgs, got %T", obj)
|
||||||
|
}
|
||||||
|
return *ptr, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ValidateHardPodAffinityWeight validates that weight is within allowed range.
|
// ValidateHardPodAffinityWeight validates that weight is within allowed range.
|
||||||
|
@ -137,7 +137,7 @@ func (pl *InterPodAffinity) processExistingPod(state *preScoreState, existingPod
|
|||||||
// For every hard pod affinity term of <existingPod>, if <pod> matches the term,
|
// For every hard pod affinity term of <existingPod>, if <pod> matches the term,
|
||||||
// increment <p.counts> for every node in the cluster with the same <term.TopologyKey>
|
// increment <p.counts> for every node in the cluster with the same <term.TopologyKey>
|
||||||
// value as that of <existingPod>'s node by the constant <ipa.hardPodAffinityWeight>
|
// value as that of <existingPod>'s node by the constant <ipa.hardPodAffinityWeight>
|
||||||
if *pl.args.HardPodAffinityWeight > 0 {
|
if pl.args.HardPodAffinityWeight > 0 {
|
||||||
terms := existingPodAffinity.PodAffinity.RequiredDuringSchedulingIgnoredDuringExecution
|
terms := existingPodAffinity.PodAffinity.RequiredDuringSchedulingIgnoredDuringExecution
|
||||||
// TODO: Uncomment this block when implement RequiredDuringSchedulingRequiredDuringExecution.
|
// TODO: Uncomment this block when implement RequiredDuringSchedulingRequiredDuringExecution.
|
||||||
//if len(existingPodAffinity.PodAffinity.RequiredDuringSchedulingRequiredDuringExecution) != 0 {
|
//if len(existingPodAffinity.PodAffinity.RequiredDuringSchedulingRequiredDuringExecution) != 0 {
|
||||||
@ -145,7 +145,7 @@ func (pl *InterPodAffinity) processExistingPod(state *preScoreState, existingPod
|
|||||||
//}
|
//}
|
||||||
for i := range terms {
|
for i := range terms {
|
||||||
term := &terms[i]
|
term := &terms[i]
|
||||||
processedTerm, err := newWeightedAffinityTerm(existingPod, term, *pl.args.HardPodAffinityWeight)
|
processedTerm, err := newWeightedAffinityTerm(existingPod, term, pl.args.HardPodAffinityWeight)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -18,17 +18,14 @@ package interpodaffinity
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/kubernetes/pkg/scheduler/apis/config"
|
||||||
schedulerv1alpha2 "k8s.io/kube-scheduler/config/v1alpha2"
|
|
||||||
framework "k8s.io/kubernetes/pkg/scheduler/framework/v1alpha1"
|
framework "k8s.io/kubernetes/pkg/scheduler/framework/v1alpha1"
|
||||||
"k8s.io/kubernetes/pkg/scheduler/internal/cache"
|
"k8s.io/kubernetes/pkg/scheduler/internal/cache"
|
||||||
"k8s.io/utils/pointer"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestPreferredAffinity(t *testing.T) {
|
func TestPreferredAffinity(t *testing.T) {
|
||||||
@ -521,8 +518,8 @@ func TestPreferredAffinity(t *testing.T) {
|
|||||||
state := framework.NewCycleState()
|
state := framework.NewCycleState()
|
||||||
snapshot := cache.NewSnapshot(test.pods, test.nodes)
|
snapshot := cache.NewSnapshot(test.pods, test.nodes)
|
||||||
p := &InterPodAffinity{
|
p := &InterPodAffinity{
|
||||||
args: schedulerv1alpha2.InterPodAffinityArgs{
|
args: config.InterPodAffinityArgs{
|
||||||
HardPodAffinityWeight: pointer.Int32Ptr(DefaultHardPodAffinityWeight),
|
HardPodAffinityWeight: DefaultHardPodAffinityWeight,
|
||||||
},
|
},
|
||||||
sharedLister: snapshot,
|
sharedLister: snapshot,
|
||||||
}
|
}
|
||||||
@ -630,7 +627,7 @@ func TestPreferredAffinityWithHardPodAffinitySymmetricWeight(t *testing.T) {
|
|||||||
snapshot := cache.NewSnapshot(test.pods, test.nodes)
|
snapshot := cache.NewSnapshot(test.pods, test.nodes)
|
||||||
fh, _ := framework.NewFramework(nil, nil, nil, framework.WithSnapshotSharedLister(snapshot))
|
fh, _ := framework.NewFramework(nil, nil, nil, framework.WithSnapshotSharedLister(snapshot))
|
||||||
|
|
||||||
args := &runtime.Unknown{Raw: []byte(fmt.Sprintf(`{"hardPodAffinityWeight":%d}`, test.hardPodAffinityWeight))}
|
args := &config.InterPodAffinityArgs{HardPodAffinityWeight: test.hardPodAffinityWeight}
|
||||||
p, err := New(args, fh)
|
p, err := New(args, fh)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
@ -17,13 +17,9 @@ limitations under the License.
|
|||||||
package plugins
|
package plugins
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
|
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
|
||||||
"k8s.io/apimachinery/pkg/util/sets"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||||
"k8s.io/klog"
|
"k8s.io/klog"
|
||||||
schedulerv1alpha2 "k8s.io/kube-scheduler/config/v1alpha2"
|
|
||||||
"k8s.io/kubernetes/pkg/features"
|
"k8s.io/kubernetes/pkg/features"
|
||||||
"k8s.io/kubernetes/pkg/scheduler/apis/config"
|
"k8s.io/kubernetes/pkg/scheduler/apis/config"
|
||||||
"k8s.io/kubernetes/pkg/scheduler/framework/plugins/defaultpodtopologyspread"
|
"k8s.io/kubernetes/pkg/scheduler/framework/plugins/defaultpodtopologyspread"
|
||||||
@ -165,15 +161,15 @@ type ConfigProducerArgs struct {
|
|||||||
// Weight used for priority functions.
|
// Weight used for priority functions.
|
||||||
Weight int32
|
Weight int32
|
||||||
// NodeLabelArgs is the args for the NodeLabel plugin.
|
// NodeLabelArgs is the args for the NodeLabel plugin.
|
||||||
NodeLabelArgs *schedulerv1alpha2.NodeLabelArgs
|
NodeLabelArgs *config.NodeLabelArgs
|
||||||
// RequestedToCapacityRatioArgs is the args for the RequestedToCapacityRatio plugin.
|
// RequestedToCapacityRatioArgs is the args for the RequestedToCapacityRatio plugin.
|
||||||
RequestedToCapacityRatioArgs *schedulerv1alpha2.RequestedToCapacityRatioArgs
|
RequestedToCapacityRatioArgs *config.RequestedToCapacityRatioArgs
|
||||||
// ServiceAffinityArgs is the args for the ServiceAffinity plugin.
|
// ServiceAffinityArgs is the args for the ServiceAffinity plugin.
|
||||||
ServiceAffinityArgs *schedulerv1alpha2.ServiceAffinityArgs
|
ServiceAffinityArgs *config.ServiceAffinityArgs
|
||||||
// NodeResourcesFitArgs is the args for the NodeResources fit filter.
|
// NodeResourcesFitArgs is the args for the NodeResources fit filter.
|
||||||
NodeResourcesFitArgs *schedulerv1alpha2.NodeResourcesFitArgs
|
NodeResourcesFitArgs *config.NodeResourcesFitArgs
|
||||||
// InterPodAffinityArgs is the args for InterPodAffinity plugin
|
// InterPodAffinityArgs is the args for InterPodAffinity plugin
|
||||||
InterPodAffinityArgs *schedulerv1alpha2.InterPodAffinityArgs
|
InterPodAffinityArgs *config.InterPodAffinityArgs
|
||||||
}
|
}
|
||||||
|
|
||||||
// ConfigProducer returns the set of plugins and their configuration for a
|
// ConfigProducer returns the set of plugins and their configuration for a
|
||||||
@ -227,7 +223,8 @@ func NewLegacyRegistry() *LegacyRegistry {
|
|||||||
plugins.Filter = appendToPluginSet(plugins.Filter, noderesources.FitName, nil)
|
plugins.Filter = appendToPluginSet(plugins.Filter, noderesources.FitName, nil)
|
||||||
plugins.PreFilter = appendToPluginSet(plugins.PreFilter, noderesources.FitName, nil)
|
plugins.PreFilter = appendToPluginSet(plugins.PreFilter, noderesources.FitName, nil)
|
||||||
if args.NodeResourcesFitArgs != nil {
|
if args.NodeResourcesFitArgs != nil {
|
||||||
pluginConfig = append(pluginConfig, NewPluginConfig(noderesources.FitName, args.NodeResourcesFitArgs))
|
pluginConfig = append(pluginConfig,
|
||||||
|
config.PluginConfig{Name: noderesources.FitName, Args: args.NodeResourcesFitArgs})
|
||||||
}
|
}
|
||||||
plugins.Filter = appendToPluginSet(plugins.Filter, nodename.Name, nil)
|
plugins.Filter = appendToPluginSet(plugins.Filter, nodename.Name, nil)
|
||||||
plugins.Filter = appendToPluginSet(plugins.Filter, nodeports.Name, nil)
|
plugins.Filter = appendToPluginSet(plugins.Filter, nodeports.Name, nil)
|
||||||
@ -245,7 +242,8 @@ func NewLegacyRegistry() *LegacyRegistry {
|
|||||||
plugins.Filter = appendToPluginSet(plugins.Filter, noderesources.FitName, nil)
|
plugins.Filter = appendToPluginSet(plugins.Filter, noderesources.FitName, nil)
|
||||||
plugins.PreFilter = appendToPluginSet(plugins.PreFilter, noderesources.FitName, nil)
|
plugins.PreFilter = appendToPluginSet(plugins.PreFilter, noderesources.FitName, nil)
|
||||||
if args.NodeResourcesFitArgs != nil {
|
if args.NodeResourcesFitArgs != nil {
|
||||||
pluginConfig = append(pluginConfig, NewPluginConfig(noderesources.FitName, args.NodeResourcesFitArgs))
|
pluginConfig = append(pluginConfig,
|
||||||
|
config.PluginConfig{Name: noderesources.FitName, Args: args.NodeResourcesFitArgs})
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
})
|
})
|
||||||
@ -320,7 +318,8 @@ func NewLegacyRegistry() *LegacyRegistry {
|
|||||||
func(args ConfigProducerArgs) (plugins config.Plugins, pluginConfig []config.PluginConfig) {
|
func(args ConfigProducerArgs) (plugins config.Plugins, pluginConfig []config.PluginConfig) {
|
||||||
plugins.Filter = appendToPluginSet(plugins.Filter, nodelabel.Name, nil)
|
plugins.Filter = appendToPluginSet(plugins.Filter, nodelabel.Name, nil)
|
||||||
if args.NodeLabelArgs != nil {
|
if args.NodeLabelArgs != nil {
|
||||||
pluginConfig = append(pluginConfig, NewPluginConfig(nodelabel.Name, args.NodeLabelArgs))
|
pluginConfig = append(pluginConfig,
|
||||||
|
config.PluginConfig{Name: nodelabel.Name, Args: args.NodeLabelArgs})
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
})
|
})
|
||||||
@ -328,7 +327,8 @@ func NewLegacyRegistry() *LegacyRegistry {
|
|||||||
func(args ConfigProducerArgs) (plugins config.Plugins, pluginConfig []config.PluginConfig) {
|
func(args ConfigProducerArgs) (plugins config.Plugins, pluginConfig []config.PluginConfig) {
|
||||||
plugins.Filter = appendToPluginSet(plugins.Filter, serviceaffinity.Name, nil)
|
plugins.Filter = appendToPluginSet(plugins.Filter, serviceaffinity.Name, nil)
|
||||||
if args.ServiceAffinityArgs != nil {
|
if args.ServiceAffinityArgs != nil {
|
||||||
pluginConfig = append(pluginConfig, NewPluginConfig(serviceaffinity.Name, args.ServiceAffinityArgs))
|
pluginConfig = append(pluginConfig,
|
||||||
|
config.PluginConfig{Name: serviceaffinity.Name, Args: args.ServiceAffinityArgs})
|
||||||
}
|
}
|
||||||
plugins.PreFilter = appendToPluginSet(plugins.PreFilter, serviceaffinity.Name, nil)
|
plugins.PreFilter = appendToPluginSet(plugins.PreFilter, serviceaffinity.Name, nil)
|
||||||
return
|
return
|
||||||
@ -362,7 +362,8 @@ func NewLegacyRegistry() *LegacyRegistry {
|
|||||||
plugins.PreScore = appendToPluginSet(plugins.PreScore, interpodaffinity.Name, nil)
|
plugins.PreScore = appendToPluginSet(plugins.PreScore, interpodaffinity.Name, nil)
|
||||||
plugins.Score = appendToPluginSet(plugins.Score, interpodaffinity.Name, &args.Weight)
|
plugins.Score = appendToPluginSet(plugins.Score, interpodaffinity.Name, &args.Weight)
|
||||||
if args.InterPodAffinityArgs != nil {
|
if args.InterPodAffinityArgs != nil {
|
||||||
pluginConfig = append(pluginConfig, NewPluginConfig(interpodaffinity.Name, args.InterPodAffinityArgs))
|
pluginConfig = append(pluginConfig,
|
||||||
|
config.PluginConfig{Name: interpodaffinity.Name, Args: args.InterPodAffinityArgs})
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
})
|
})
|
||||||
@ -390,7 +391,8 @@ func NewLegacyRegistry() *LegacyRegistry {
|
|||||||
func(args ConfigProducerArgs) (plugins config.Plugins, pluginConfig []config.PluginConfig) {
|
func(args ConfigProducerArgs) (plugins config.Plugins, pluginConfig []config.PluginConfig) {
|
||||||
plugins.Score = appendToPluginSet(plugins.Score, noderesources.RequestedToCapacityRatioName, &args.Weight)
|
plugins.Score = appendToPluginSet(plugins.Score, noderesources.RequestedToCapacityRatioName, &args.Weight)
|
||||||
if args.RequestedToCapacityRatioArgs != nil {
|
if args.RequestedToCapacityRatioArgs != nil {
|
||||||
pluginConfig = append(pluginConfig, NewPluginConfig(noderesources.RequestedToCapacityRatioName, args.RequestedToCapacityRatioArgs))
|
pluginConfig = append(pluginConfig,
|
||||||
|
config.PluginConfig{Name: noderesources.RequestedToCapacityRatioName, Args: args.RequestedToCapacityRatioArgs})
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
})
|
})
|
||||||
@ -403,7 +405,8 @@ func NewLegacyRegistry() *LegacyRegistry {
|
|||||||
weight := args.Weight * int32(len(args.NodeLabelArgs.PresentLabelsPreference)+len(args.NodeLabelArgs.AbsentLabelsPreference))
|
weight := args.Weight * int32(len(args.NodeLabelArgs.PresentLabelsPreference)+len(args.NodeLabelArgs.AbsentLabelsPreference))
|
||||||
plugins.Score = appendToPluginSet(plugins.Score, nodelabel.Name, &weight)
|
plugins.Score = appendToPluginSet(plugins.Score, nodelabel.Name, &weight)
|
||||||
if args.NodeLabelArgs != nil {
|
if args.NodeLabelArgs != nil {
|
||||||
pluginConfig = append(pluginConfig, NewPluginConfig(nodelabel.Name, args.NodeLabelArgs))
|
pluginConfig = append(pluginConfig,
|
||||||
|
config.PluginConfig{Name: nodelabel.Name, Args: args.NodeLabelArgs})
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
})
|
})
|
||||||
@ -415,7 +418,8 @@ func NewLegacyRegistry() *LegacyRegistry {
|
|||||||
weight := args.Weight * int32(len(args.ServiceAffinityArgs.AntiAffinityLabelsPreference))
|
weight := args.Weight * int32(len(args.ServiceAffinityArgs.AntiAffinityLabelsPreference))
|
||||||
plugins.Score = appendToPluginSet(plugins.Score, serviceaffinity.Name, &weight)
|
plugins.Score = appendToPluginSet(plugins.Score, serviceaffinity.Name, &weight)
|
||||||
if args.ServiceAffinityArgs != nil {
|
if args.ServiceAffinityArgs != nil {
|
||||||
pluginConfig = append(pluginConfig, NewPluginConfig(serviceaffinity.Name, args.ServiceAffinityArgs))
|
pluginConfig = append(pluginConfig,
|
||||||
|
config.PluginConfig{Name: serviceaffinity.Name, Args: args.ServiceAffinityArgs})
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
})
|
})
|
||||||
@ -487,19 +491,6 @@ func appendToPluginSet(set *config.PluginSet, name string, weight *int32) *confi
|
|||||||
return set
|
return set
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewPluginConfig builds a PluginConfig with the struct of args marshaled.
|
|
||||||
// It panics if it fails to marshal.
|
|
||||||
func NewPluginConfig(pluginName string, args interface{}) config.PluginConfig {
|
|
||||||
encoding, err := json.Marshal(args)
|
|
||||||
if err != nil {
|
|
||||||
klog.Fatalf("failed to marshal %+v: %v", args, err)
|
|
||||||
}
|
|
||||||
return config.PluginConfig{
|
|
||||||
Name: pluginName,
|
|
||||||
Args: &runtime.Unknown{Raw: encoding},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ProcessPredicatePolicy given a PredicatePolicy, return the plugin name implementing the predicate and update
|
// ProcessPredicatePolicy given a PredicatePolicy, return the plugin name implementing the predicate and update
|
||||||
// the ConfigProducerArgs if necessary.
|
// the ConfigProducerArgs if necessary.
|
||||||
func (lr *LegacyRegistry) ProcessPredicatePolicy(policy config.PredicatePolicy, pluginArgs *ConfigProducerArgs) string {
|
func (lr *LegacyRegistry) ProcessPredicatePolicy(policy config.PredicatePolicy, pluginArgs *ConfigProducerArgs) string {
|
||||||
@ -526,7 +517,7 @@ func (lr *LegacyRegistry) ProcessPredicatePolicy(policy config.PredicatePolicy,
|
|||||||
if policy.Argument.ServiceAffinity != nil {
|
if policy.Argument.ServiceAffinity != nil {
|
||||||
// map LabelsPresence policy to ConfigProducerArgs that's used to configure the ServiceAffinity plugin.
|
// map LabelsPresence policy to ConfigProducerArgs that's used to configure the ServiceAffinity plugin.
|
||||||
if pluginArgs.ServiceAffinityArgs == nil {
|
if pluginArgs.ServiceAffinityArgs == nil {
|
||||||
pluginArgs.ServiceAffinityArgs = &schedulerv1alpha2.ServiceAffinityArgs{}
|
pluginArgs.ServiceAffinityArgs = &config.ServiceAffinityArgs{}
|
||||||
}
|
}
|
||||||
pluginArgs.ServiceAffinityArgs.AffinityLabels = append(pluginArgs.ServiceAffinityArgs.AffinityLabels, policy.Argument.ServiceAffinity.Labels...)
|
pluginArgs.ServiceAffinityArgs.AffinityLabels = append(pluginArgs.ServiceAffinityArgs.AffinityLabels, policy.Argument.ServiceAffinity.Labels...)
|
||||||
|
|
||||||
@ -539,7 +530,7 @@ func (lr *LegacyRegistry) ProcessPredicatePolicy(policy config.PredicatePolicy,
|
|||||||
if policy.Argument.LabelsPresence != nil {
|
if policy.Argument.LabelsPresence != nil {
|
||||||
// Map LabelPresence policy to ConfigProducerArgs that's used to configure the NodeLabel plugin.
|
// Map LabelPresence policy to ConfigProducerArgs that's used to configure the NodeLabel plugin.
|
||||||
if pluginArgs.NodeLabelArgs == nil {
|
if pluginArgs.NodeLabelArgs == nil {
|
||||||
pluginArgs.NodeLabelArgs = &schedulerv1alpha2.NodeLabelArgs{}
|
pluginArgs.NodeLabelArgs = &config.NodeLabelArgs{}
|
||||||
}
|
}
|
||||||
if policy.Argument.LabelsPresence.Presence {
|
if policy.Argument.LabelsPresence.Presence {
|
||||||
pluginArgs.NodeLabelArgs.PresentLabels = append(pluginArgs.NodeLabelArgs.PresentLabels, policy.Argument.LabelsPresence.Labels...)
|
pluginArgs.NodeLabelArgs.PresentLabels = append(pluginArgs.NodeLabelArgs.PresentLabels, policy.Argument.LabelsPresence.Labels...)
|
||||||
@ -587,7 +578,7 @@ func (lr *LegacyRegistry) ProcessPriorityPolicy(policy config.PriorityPolicy, co
|
|||||||
// This name is then used to find the registered plugin and run the plugin instead of the priority.
|
// This name is then used to find the registered plugin and run the plugin instead of the priority.
|
||||||
priorityName = serviceaffinity.Name
|
priorityName = serviceaffinity.Name
|
||||||
if configProducerArgs.ServiceAffinityArgs == nil {
|
if configProducerArgs.ServiceAffinityArgs == nil {
|
||||||
configProducerArgs.ServiceAffinityArgs = &schedulerv1alpha2.ServiceAffinityArgs{}
|
configProducerArgs.ServiceAffinityArgs = &config.ServiceAffinityArgs{}
|
||||||
}
|
}
|
||||||
configProducerArgs.ServiceAffinityArgs.AntiAffinityLabelsPreference = append(
|
configProducerArgs.ServiceAffinityArgs.AntiAffinityLabelsPreference = append(
|
||||||
configProducerArgs.ServiceAffinityArgs.AntiAffinityLabelsPreference,
|
configProducerArgs.ServiceAffinityArgs.AntiAffinityLabelsPreference,
|
||||||
@ -601,7 +592,7 @@ func (lr *LegacyRegistry) ProcessPriorityPolicy(policy config.PriorityPolicy, co
|
|||||||
// This name is then used to find the registered plugin and run the plugin instead of the priority.
|
// This name is then used to find the registered plugin and run the plugin instead of the priority.
|
||||||
priorityName = nodelabel.Name
|
priorityName = nodelabel.Name
|
||||||
if configProducerArgs.NodeLabelArgs == nil {
|
if configProducerArgs.NodeLabelArgs == nil {
|
||||||
configProducerArgs.NodeLabelArgs = &schedulerv1alpha2.NodeLabelArgs{}
|
configProducerArgs.NodeLabelArgs = &config.NodeLabelArgs{}
|
||||||
}
|
}
|
||||||
if policy.Argument.LabelPreference.Presence {
|
if policy.Argument.LabelPreference.Presence {
|
||||||
configProducerArgs.NodeLabelArgs.PresentLabelsPreference = append(
|
configProducerArgs.NodeLabelArgs.PresentLabelsPreference = append(
|
||||||
@ -618,19 +609,19 @@ func (lr *LegacyRegistry) ProcessPriorityPolicy(policy config.PriorityPolicy, co
|
|||||||
|
|
||||||
if policy.Argument.RequestedToCapacityRatioArguments != nil {
|
if policy.Argument.RequestedToCapacityRatioArguments != nil {
|
||||||
policyArgs := policy.Argument.RequestedToCapacityRatioArguments
|
policyArgs := policy.Argument.RequestedToCapacityRatioArguments
|
||||||
args := &schedulerv1alpha2.RequestedToCapacityRatioArgs{}
|
args := &config.RequestedToCapacityRatioArgs{}
|
||||||
|
|
||||||
args.Shape = make([]schedulerv1alpha2.UtilizationShapePoint, len(policyArgs.Shape))
|
args.Shape = make([]config.UtilizationShapePoint, len(policyArgs.Shape))
|
||||||
for i, s := range policyArgs.Shape {
|
for i, s := range policyArgs.Shape {
|
||||||
args.Shape[i] = schedulerv1alpha2.UtilizationShapePoint{
|
args.Shape[i] = config.UtilizationShapePoint{
|
||||||
Utilization: s.Utilization,
|
Utilization: s.Utilization,
|
||||||
Score: s.Score,
|
Score: s.Score,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
args.Resources = make([]schedulerv1alpha2.ResourceSpec, len(policyArgs.Resources))
|
args.Resources = make([]config.ResourceSpec, len(policyArgs.Resources))
|
||||||
for i, r := range policyArgs.Resources {
|
for i, r := range policyArgs.Resources {
|
||||||
args.Resources[i] = schedulerv1alpha2.ResourceSpec{
|
args.Resources[i] = config.ResourceSpec{
|
||||||
Name: r.Name,
|
Name: r.Name,
|
||||||
Weight: r.Weight,
|
Weight: r.Weight,
|
||||||
}
|
}
|
||||||
|
@ -6,11 +6,11 @@ go_library(
|
|||||||
importpath = "k8s.io/kubernetes/pkg/scheduler/framework/plugins/nodelabel",
|
importpath = "k8s.io/kubernetes/pkg/scheduler/framework/plugins/nodelabel",
|
||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
deps = [
|
deps = [
|
||||||
|
"//pkg/scheduler/apis/config:go_default_library",
|
||||||
"//pkg/scheduler/framework/v1alpha1:go_default_library",
|
"//pkg/scheduler/framework/v1alpha1:go_default_library",
|
||||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/labels:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/labels:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||||
"//staging/src/k8s.io/kube-scheduler/config/v1alpha2:go_default_library",
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -19,11 +19,11 @@ go_test(
|
|||||||
srcs = ["node_label_test.go"],
|
srcs = ["node_label_test.go"],
|
||||||
embed = [":go_default_library"],
|
embed = [":go_default_library"],
|
||||||
deps = [
|
deps = [
|
||||||
|
"//pkg/scheduler/apis/config:go_default_library",
|
||||||
"//pkg/scheduler/framework/v1alpha1:go_default_library",
|
"//pkg/scheduler/framework/v1alpha1:go_default_library",
|
||||||
"//pkg/scheduler/internal/cache:go_default_library",
|
"//pkg/scheduler/internal/cache:go_default_library",
|
||||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ import (
|
|||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
"k8s.io/apimachinery/pkg/labels"
|
"k8s.io/apimachinery/pkg/labels"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
schedulerv1alpha2 "k8s.io/kube-scheduler/config/v1alpha2"
|
"k8s.io/kubernetes/pkg/scheduler/apis/config"
|
||||||
framework "k8s.io/kubernetes/pkg/scheduler/framework/v1alpha1"
|
framework "k8s.io/kubernetes/pkg/scheduler/framework/v1alpha1"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -51,8 +51,8 @@ func validateNoConflict(presentLabels []string, absentLabels []string) error {
|
|||||||
|
|
||||||
// New initializes a new plugin and returns it.
|
// New initializes a new plugin and returns it.
|
||||||
func New(plArgs runtime.Object, handle framework.FrameworkHandle) (framework.Plugin, error) {
|
func New(plArgs runtime.Object, handle framework.FrameworkHandle) (framework.Plugin, error) {
|
||||||
args := schedulerv1alpha2.NodeLabelArgs{}
|
args, err := getArgs(plArgs)
|
||||||
if err := framework.DecodeInto(plArgs, &args); err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if err := validateNoConflict(args.PresentLabels, args.AbsentLabels); err != nil {
|
if err := validateNoConflict(args.PresentLabels, args.AbsentLabels); err != nil {
|
||||||
@ -67,10 +67,21 @@ func New(plArgs runtime.Object, handle framework.FrameworkHandle) (framework.Plu
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getArgs(obj runtime.Object) (config.NodeLabelArgs, error) {
|
||||||
|
if obj == nil {
|
||||||
|
return config.NodeLabelArgs{}, nil
|
||||||
|
}
|
||||||
|
ptr, ok := obj.(*config.NodeLabelArgs)
|
||||||
|
if !ok {
|
||||||
|
return config.NodeLabelArgs{}, fmt.Errorf("want args to be of type NodeLabelArgs, got %T", obj)
|
||||||
|
}
|
||||||
|
return *ptr, nil
|
||||||
|
}
|
||||||
|
|
||||||
// NodeLabel checks whether a pod can fit based on the node labels which match a filter that it requests.
|
// NodeLabel checks whether a pod can fit based on the node labels which match a filter that it requests.
|
||||||
type NodeLabel struct {
|
type NodeLabel struct {
|
||||||
handle framework.FrameworkHandle
|
handle framework.FrameworkHandle
|
||||||
args schedulerv1alpha2.NodeLabelArgs
|
args config.NodeLabelArgs
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ framework.FilterPlugin = &NodeLabel{}
|
var _ framework.FilterPlugin = &NodeLabel{}
|
||||||
|
@ -22,7 +22,7 @@ import (
|
|||||||
|
|
||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/kubernetes/pkg/scheduler/apis/config"
|
||||||
framework "k8s.io/kubernetes/pkg/scheduler/framework/v1alpha1"
|
framework "k8s.io/kubernetes/pkg/scheduler/framework/v1alpha1"
|
||||||
"k8s.io/kubernetes/pkg/scheduler/internal/cache"
|
"k8s.io/kubernetes/pkg/scheduler/internal/cache"
|
||||||
)
|
)
|
||||||
@ -30,35 +30,54 @@ import (
|
|||||||
func TestValidateNodeLabelArgs(t *testing.T) {
|
func TestValidateNodeLabelArgs(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
args string
|
args config.NodeLabelArgs
|
||||||
err bool
|
err bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "happy case",
|
name: "happy case",
|
||||||
args: `{"presentLabels" : ["foo", "bar"], "absentLabels" : ["baz"], "presentLabelsPreference" : ["foo", "bar"], "absentLabelsPreference" : ["baz"]}`,
|
args: config.NodeLabelArgs{
|
||||||
|
PresentLabels: []string{"foo", "bar"},
|
||||||
|
AbsentLabels: []string{"baz"},
|
||||||
|
PresentLabelsPreference: []string{"foo", "bar"},
|
||||||
|
AbsentLabelsPreference: []string{"baz"},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "label presence conflict",
|
name: "label presence conflict",
|
||||||
// "bar" exists in both present and absent labels therefore validation should fail.
|
// "bar" exists in both present and absent labels therefore validation should fail.
|
||||||
args: `{"presentLabels" : ["foo", "bar"], "absentLabels" : ["bar", "baz"], "presentLabelsPreference" : ["foo", "bar"], "absentLabelsPreference" : ["baz"]}`,
|
args: config.NodeLabelArgs{
|
||||||
err: true,
|
PresentLabels: []string{"foo", "bar"},
|
||||||
|
AbsentLabels: []string{"bar", "baz"},
|
||||||
|
PresentLabelsPreference: []string{"foo", "bar"},
|
||||||
|
AbsentLabelsPreference: []string{"baz"},
|
||||||
|
},
|
||||||
|
err: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "label preference conflict",
|
name: "label preference conflict",
|
||||||
// "bar" exists in both present and absent labels preferences therefore validation should fail.
|
// "bar" exists in both present and absent labels preferences therefore validation should fail.
|
||||||
args: `{"presentLabels" : ["foo", "bar"], "absentLabels" : ["baz"], "presentLabelsPreference" : ["foo", "bar"], "absentLabelsPreference" : ["bar", "baz"]}`,
|
args: config.NodeLabelArgs{
|
||||||
err: true,
|
PresentLabels: []string{"foo", "bar"},
|
||||||
|
AbsentLabels: []string{"baz"},
|
||||||
|
PresentLabelsPreference: []string{"foo", "bar"},
|
||||||
|
AbsentLabelsPreference: []string{"bar", "baz"},
|
||||||
|
},
|
||||||
|
err: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "both label presence and preference conflict",
|
name: "both label presence and preference conflict",
|
||||||
args: `{"presentLabels" : ["foo", "bar"], "absentLabels" : ["bar", "baz"], "presentLabelsPreference" : ["foo", "bar"], "absentLabelsPreference" : ["bar", "baz"]}`,
|
args: config.NodeLabelArgs{
|
||||||
err: true,
|
PresentLabels: []string{"foo", "bar"},
|
||||||
|
AbsentLabels: []string{"bar", "baz"},
|
||||||
|
PresentLabelsPreference: []string{"foo", "bar"},
|
||||||
|
AbsentLabelsPreference: []string{"bar", "baz"},
|
||||||
|
},
|
||||||
|
err: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.name, func(t *testing.T) {
|
||||||
args := &runtime.Unknown{Raw: []byte(test.args)}
|
_, err := New(&test.args, nil)
|
||||||
_, err := New(args, nil)
|
|
||||||
if test.err && err == nil {
|
if test.err && err == nil {
|
||||||
t.Fatal("Plugin initialization should fail.")
|
t.Fatal("Plugin initialization should fail.")
|
||||||
}
|
}
|
||||||
@ -73,59 +92,83 @@ func TestNodeLabelFilter(t *testing.T) {
|
|||||||
label := map[string]string{"foo": "any value", "bar": "any value"}
|
label := map[string]string{"foo": "any value", "bar": "any value"}
|
||||||
var pod *v1.Pod
|
var pod *v1.Pod
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
rawArgs string
|
args config.NodeLabelArgs
|
||||||
res framework.Code
|
res framework.Code
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "present label does not match",
|
name: "present label does not match",
|
||||||
rawArgs: `{"presentLabels" : ["baz"]}`,
|
args: config.NodeLabelArgs{
|
||||||
res: framework.UnschedulableAndUnresolvable,
|
PresentLabels: []string{"baz"},
|
||||||
|
},
|
||||||
|
res: framework.UnschedulableAndUnresolvable,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "absent label does not match",
|
name: "absent label does not match",
|
||||||
rawArgs: `{"absentLabels" : ["baz"]}`,
|
args: config.NodeLabelArgs{
|
||||||
res: framework.Success,
|
AbsentLabels: []string{"baz"},
|
||||||
|
},
|
||||||
|
res: framework.Success,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "one of two present labels matches",
|
name: "one of two present labels matches",
|
||||||
rawArgs: `{"presentLabels" : ["foo", "baz"]}`,
|
args: config.NodeLabelArgs{
|
||||||
res: framework.UnschedulableAndUnresolvable,
|
PresentLabels: []string{"foo", "baz"},
|
||||||
|
},
|
||||||
|
res: framework.UnschedulableAndUnresolvable,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "one of two absent labels matches",
|
name: "one of two absent labels matches",
|
||||||
rawArgs: `{"absentLabels" : ["foo", "baz"]}`,
|
args: config.NodeLabelArgs{
|
||||||
res: framework.UnschedulableAndUnresolvable,
|
AbsentLabels: []string{"foo", "baz"},
|
||||||
|
},
|
||||||
|
res: framework.UnschedulableAndUnresolvable,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "all present abels match",
|
name: "all present labels match",
|
||||||
rawArgs: `{"presentLabels" : ["foo", "bar"]}`,
|
args: config.NodeLabelArgs{
|
||||||
res: framework.Success,
|
PresentLabels: []string{"foo", "bar"},
|
||||||
|
},
|
||||||
|
res: framework.Success,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "all absent labels match",
|
name: "all absent labels match",
|
||||||
rawArgs: `{"absentLabels" : ["foo", "bar"]}`,
|
args: config.NodeLabelArgs{
|
||||||
res: framework.UnschedulableAndUnresolvable,
|
AbsentLabels: []string{"foo", "bar"},
|
||||||
|
},
|
||||||
|
res: framework.UnschedulableAndUnresolvable,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "both present and absent label matches",
|
name: "both present and absent label matches",
|
||||||
rawArgs: `{"presentLabels" : ["foo"], "absentLabels" : ["bar"]}`,
|
args: config.NodeLabelArgs{
|
||||||
res: framework.UnschedulableAndUnresolvable,
|
PresentLabels: []string{"foo"},
|
||||||
|
AbsentLabels: []string{"bar"},
|
||||||
|
},
|
||||||
|
res: framework.UnschedulableAndUnresolvable,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "neither present nor absent label matches",
|
name: "neither present nor absent label matches",
|
||||||
rawArgs: `{"presentLabels" : ["foz"], "absentLabels" : ["baz"]}`,
|
args: config.NodeLabelArgs{
|
||||||
res: framework.UnschedulableAndUnresolvable,
|
PresentLabels: []string{"foz"},
|
||||||
|
AbsentLabels: []string{"baz"},
|
||||||
|
},
|
||||||
|
res: framework.UnschedulableAndUnresolvable,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "present label matches and absent label doesn't match",
|
name: "present label matches and absent label doesn't match",
|
||||||
rawArgs: `{"presentLabels" : ["foo"], "absentLabels" : ["baz"]}`,
|
args: config.NodeLabelArgs{
|
||||||
res: framework.Success,
|
PresentLabels: []string{"foo"},
|
||||||
|
AbsentLabels: []string{"baz"},
|
||||||
|
},
|
||||||
|
res: framework.Success,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "present label doesn't match and absent label matches",
|
name: "present label doesn't match and absent label matches",
|
||||||
rawArgs: `{"presentLabels" : ["foz"], "absentLabels" : ["bar"]}`,
|
args: config.NodeLabelArgs{
|
||||||
res: framework.UnschedulableAndUnresolvable,
|
PresentLabels: []string{"foz"},
|
||||||
|
AbsentLabels: []string{"bar"},
|
||||||
|
},
|
||||||
|
res: framework.UnschedulableAndUnresolvable,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,8 +178,7 @@ func TestNodeLabelFilter(t *testing.T) {
|
|||||||
nodeInfo := framework.NewNodeInfo()
|
nodeInfo := framework.NewNodeInfo()
|
||||||
nodeInfo.SetNode(&node)
|
nodeInfo.SetNode(&node)
|
||||||
|
|
||||||
args := &runtime.Unknown{Raw: []byte(test.rawArgs)}
|
p, err := New(&test.args, nil)
|
||||||
p, err := New(args, nil)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to create plugin: %v", err)
|
t.Fatalf("Failed to create plugin: %v", err)
|
||||||
}
|
}
|
||||||
@ -151,74 +193,103 @@ func TestNodeLabelFilter(t *testing.T) {
|
|||||||
|
|
||||||
func TestNodeLabelScore(t *testing.T) {
|
func TestNodeLabelScore(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
rawArgs string
|
args config.NodeLabelArgs
|
||||||
want int64
|
want int64
|
||||||
name string
|
name string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
want: framework.MaxNodeScore,
|
want: framework.MaxNodeScore,
|
||||||
rawArgs: `{"presentLabelsPreference" : ["foo"]}`,
|
args: config.NodeLabelArgs{
|
||||||
name: "one present label match",
|
PresentLabelsPreference: []string{"foo"},
|
||||||
|
},
|
||||||
|
name: "one present label match",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
want: 0,
|
want: 0,
|
||||||
rawArgs: `{"presentLabelsPreference" : ["somelabel"]}`,
|
args: config.NodeLabelArgs{
|
||||||
name: "one present label mismatch",
|
PresentLabelsPreference: []string{"somelabel"},
|
||||||
|
},
|
||||||
|
name: "one present label mismatch",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
want: framework.MaxNodeScore,
|
want: framework.MaxNodeScore,
|
||||||
rawArgs: `{"presentLabelsPreference" : ["foo", "bar"]}`,
|
args: config.NodeLabelArgs{
|
||||||
name: "two present labels match",
|
PresentLabelsPreference: []string{"foo", "bar"},
|
||||||
|
},
|
||||||
|
name: "two present labels match",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
want: 0,
|
want: 0,
|
||||||
rawArgs: `{"presentLabelsPreference" : ["somelabel1", "somelabel2"]}`,
|
args: config.NodeLabelArgs{
|
||||||
name: "two present labels mismatch",
|
PresentLabelsPreference: []string{"somelabel1", "somelabel2"},
|
||||||
|
},
|
||||||
|
name: "two present labels mismatch",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
want: framework.MaxNodeScore / 2,
|
want: framework.MaxNodeScore / 2,
|
||||||
rawArgs: `{"presentLabelsPreference" : ["foo", "somelabel"]}`,
|
args: config.NodeLabelArgs{
|
||||||
name: "two present labels only one matches",
|
PresentLabelsPreference: []string{"foo", "somelabel"},
|
||||||
|
},
|
||||||
|
name: "two present labels only one matches",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
want: 0,
|
want: 0,
|
||||||
rawArgs: `{"absentLabelsPreference" : ["foo"]}`,
|
args: config.NodeLabelArgs{
|
||||||
name: "one absent label match",
|
AbsentLabelsPreference: []string{"foo"},
|
||||||
|
},
|
||||||
|
name: "one absent label match",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
want: framework.MaxNodeScore,
|
want: framework.MaxNodeScore,
|
||||||
rawArgs: `{"absentLabelsPreference" : ["somelabel"]}`,
|
args: config.NodeLabelArgs{
|
||||||
name: "one absent label mismatch",
|
AbsentLabelsPreference: []string{"somelabel"},
|
||||||
|
},
|
||||||
|
name: "one absent label mismatch",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
want: 0,
|
want: 0,
|
||||||
rawArgs: `{"absentLabelsPreference" : ["foo", "bar"]}`,
|
args: config.NodeLabelArgs{
|
||||||
name: "two absent labels match",
|
AbsentLabelsPreference: []string{"foo", "bar"},
|
||||||
|
},
|
||||||
|
name: "two absent labels match",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
want: framework.MaxNodeScore,
|
want: framework.MaxNodeScore,
|
||||||
rawArgs: `{"absentLabelsPreference" : ["somelabel1", "somelabel2"]}`,
|
args: config.NodeLabelArgs{
|
||||||
name: "two absent labels mismatch",
|
AbsentLabelsPreference: []string{"somelabel1", "somelabel2"},
|
||||||
|
},
|
||||||
|
name: "two absent labels mismatch",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
want: framework.MaxNodeScore / 2,
|
want: framework.MaxNodeScore / 2,
|
||||||
rawArgs: `{"absentLabelsPreference" : ["foo", "somelabel"]}`,
|
args: config.NodeLabelArgs{
|
||||||
name: "two absent labels only one matches",
|
AbsentLabelsPreference: []string{"foo", "somelabel"},
|
||||||
|
},
|
||||||
|
name: "two absent labels only one matches",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
want: framework.MaxNodeScore,
|
want: framework.MaxNodeScore,
|
||||||
rawArgs: `{"presentLabelsPreference" : ["foo", "bar"], "absentLabelsPreference" : ["somelabel1", "somelabel2"]}`,
|
args: config.NodeLabelArgs{
|
||||||
name: "two present labels match, two absent labels mismatch",
|
PresentLabelsPreference: []string{"foo", "bar"},
|
||||||
|
AbsentLabelsPreference: []string{"somelabel1", "somelabel2"},
|
||||||
|
},
|
||||||
|
name: "two present labels match, two absent labels mismatch",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
want: 0,
|
want: 0,
|
||||||
rawArgs: `{"absentLabelsPreference" : ["foo", "bar"], "presentLabelsPreference" : ["somelabel1", "somelabel2"]}`,
|
args: config.NodeLabelArgs{
|
||||||
name: "two present labels both mismatch, two absent labels both match",
|
PresentLabelsPreference: []string{"somelabel1", "somelabel2"},
|
||||||
|
AbsentLabelsPreference: []string{"foo", "bar"},
|
||||||
|
},
|
||||||
|
name: "two present labels both mismatch, two absent labels both match",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
want: 3 * framework.MaxNodeScore / 4,
|
want: 3 * framework.MaxNodeScore / 4,
|
||||||
rawArgs: `{"presentLabelsPreference" : ["foo", "somelabel"], "absentLabelsPreference" : ["somelabel1", "somelabel2"]}`,
|
args: config.NodeLabelArgs{
|
||||||
name: "two present labels one matches, two absent labels mismatch",
|
PresentLabelsPreference: []string{"foo", "somelabel"},
|
||||||
|
AbsentLabelsPreference: []string{"somelabel1", "somelabel2"},
|
||||||
|
},
|
||||||
|
name: "two present labels one matches, two absent labels mismatch",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -227,8 +298,7 @@ func TestNodeLabelScore(t *testing.T) {
|
|||||||
state := framework.NewCycleState()
|
state := framework.NewCycleState()
|
||||||
node := &v1.Node{ObjectMeta: metav1.ObjectMeta{Name: "machine1", Labels: map[string]string{"foo": "", "bar": ""}}}
|
node := &v1.Node{ObjectMeta: metav1.ObjectMeta{Name: "machine1", Labels: map[string]string{"foo": "", "bar": ""}}}
|
||||||
fh, _ := framework.NewFramework(nil, nil, nil, framework.WithSnapshotSharedLister(cache.NewSnapshot(nil, []*v1.Node{node})))
|
fh, _ := framework.NewFramework(nil, nil, nil, framework.WithSnapshotSharedLister(cache.NewSnapshot(nil, []*v1.Node{node})))
|
||||||
args := &runtime.Unknown{Raw: []byte(test.rawArgs)}
|
p, err := New(&test.args, fh)
|
||||||
p, err := New(args, fh)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to create plugin: %+v", err)
|
t.Fatalf("Failed to create plugin: %+v", err)
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,6 @@ go_library(
|
|||||||
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||||
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||||
"//staging/src/k8s.io/kube-scheduler/config/v1alpha2:go_default_library",
|
|
||||||
"//vendor/k8s.io/klog:go_default_library",
|
"//vendor/k8s.io/klog:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
@ -59,15 +58,14 @@ go_test(
|
|||||||
deps = [
|
deps = [
|
||||||
"//pkg/apis/core/v1/helper:go_default_library",
|
"//pkg/apis/core/v1/helper:go_default_library",
|
||||||
"//pkg/features:go_default_library",
|
"//pkg/features:go_default_library",
|
||||||
|
"//pkg/scheduler/apis/config:go_default_library",
|
||||||
"//pkg/scheduler/framework/v1alpha1:go_default_library",
|
"//pkg/scheduler/framework/v1alpha1:go_default_library",
|
||||||
"//pkg/scheduler/internal/cache:go_default_library",
|
"//pkg/scheduler/internal/cache:go_default_library",
|
||||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
|
||||||
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||||
"//staging/src/k8s.io/component-base/featuregate/testing:go_default_library",
|
"//staging/src/k8s.io/component-base/featuregate/testing:go_default_library",
|
||||||
"//staging/src/k8s.io/kube-scheduler/config/v1alpha2:go_default_library",
|
|
||||||
"//vendor/github.com/stretchr/testify/assert:go_default_library",
|
"//vendor/github.com/stretchr/testify/assert:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
@ -24,9 +24,9 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/util/sets"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||||
schedulerv1alpha2 "k8s.io/kube-scheduler/config/v1alpha2"
|
|
||||||
v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper"
|
v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper"
|
||||||
"k8s.io/kubernetes/pkg/features"
|
"k8s.io/kubernetes/pkg/features"
|
||||||
|
"k8s.io/kubernetes/pkg/scheduler/apis/config"
|
||||||
framework "k8s.io/kubernetes/pkg/scheduler/framework/v1alpha1"
|
framework "k8s.io/kubernetes/pkg/scheduler/framework/v1alpha1"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -64,16 +64,27 @@ func (f *Fit) Name() string {
|
|||||||
|
|
||||||
// NewFit initializes a new plugin and returns it.
|
// NewFit initializes a new plugin and returns it.
|
||||||
func NewFit(plArgs runtime.Object, _ framework.FrameworkHandle) (framework.Plugin, error) {
|
func NewFit(plArgs runtime.Object, _ framework.FrameworkHandle) (framework.Plugin, error) {
|
||||||
args := &schedulerv1alpha2.NodeResourcesFitArgs{}
|
args, err := getFitArgs(plArgs)
|
||||||
if err := framework.DecodeInto(plArgs, args); err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
fit := &Fit{
|
||||||
fit := &Fit{}
|
ignoredResources: sets.NewString(args.IgnoredResources...),
|
||||||
fit.ignoredResources = sets.NewString(args.IgnoredResources...)
|
}
|
||||||
return fit, nil
|
return fit, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getFitArgs(obj runtime.Object) (config.NodeResourcesFitArgs, error) {
|
||||||
|
if obj == nil {
|
||||||
|
return config.NodeResourcesFitArgs{}, nil
|
||||||
|
}
|
||||||
|
ptr, ok := obj.(*config.NodeResourcesFitArgs)
|
||||||
|
if !ok {
|
||||||
|
return config.NodeResourcesFitArgs{}, fmt.Errorf("want args to be of type NodeResourcesFitArgs, got %T", obj)
|
||||||
|
}
|
||||||
|
return *ptr, nil
|
||||||
|
}
|
||||||
|
|
||||||
// computePodResourceRequest returns a framework.Resource that covers the largest
|
// computePodResourceRequest returns a framework.Resource that covers the largest
|
||||||
// width in each resource dimension. Because init-containers run sequentially, we collect
|
// width in each resource dimension. Because init-containers run sequentially, we collect
|
||||||
// the max in each dimension iteratively. In contrast, we sum the resource vectors for
|
// the max in each dimension iteratively. In contrast, we sum the resource vectors for
|
||||||
|
@ -19,10 +19,11 @@ package noderesources
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"k8s.io/kubernetes/pkg/scheduler/apis/config"
|
||||||
|
|
||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
"k8s.io/apimachinery/pkg/api/resource"
|
"k8s.io/apimachinery/pkg/api/resource"
|
||||||
v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper"
|
v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper"
|
||||||
@ -94,7 +95,7 @@ func TestEnoughRequests(t *testing.T) {
|
|||||||
pod *v1.Pod
|
pod *v1.Pod
|
||||||
nodeInfo *framework.NodeInfo
|
nodeInfo *framework.NodeInfo
|
||||||
name string
|
name string
|
||||||
ignoredResources []byte
|
args config.NodeResourcesFitArgs
|
||||||
wantInsufficientResources []InsufficientResource
|
wantInsufficientResources []InsufficientResource
|
||||||
wantStatus *framework.Status
|
wantStatus *framework.Status
|
||||||
}{
|
}{
|
||||||
@ -340,8 +341,10 @@ func TestEnoughRequests(t *testing.T) {
|
|||||||
{
|
{
|
||||||
pod: newResourcePod(
|
pod: newResourcePod(
|
||||||
framework.Resource{MilliCPU: 1, Memory: 1, ScalarResources: map[v1.ResourceName]int64{extendedResourceB: 1}}),
|
framework.Resource{MilliCPU: 1, Memory: 1, ScalarResources: map[v1.ResourceName]int64{extendedResourceB: 1}}),
|
||||||
nodeInfo: framework.NewNodeInfo(newResourcePod(framework.Resource{MilliCPU: 0, Memory: 0})),
|
nodeInfo: framework.NewNodeInfo(newResourcePod(framework.Resource{MilliCPU: 0, Memory: 0})),
|
||||||
ignoredResources: []byte(`{"IgnoredResources" : ["example.com/bbb"]}`),
|
args: config.NodeResourcesFitArgs{
|
||||||
|
IgnoredResources: []string{"example.com/bbb"},
|
||||||
|
},
|
||||||
name: "skip checking ignored extended resource",
|
name: "skip checking ignored extended resource",
|
||||||
wantInsufficientResources: []InsufficientResource{},
|
wantInsufficientResources: []InsufficientResource{},
|
||||||
},
|
},
|
||||||
@ -371,8 +374,10 @@ func TestEnoughRequests(t *testing.T) {
|
|||||||
node := v1.Node{Status: v1.NodeStatus{Capacity: makeResources(10, 20, 32, 5, 20, 5).Capacity, Allocatable: makeAllocatableResources(10, 20, 32, 5, 20, 5)}}
|
node := v1.Node{Status: v1.NodeStatus{Capacity: makeResources(10, 20, 32, 5, 20, 5).Capacity, Allocatable: makeAllocatableResources(10, 20, 32, 5, 20, 5)}}
|
||||||
test.nodeInfo.SetNode(&node)
|
test.nodeInfo.SetNode(&node)
|
||||||
|
|
||||||
args := &runtime.Unknown{Raw: test.ignoredResources}
|
p, err := NewFit(&test.args, nil)
|
||||||
p, _ := NewFit(args, nil)
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
cycleState := framework.NewCycleState()
|
cycleState := framework.NewCycleState()
|
||||||
preFilterStatus := p.(framework.PreFilterPlugin).PreFilter(context.Background(), cycleState, test.pod)
|
preFilterStatus := p.(framework.PreFilterPlugin).PreFilter(context.Background(), cycleState, test.pod)
|
||||||
if !preFilterStatus.IsSuccess() {
|
if !preFilterStatus.IsSuccess() {
|
||||||
|
@ -24,7 +24,6 @@ import (
|
|||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/klog"
|
"k8s.io/klog"
|
||||||
schedulerv1alpha2 "k8s.io/kube-scheduler/config/v1alpha2"
|
|
||||||
"k8s.io/kubernetes/pkg/scheduler/apis/config"
|
"k8s.io/kubernetes/pkg/scheduler/apis/config"
|
||||||
framework "k8s.io/kubernetes/pkg/scheduler/framework/v1alpha1"
|
framework "k8s.io/kubernetes/pkg/scheduler/framework/v1alpha1"
|
||||||
)
|
)
|
||||||
@ -49,8 +48,8 @@ type functionShapePoint struct {
|
|||||||
|
|
||||||
// NewRequestedToCapacityRatio initializes a new plugin and returns it.
|
// NewRequestedToCapacityRatio initializes a new plugin and returns it.
|
||||||
func NewRequestedToCapacityRatio(plArgs runtime.Object, handle framework.FrameworkHandle) (framework.Plugin, error) {
|
func NewRequestedToCapacityRatio(plArgs runtime.Object, handle framework.FrameworkHandle) (framework.Plugin, error) {
|
||||||
args := &schedulerv1alpha2.RequestedToCapacityRatioArgs{}
|
args, err := getRequestedToCapacityRatioArgs(plArgs)
|
||||||
if err := framework.DecodeInto(plArgs, args); err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,6 +91,17 @@ func NewRequestedToCapacityRatio(plArgs runtime.Object, handle framework.Framewo
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getRequestedToCapacityRatioArgs(obj runtime.Object) (config.RequestedToCapacityRatioArgs, error) {
|
||||||
|
if obj == nil {
|
||||||
|
return config.RequestedToCapacityRatioArgs{}, nil
|
||||||
|
}
|
||||||
|
ptr, ok := obj.(*config.RequestedToCapacityRatioArgs)
|
||||||
|
if !ok {
|
||||||
|
return config.RequestedToCapacityRatioArgs{}, fmt.Errorf("want args to be of type RequestedToCapacityRatioArgs, got %T", obj)
|
||||||
|
}
|
||||||
|
return *ptr, nil
|
||||||
|
}
|
||||||
|
|
||||||
// RequestedToCapacityRatio is a score plugin that allow users to apply bin packing
|
// RequestedToCapacityRatio is a score plugin that allow users to apply bin packing
|
||||||
// on core resources like CPU, Memory as well as extended resources like accelerators.
|
// on core resources like CPU, Memory as well as extended resources like accelerators.
|
||||||
type RequestedToCapacityRatio struct {
|
type RequestedToCapacityRatio struct {
|
||||||
|
@ -24,8 +24,7 @@ import (
|
|||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
"k8s.io/apimachinery/pkg/api/resource"
|
"k8s.io/apimachinery/pkg/api/resource"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/kubernetes/pkg/scheduler/apis/config"
|
||||||
schedulerv1alpha2 "k8s.io/kube-scheduler/config/v1alpha2"
|
|
||||||
framework "k8s.io/kubernetes/pkg/scheduler/framework/v1alpha1"
|
framework "k8s.io/kubernetes/pkg/scheduler/framework/v1alpha1"
|
||||||
"k8s.io/kubernetes/pkg/scheduler/internal/cache"
|
"k8s.io/kubernetes/pkg/scheduler/internal/cache"
|
||||||
)
|
)
|
||||||
@ -68,8 +67,17 @@ func TestRequestedToCapacityRatio(t *testing.T) {
|
|||||||
state := framework.NewCycleState()
|
state := framework.NewCycleState()
|
||||||
snapshot := cache.NewSnapshot(test.scheduledPods, test.nodes)
|
snapshot := cache.NewSnapshot(test.scheduledPods, test.nodes)
|
||||||
fh, _ := framework.NewFramework(nil, nil, nil, framework.WithSnapshotSharedLister(snapshot))
|
fh, _ := framework.NewFramework(nil, nil, nil, framework.WithSnapshotSharedLister(snapshot))
|
||||||
args := &runtime.Unknown{Raw: []byte(`{"shape" : [{"utilization" : 0, "score" : 10}, {"utilization" : 100, "score" : 0}], "resources" : [{"name" : "memory", "weight" : 1}, {"name" : "cpu", "weight" : 1}]}`)}
|
args := config.RequestedToCapacityRatioArgs{
|
||||||
p, err := NewRequestedToCapacityRatio(args, fh)
|
Shape: []config.UtilizationShapePoint{
|
||||||
|
{Utilization: 0, Score: 10},
|
||||||
|
{Utilization: 100, Score: 0},
|
||||||
|
},
|
||||||
|
Resources: []config.ResourceSpec{
|
||||||
|
{Name: "memory", Weight: 1},
|
||||||
|
{Name: "cpu", Weight: 1},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
p, err := NewRequestedToCapacityRatio(&args, fh)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
@ -352,8 +360,16 @@ func TestResourceBinPackingSingleExtended(t *testing.T) {
|
|||||||
state := framework.NewCycleState()
|
state := framework.NewCycleState()
|
||||||
snapshot := cache.NewSnapshot(test.pods, test.nodes)
|
snapshot := cache.NewSnapshot(test.pods, test.nodes)
|
||||||
fh, _ := framework.NewFramework(nil, nil, nil, framework.WithSnapshotSharedLister(snapshot))
|
fh, _ := framework.NewFramework(nil, nil, nil, framework.WithSnapshotSharedLister(snapshot))
|
||||||
args := &runtime.Unknown{Raw: []byte(`{"shape" : [{"utilization" : 0, "score" : 0}, {"utilization" : 100, "score" : 1}], "resources" : [{"name" : "intel.com/foo", "weight" : 1}]}`)}
|
args := config.RequestedToCapacityRatioArgs{
|
||||||
p, err := NewRequestedToCapacityRatio(args, fh)
|
Shape: []config.UtilizationShapePoint{
|
||||||
|
{Utilization: 0, Score: 0},
|
||||||
|
{Utilization: 100, Score: 1},
|
||||||
|
},
|
||||||
|
Resources: []config.ResourceSpec{
|
||||||
|
{Name: "intel.com/foo", Weight: 1},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
p, err := NewRequestedToCapacityRatio(&args, fh)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
@ -587,8 +603,17 @@ func TestResourceBinPackingMultipleExtended(t *testing.T) {
|
|||||||
state := framework.NewCycleState()
|
state := framework.NewCycleState()
|
||||||
snapshot := cache.NewSnapshot(test.pods, test.nodes)
|
snapshot := cache.NewSnapshot(test.pods, test.nodes)
|
||||||
fh, _ := framework.NewFramework(nil, nil, nil, framework.WithSnapshotSharedLister(snapshot))
|
fh, _ := framework.NewFramework(nil, nil, nil, framework.WithSnapshotSharedLister(snapshot))
|
||||||
args := &runtime.Unknown{Raw: []byte(`{"shape" : [{"utilization" : 0, "score" : 0}, {"utilization" : 100, "score" : 1}], "resources" : [{"name" : "intel.com/foo", "weight" : 3}, {"name" : "intel.com/bar", "weight": 5}]}`)}
|
args := config.RequestedToCapacityRatioArgs{
|
||||||
p, err := NewRequestedToCapacityRatio(args, fh)
|
Shape: []config.UtilizationShapePoint{
|
||||||
|
{Utilization: 0, Score: 0},
|
||||||
|
{Utilization: 100, Score: 1},
|
||||||
|
},
|
||||||
|
Resources: []config.ResourceSpec{
|
||||||
|
{Name: "intel.com/foo", Weight: 3},
|
||||||
|
{Name: "intel.com/bar", Weight: 5},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
p, err := NewRequestedToCapacityRatio(&args, fh)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
@ -608,49 +633,3 @@ func TestResourceBinPackingMultipleExtended(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO compatibility test once the plugin args move to v1beta1.
|
|
||||||
// UtilizationShapePoint and ResourceSpec fields of the plugin args struct are not annotated
|
|
||||||
// with JSON tags in v1alpha2 to maintain backward compatibility with the args shipped with v1.18.
|
|
||||||
// See https://github.com/kubernetes/kubernetes/pull/88585#discussion_r405021905
|
|
||||||
|
|
||||||
func TestPluginArgsJSONEncodingIsCaseInsensitive(t *testing.T) {
|
|
||||||
rawArgs := &runtime.Unknown{Raw: []byte(`
|
|
||||||
{
|
|
||||||
"shape": [{"Utilization": 1, "Score": 1}, {"utilization": 2, "score": 2}],
|
|
||||||
"resources": [{"Name":"a","Weight":1},{"name":"b","weight":2}]
|
|
||||||
}
|
|
||||||
`)}
|
|
||||||
|
|
||||||
args := &schedulerv1alpha2.RequestedToCapacityRatioArgs{}
|
|
||||||
if err := framework.DecodeInto(rawArgs, args); err != nil {
|
|
||||||
t.Fatalf("expected no error, got: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
expectedArgs := &schedulerv1alpha2.RequestedToCapacityRatioArgs{
|
|
||||||
Shape: []schedulerv1alpha2.UtilizationShapePoint{
|
|
||||||
{
|
|
||||||
Utilization: 1,
|
|
||||||
Score: 1,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Utilization: 2,
|
|
||||||
Score: 2,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Resources: []schedulerv1alpha2.ResourceSpec{
|
|
||||||
{
|
|
||||||
Name: "a",
|
|
||||||
Weight: 1,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "b",
|
|
||||||
Weight: 2,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
if !reflect.DeepEqual(expectedArgs, args) {
|
|
||||||
t.Errorf("expected: \n\t%#v,\ngot: \n\t%#v", expectedArgs, args)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -11,6 +11,7 @@ go_library(
|
|||||||
importpath = "k8s.io/kubernetes/pkg/scheduler/framework/plugins/podtopologyspread",
|
importpath = "k8s.io/kubernetes/pkg/scheduler/framework/plugins/podtopologyspread",
|
||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
deps = [
|
deps = [
|
||||||
|
"//pkg/scheduler/apis/config:go_default_library",
|
||||||
"//pkg/scheduler/framework/plugins/helper:go_default_library",
|
"//pkg/scheduler/framework/plugins/helper:go_default_library",
|
||||||
"//pkg/scheduler/framework/v1alpha1:go_default_library",
|
"//pkg/scheduler/framework/v1alpha1:go_default_library",
|
||||||
"//pkg/scheduler/internal/parallelize:go_default_library",
|
"//pkg/scheduler/internal/parallelize:go_default_library",
|
||||||
@ -24,7 +25,6 @@ go_library(
|
|||||||
"//staging/src/k8s.io/client-go/informers:go_default_library",
|
"//staging/src/k8s.io/client-go/informers:go_default_library",
|
||||||
"//staging/src/k8s.io/client-go/listers/apps/v1:go_default_library",
|
"//staging/src/k8s.io/client-go/listers/apps/v1:go_default_library",
|
||||||
"//staging/src/k8s.io/client-go/listers/core/v1:go_default_library",
|
"//staging/src/k8s.io/client-go/listers/core/v1:go_default_library",
|
||||||
"//staging/src/k8s.io/kube-scheduler/config/v1alpha2:go_default_library",
|
|
||||||
"//vendor/k8s.io/klog:go_default_library",
|
"//vendor/k8s.io/klog:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
@ -38,6 +38,7 @@ go_test(
|
|||||||
],
|
],
|
||||||
embed = [":go_default_library"],
|
embed = [":go_default_library"],
|
||||||
deps = [
|
deps = [
|
||||||
|
"//pkg/scheduler/apis/config:go_default_library",
|
||||||
"//pkg/scheduler/framework/v1alpha1:go_default_library",
|
"//pkg/scheduler/framework/v1alpha1:go_default_library",
|
||||||
"//pkg/scheduler/internal/cache:go_default_library",
|
"//pkg/scheduler/internal/cache:go_default_library",
|
||||||
"//pkg/scheduler/internal/parallelize:go_default_library",
|
"//pkg/scheduler/internal/parallelize:go_default_library",
|
||||||
@ -50,7 +51,6 @@ go_test(
|
|||||||
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||||
"//staging/src/k8s.io/client-go/informers:go_default_library",
|
"//staging/src/k8s.io/client-go/informers:go_default_library",
|
||||||
"//staging/src/k8s.io/client-go/kubernetes/fake:go_default_library",
|
"//staging/src/k8s.io/client-go/kubernetes/fake:go_default_library",
|
||||||
"//staging/src/k8s.io/kube-scheduler/config/v1alpha2:go_default_library",
|
|
||||||
"//vendor/github.com/google/go-cmp/cmp:go_default_library",
|
"//vendor/github.com/google/go-cmp/cmp:go_default_library",
|
||||||
"//vendor/k8s.io/utils/pointer:go_default_library",
|
"//vendor/k8s.io/utils/pointer:go_default_library",
|
||||||
],
|
],
|
||||||
|
@ -28,7 +28,7 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/client-go/informers"
|
"k8s.io/client-go/informers"
|
||||||
"k8s.io/client-go/kubernetes/fake"
|
"k8s.io/client-go/kubernetes/fake"
|
||||||
schedulerv1alpha2 "k8s.io/kube-scheduler/config/v1alpha2"
|
"k8s.io/kubernetes/pkg/scheduler/apis/config"
|
||||||
framework "k8s.io/kubernetes/pkg/scheduler/framework/v1alpha1"
|
framework "k8s.io/kubernetes/pkg/scheduler/framework/v1alpha1"
|
||||||
"k8s.io/kubernetes/pkg/scheduler/internal/cache"
|
"k8s.io/kubernetes/pkg/scheduler/internal/cache"
|
||||||
"k8s.io/kubernetes/pkg/scheduler/internal/parallelize"
|
"k8s.io/kubernetes/pkg/scheduler/internal/parallelize"
|
||||||
@ -518,7 +518,7 @@ func TestPreFilterState(t *testing.T) {
|
|||||||
informerFactory := informers.NewSharedInformerFactory(fake.NewSimpleClientset(tt.objs...), 0)
|
informerFactory := informers.NewSharedInformerFactory(fake.NewSimpleClientset(tt.objs...), 0)
|
||||||
pl := PodTopologySpread{
|
pl := PodTopologySpread{
|
||||||
sharedLister: cache.NewSnapshot(tt.existingPods, tt.nodes),
|
sharedLister: cache.NewSnapshot(tt.existingPods, tt.nodes),
|
||||||
args: schedulerv1alpha2.PodTopologySpreadArgs{
|
args: config.PodTopologySpreadArgs{
|
||||||
DefaultConstraints: tt.defaultConstraints,
|
DefaultConstraints: tt.defaultConstraints,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ import (
|
|||||||
"k8s.io/client-go/informers"
|
"k8s.io/client-go/informers"
|
||||||
appslisters "k8s.io/client-go/listers/apps/v1"
|
appslisters "k8s.io/client-go/listers/apps/v1"
|
||||||
corelisters "k8s.io/client-go/listers/core/v1"
|
corelisters "k8s.io/client-go/listers/core/v1"
|
||||||
schedulerv1alpha2 "k8s.io/kube-scheduler/config/v1alpha2"
|
"k8s.io/kubernetes/pkg/scheduler/apis/config"
|
||||||
framework "k8s.io/kubernetes/pkg/scheduler/framework/v1alpha1"
|
framework "k8s.io/kubernetes/pkg/scheduler/framework/v1alpha1"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -42,7 +42,7 @@ var (
|
|||||||
|
|
||||||
// PodTopologySpread is a plugin that ensures pod's topologySpreadConstraints is satisfied.
|
// PodTopologySpread is a plugin that ensures pod's topologySpreadConstraints is satisfied.
|
||||||
type PodTopologySpread struct {
|
type PodTopologySpread struct {
|
||||||
args schedulerv1alpha2.PodTopologySpreadArgs
|
args config.PodTopologySpreadArgs
|
||||||
sharedLister framework.SharedLister
|
sharedLister framework.SharedLister
|
||||||
services corelisters.ServiceLister
|
services corelisters.ServiceLister
|
||||||
replicationCtrls corelisters.ReplicationControllerLister
|
replicationCtrls corelisters.ReplicationControllerLister
|
||||||
@ -71,17 +71,21 @@ func (pl *PodTopologySpread) BuildArgs() interface{} {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// New initializes a new plugin and returns it.
|
// New initializes a new plugin and returns it.
|
||||||
func New(args runtime.Object, h framework.FrameworkHandle) (framework.Plugin, error) {
|
func New(plArgs runtime.Object, h framework.FrameworkHandle) (framework.Plugin, error) {
|
||||||
if h.SnapshotSharedLister() == nil {
|
if h.SnapshotSharedLister() == nil {
|
||||||
return nil, fmt.Errorf("SnapshotSharedlister is nil")
|
return nil, fmt.Errorf("SnapshotSharedlister is nil")
|
||||||
}
|
}
|
||||||
pl := &PodTopologySpread{sharedLister: h.SnapshotSharedLister()}
|
args, err := getArgs(plArgs)
|
||||||
if err := framework.DecodeInto(args, &pl.args); err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if err := validateArgs(&pl.args); err != nil {
|
if err := validateArgs(&args); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
pl := &PodTopologySpread{
|
||||||
|
sharedLister: h.SnapshotSharedLister(),
|
||||||
|
args: args,
|
||||||
|
}
|
||||||
if len(pl.args.DefaultConstraints) != 0 {
|
if len(pl.args.DefaultConstraints) != 0 {
|
||||||
if h.SharedInformerFactory() == nil {
|
if h.SharedInformerFactory() == nil {
|
||||||
return nil, fmt.Errorf("SharedInformerFactory is nil")
|
return nil, fmt.Errorf("SharedInformerFactory is nil")
|
||||||
@ -91,6 +95,17 @@ func New(args runtime.Object, h framework.FrameworkHandle) (framework.Plugin, er
|
|||||||
return pl, nil
|
return pl, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getArgs(obj runtime.Object) (config.PodTopologySpreadArgs, error) {
|
||||||
|
if obj == nil {
|
||||||
|
return config.PodTopologySpreadArgs{}, nil
|
||||||
|
}
|
||||||
|
ptr, ok := obj.(*config.PodTopologySpreadArgs)
|
||||||
|
if !ok {
|
||||||
|
return config.PodTopologySpreadArgs{}, fmt.Errorf("want args to be of type PodTopologySpreadArgs, got %T", obj)
|
||||||
|
}
|
||||||
|
return *ptr, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (pl *PodTopologySpread) setListers(factory informers.SharedInformerFactory) {
|
func (pl *PodTopologySpread) setListers(factory informers.SharedInformerFactory) {
|
||||||
pl.services = factory.Core().V1().Services().Lister()
|
pl.services = factory.Core().V1().Services().Lister()
|
||||||
pl.replicationCtrls = factory.Core().V1().ReplicationControllers().Lister()
|
pl.replicationCtrls = factory.Core().V1().ReplicationControllers().Lister()
|
||||||
@ -101,7 +116,7 @@ func (pl *PodTopologySpread) setListers(factory informers.SharedInformerFactory)
|
|||||||
// validateArgs replicates the validation from
|
// validateArgs replicates the validation from
|
||||||
// pkg/apis/core/validation.validateTopologySpreadConstraints.
|
// pkg/apis/core/validation.validateTopologySpreadConstraints.
|
||||||
// This has the additional check for .labelSelector to be nil.
|
// This has the additional check for .labelSelector to be nil.
|
||||||
func validateArgs(args *schedulerv1alpha2.PodTopologySpreadArgs) error {
|
func validateArgs(args *config.PodTopologySpreadArgs) error {
|
||||||
var allErrs field.ErrorList
|
var allErrs field.ErrorList
|
||||||
path := field.NewPath("defaultConstraints")
|
path := field.NewPath("defaultConstraints")
|
||||||
for i, c := range args.DefaultConstraints {
|
for i, c := range args.DefaultConstraints {
|
||||||
|
@ -20,38 +20,25 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/google/go-cmp/cmp"
|
|
||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/client-go/informers"
|
"k8s.io/client-go/informers"
|
||||||
"k8s.io/client-go/kubernetes/fake"
|
"k8s.io/client-go/kubernetes/fake"
|
||||||
schedulerv1alpha2 "k8s.io/kube-scheduler/config/v1alpha2"
|
"k8s.io/kubernetes/pkg/scheduler/apis/config"
|
||||||
framework "k8s.io/kubernetes/pkg/scheduler/framework/v1alpha1"
|
framework "k8s.io/kubernetes/pkg/scheduler/framework/v1alpha1"
|
||||||
"k8s.io/kubernetes/pkg/scheduler/internal/cache"
|
"k8s.io/kubernetes/pkg/scheduler/internal/cache"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestNew(t *testing.T) {
|
func TestNew(t *testing.T) {
|
||||||
cases := []struct {
|
cases := []struct {
|
||||||
name string
|
name string
|
||||||
args runtime.Unknown
|
args config.PodTopologySpreadArgs
|
||||||
wantErr string
|
wantErr string
|
||||||
wantArgs schedulerv1alpha2.PodTopologySpreadArgs
|
|
||||||
}{
|
}{
|
||||||
{name: "empty args"},
|
{name: "empty args"},
|
||||||
{
|
{
|
||||||
name: "valid constraints",
|
name: "valid constraints",
|
||||||
args: runtime.Unknown{
|
args: config.PodTopologySpreadArgs{
|
||||||
ContentType: runtime.ContentTypeYAML,
|
|
||||||
Raw: []byte(`defaultConstraints:
|
|
||||||
- maxSkew: 1
|
|
||||||
topologyKey: "node"
|
|
||||||
whenUnsatisfiable: "ScheduleAnyway"
|
|
||||||
- maxSkew: 5
|
|
||||||
topologyKey: "zone"
|
|
||||||
whenUnsatisfiable: "DoNotSchedule"
|
|
||||||
`),
|
|
||||||
},
|
|
||||||
wantArgs: schedulerv1alpha2.PodTopologySpreadArgs{
|
|
||||||
DefaultConstraints: []v1.TopologySpreadConstraint{
|
DefaultConstraints: []v1.TopologySpreadConstraint{
|
||||||
{
|
{
|
||||||
MaxSkew: 1,
|
MaxSkew: 1,
|
||||||
@ -68,66 +55,75 @@ func TestNew(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "repeated constraints",
|
name: "repeated constraints",
|
||||||
args: runtime.Unknown{
|
args: config.PodTopologySpreadArgs{
|
||||||
ContentType: runtime.ContentTypeYAML,
|
DefaultConstraints: []v1.TopologySpreadConstraint{
|
||||||
Raw: []byte(`defaultConstraints:
|
{
|
||||||
- maxSkew: 1
|
MaxSkew: 1,
|
||||||
topologyKey: "node"
|
TopologyKey: "node",
|
||||||
whenUnsatisfiable: "ScheduleAnyway"
|
WhenUnsatisfiable: v1.ScheduleAnyway,
|
||||||
- maxSkew: 5
|
},
|
||||||
topologyKey: "node"
|
{
|
||||||
whenUnsatisfiable: "ScheduleAnyway"
|
MaxSkew: 5,
|
||||||
`),
|
TopologyKey: "node",
|
||||||
|
WhenUnsatisfiable: v1.ScheduleAnyway,
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
wantErr: "Duplicate value",
|
wantErr: "Duplicate value",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "unknown whenUnsatisfiable",
|
name: "unknown whenUnsatisfiable",
|
||||||
args: runtime.Unknown{
|
args: config.PodTopologySpreadArgs{
|
||||||
ContentType: runtime.ContentTypeYAML,
|
DefaultConstraints: []v1.TopologySpreadConstraint{
|
||||||
Raw: []byte(`defaultConstraints:
|
{
|
||||||
- maxSkew: 1
|
MaxSkew: 1,
|
||||||
topologyKey: "node"
|
TopologyKey: "node",
|
||||||
whenUnsatisfiable: "Unknown"
|
WhenUnsatisfiable: "Unknown",
|
||||||
`),
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
wantErr: "Unsupported value",
|
wantErr: "Unsupported value",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "negative maxSkew",
|
name: "negative maxSkew",
|
||||||
args: runtime.Unknown{
|
args: config.PodTopologySpreadArgs{
|
||||||
ContentType: runtime.ContentTypeYAML,
|
DefaultConstraints: []v1.TopologySpreadConstraint{
|
||||||
Raw: []byte(`defaultConstraints:
|
{
|
||||||
- maxSkew: -1
|
MaxSkew: -1,
|
||||||
topologyKey: "node"
|
TopologyKey: "node",
|
||||||
whenUnsatisfiable: "ScheduleAnyway"
|
WhenUnsatisfiable: v1.ScheduleAnyway,
|
||||||
`),
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
wantErr: "must be greater than zero",
|
wantErr: "must be greater than zero",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "empty topologyKey",
|
name: "empty topologyKey",
|
||||||
args: runtime.Unknown{
|
args: config.PodTopologySpreadArgs{
|
||||||
ContentType: runtime.ContentTypeYAML,
|
DefaultConstraints: []v1.TopologySpreadConstraint{
|
||||||
Raw: []byte(`defaultConstraints:
|
{
|
||||||
- maxSkew: 1
|
MaxSkew: 1,
|
||||||
whenUnsatisfiable: "ScheduleAnyway"
|
WhenUnsatisfiable: v1.ScheduleAnyway,
|
||||||
`),
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
wantErr: "can not be empty",
|
wantErr: "can not be empty",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "with label selector",
|
name: "with label selector",
|
||||||
args: runtime.Unknown{
|
args: config.PodTopologySpreadArgs{
|
||||||
ContentType: runtime.ContentTypeYAML,
|
DefaultConstraints: []v1.TopologySpreadConstraint{
|
||||||
Raw: []byte(`defaultConstraints:
|
{
|
||||||
- maxSkew: 1
|
MaxSkew: 1,
|
||||||
topologyKey: "rack"
|
TopologyKey: "rack",
|
||||||
whenUnsatisfiable: "ScheduleAnyway"
|
WhenUnsatisfiable: v1.ScheduleAnyway,
|
||||||
labelSelector:
|
LabelSelector: &metav1.LabelSelector{
|
||||||
matchLabels:
|
MatchLabels: map[string]string{
|
||||||
foo: "bar"
|
"foo": "bar",
|
||||||
`),
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
wantErr: "constraint must not define a selector",
|
wantErr: "constraint must not define a selector",
|
||||||
},
|
},
|
||||||
@ -142,7 +138,7 @@ func TestNew(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
pl, err := New(&tc.args, f)
|
_, err = New(&tc.args, f)
|
||||||
if len(tc.wantErr) != 0 {
|
if len(tc.wantErr) != 0 {
|
||||||
if err == nil || !strings.Contains(err.Error(), tc.wantErr) {
|
if err == nil || !strings.Contains(err.Error(), tc.wantErr) {
|
||||||
t.Errorf("must fail, got error %q, want %q", err, tc.wantErr)
|
t.Errorf("must fail, got error %q, want %q", err, tc.wantErr)
|
||||||
@ -152,10 +148,6 @@ func TestNew(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
plObj := pl.(*PodTopologySpread)
|
|
||||||
if diff := cmp.Diff(tc.wantArgs, plObj.BuildArgs()); diff != "" {
|
|
||||||
t.Errorf("wrong plugin build args (-want,+got):\n%s", diff)
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/util/sets"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
"k8s.io/client-go/informers"
|
"k8s.io/client-go/informers"
|
||||||
"k8s.io/client-go/kubernetes/fake"
|
"k8s.io/client-go/kubernetes/fake"
|
||||||
schedulerv1alpha2 "k8s.io/kube-scheduler/config/v1alpha2"
|
"k8s.io/kubernetes/pkg/scheduler/apis/config"
|
||||||
framework "k8s.io/kubernetes/pkg/scheduler/framework/v1alpha1"
|
framework "k8s.io/kubernetes/pkg/scheduler/framework/v1alpha1"
|
||||||
"k8s.io/kubernetes/pkg/scheduler/internal/cache"
|
"k8s.io/kubernetes/pkg/scheduler/internal/cache"
|
||||||
"k8s.io/kubernetes/pkg/scheduler/internal/parallelize"
|
"k8s.io/kubernetes/pkg/scheduler/internal/parallelize"
|
||||||
@ -195,7 +195,7 @@ func TestPreScoreStateEmptyNodes(t *testing.T) {
|
|||||||
informerFactory := informers.NewSharedInformerFactory(fake.NewSimpleClientset(tt.objs...), 0)
|
informerFactory := informers.NewSharedInformerFactory(fake.NewSimpleClientset(tt.objs...), 0)
|
||||||
pl := PodTopologySpread{
|
pl := PodTopologySpread{
|
||||||
sharedLister: cache.NewSnapshot(nil, tt.nodes),
|
sharedLister: cache.NewSnapshot(nil, tt.nodes),
|
||||||
args: schedulerv1alpha2.PodTopologySpreadArgs{
|
args: config.PodTopologySpreadArgs{
|
||||||
DefaultConstraints: tt.defaultConstraints,
|
DefaultConstraints: tt.defaultConstraints,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -729,7 +729,7 @@ func BenchmarkTestDefaultEvenPodsSpreadPriority(b *testing.B) {
|
|||||||
snapshot := cache.NewSnapshot(existingPods, allNodes)
|
snapshot := cache.NewSnapshot(existingPods, allNodes)
|
||||||
p := &PodTopologySpread{
|
p := &PodTopologySpread{
|
||||||
sharedLister: snapshot,
|
sharedLister: snapshot,
|
||||||
args: schedulerv1alpha2.PodTopologySpreadArgs{
|
args: config.PodTopologySpreadArgs{
|
||||||
DefaultConstraints: []v1.TopologySpreadConstraint{
|
DefaultConstraints: []v1.TopologySpreadConstraint{
|
||||||
{MaxSkew: 1, TopologyKey: v1.LabelHostname, WhenUnsatisfiable: v1.ScheduleAnyway},
|
{MaxSkew: 1, TopologyKey: v1.LabelHostname, WhenUnsatisfiable: v1.ScheduleAnyway},
|
||||||
{MaxSkew: 1, TopologyKey: v1.LabelZoneFailureDomain, WhenUnsatisfiable: v1.ScheduleAnyway},
|
{MaxSkew: 1, TopologyKey: v1.LabelZoneFailureDomain, WhenUnsatisfiable: v1.ScheduleAnyway},
|
||||||
|
@ -6,13 +6,13 @@ go_library(
|
|||||||
importpath = "k8s.io/kubernetes/pkg/scheduler/framework/plugins/serviceaffinity",
|
importpath = "k8s.io/kubernetes/pkg/scheduler/framework/plugins/serviceaffinity",
|
||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
deps = [
|
deps = [
|
||||||
|
"//pkg/scheduler/apis/config:go_default_library",
|
||||||
"//pkg/scheduler/framework/plugins/helper:go_default_library",
|
"//pkg/scheduler/framework/plugins/helper:go_default_library",
|
||||||
"//pkg/scheduler/framework/v1alpha1:go_default_library",
|
"//pkg/scheduler/framework/v1alpha1:go_default_library",
|
||||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/labels:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/labels:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||||
"//staging/src/k8s.io/client-go/listers/core/v1:go_default_library",
|
"//staging/src/k8s.io/client-go/listers/core/v1:go_default_library",
|
||||||
"//staging/src/k8s.io/kube-scheduler/config/v1alpha2:go_default_library",
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -21,12 +21,12 @@ go_test(
|
|||||||
srcs = ["service_affinity_test.go"],
|
srcs = ["service_affinity_test.go"],
|
||||||
embed = [":go_default_library"],
|
embed = [":go_default_library"],
|
||||||
deps = [
|
deps = [
|
||||||
|
"//pkg/scheduler/apis/config:go_default_library",
|
||||||
"//pkg/scheduler/framework/v1alpha1:go_default_library",
|
"//pkg/scheduler/framework/v1alpha1:go_default_library",
|
||||||
"//pkg/scheduler/framework/v1alpha1/fake:go_default_library",
|
"//pkg/scheduler/framework/v1alpha1/fake:go_default_library",
|
||||||
"//pkg/scheduler/internal/cache:go_default_library",
|
"//pkg/scheduler/internal/cache:go_default_library",
|
||||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||||
"//staging/src/k8s.io/kube-scheduler/config/v1alpha2:go_default_library",
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/labels"
|
"k8s.io/apimachinery/pkg/labels"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
corelisters "k8s.io/client-go/listers/core/v1"
|
corelisters "k8s.io/client-go/listers/core/v1"
|
||||||
schedulerv1alpha2 "k8s.io/kube-scheduler/config/v1alpha2"
|
"k8s.io/kubernetes/pkg/scheduler/apis/config"
|
||||||
"k8s.io/kubernetes/pkg/scheduler/framework/plugins/helper"
|
"k8s.io/kubernetes/pkg/scheduler/framework/plugins/helper"
|
||||||
framework "k8s.io/kubernetes/pkg/scheduler/framework/v1alpha1"
|
framework "k8s.io/kubernetes/pkg/scheduler/framework/v1alpha1"
|
||||||
)
|
)
|
||||||
@ -64,12 +64,11 @@ func (s *preFilterState) Clone() framework.StateData {
|
|||||||
|
|
||||||
// New initializes a new plugin and returns it.
|
// New initializes a new plugin and returns it.
|
||||||
func New(plArgs runtime.Object, handle framework.FrameworkHandle) (framework.Plugin, error) {
|
func New(plArgs runtime.Object, handle framework.FrameworkHandle) (framework.Plugin, error) {
|
||||||
args := schedulerv1alpha2.ServiceAffinityArgs{}
|
args, err := getArgs(plArgs)
|
||||||
if err := framework.DecodeInto(plArgs, &args); err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
informerFactory := handle.SharedInformerFactory()
|
serviceLister := handle.SharedInformerFactory().Core().V1().Services().Lister()
|
||||||
serviceLister := informerFactory.Core().V1().Services().Lister()
|
|
||||||
|
|
||||||
return &ServiceAffinity{
|
return &ServiceAffinity{
|
||||||
sharedLister: handle.SnapshotSharedLister(),
|
sharedLister: handle.SnapshotSharedLister(),
|
||||||
@ -78,9 +77,20 @@ func New(plArgs runtime.Object, handle framework.FrameworkHandle) (framework.Plu
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getArgs(obj runtime.Object) (config.ServiceAffinityArgs, error) {
|
||||||
|
if obj == nil {
|
||||||
|
return config.ServiceAffinityArgs{}, nil
|
||||||
|
}
|
||||||
|
ptr, ok := obj.(*config.ServiceAffinityArgs)
|
||||||
|
if !ok {
|
||||||
|
return config.ServiceAffinityArgs{}, fmt.Errorf("want args to be of type ServiceAffinityArgs, got %T", obj)
|
||||||
|
}
|
||||||
|
return *ptr, nil
|
||||||
|
}
|
||||||
|
|
||||||
// ServiceAffinity is a plugin that checks service affinity.
|
// ServiceAffinity is a plugin that checks service affinity.
|
||||||
type ServiceAffinity struct {
|
type ServiceAffinity struct {
|
||||||
args schedulerv1alpha2.ServiceAffinityArgs
|
args config.ServiceAffinityArgs
|
||||||
sharedLister framework.SharedLister
|
sharedLister framework.SharedLister
|
||||||
serviceLister corelisters.ServiceLister
|
serviceLister corelisters.ServiceLister
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ import (
|
|||||||
|
|
||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
schedulerv1alpha2 "k8s.io/kube-scheduler/config/v1alpha2"
|
"k8s.io/kubernetes/pkg/scheduler/apis/config"
|
||||||
framework "k8s.io/kubernetes/pkg/scheduler/framework/v1alpha1"
|
framework "k8s.io/kubernetes/pkg/scheduler/framework/v1alpha1"
|
||||||
fakeframework "k8s.io/kubernetes/pkg/scheduler/framework/v1alpha1/fake"
|
fakeframework "k8s.io/kubernetes/pkg/scheduler/framework/v1alpha1/fake"
|
||||||
"k8s.io/kubernetes/pkg/scheduler/internal/cache"
|
"k8s.io/kubernetes/pkg/scheduler/internal/cache"
|
||||||
@ -165,7 +165,7 @@ func TestServiceAffinity(t *testing.T) {
|
|||||||
p := &ServiceAffinity{
|
p := &ServiceAffinity{
|
||||||
sharedLister: snapshot,
|
sharedLister: snapshot,
|
||||||
serviceLister: fakeframework.ServiceLister(test.services),
|
serviceLister: fakeframework.ServiceLister(test.services),
|
||||||
args: schedulerv1alpha2.ServiceAffinityArgs{
|
args: config.ServiceAffinityArgs{
|
||||||
AffinityLabels: test.labels,
|
AffinityLabels: test.labels,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -389,7 +389,7 @@ func TestServiceAffinityScore(t *testing.T) {
|
|||||||
p := &ServiceAffinity{
|
p := &ServiceAffinity{
|
||||||
sharedLister: snapshot,
|
sharedLister: snapshot,
|
||||||
serviceLister: serviceLister,
|
serviceLister: serviceLister,
|
||||||
args: schedulerv1alpha2.ServiceAffinityArgs{
|
args: config.ServiceAffinityArgs{
|
||||||
AntiAffinityLabelsPreference: test.labels,
|
AntiAffinityLabelsPreference: test.labels,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -606,7 +606,7 @@ func TestPreFilterDisabled(t *testing.T) {
|
|||||||
node := v1.Node{}
|
node := v1.Node{}
|
||||||
nodeInfo.SetNode(&node)
|
nodeInfo.SetNode(&node)
|
||||||
p := &ServiceAffinity{
|
p := &ServiceAffinity{
|
||||||
args: schedulerv1alpha2.ServiceAffinityArgs{
|
args: config.ServiceAffinityArgs{
|
||||||
AffinityLabels: []string{"region"},
|
AffinityLabels: []string{"region"},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user