Use internal config types in scheduling plugin args

Signed-off-by: Aldo Culquicondor <acondor@google.com>
This commit is contained in:
Aldo Culquicondor 2020-04-15 13:37:56 -04:00
parent 6b153dc920
commit 98d1e241f1
29 changed files with 491 additions and 429 deletions

View File

@ -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",

View File

@ -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
} }

View File

@ -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}`),
},
}, },
}, },
}, },

View File

@ -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",
], ],

View File

@ -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"
]
}`),
}, },
}, },
}, },

View File

@ -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,
} }
} }

View File

@ -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)

View File

@ -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",
], ],
) )

View File

@ -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",
], ],
) )

View File

@ -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.

View File

@ -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
} }

View File

@ -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)

View File

@ -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,
} }

View File

@ -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",
], ],
) )

View File

@ -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{}

View File

@ -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)
} }

View File

@ -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",
], ],
) )

View File

@ -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

View File

@ -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() {

View File

@ -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 {

View File

@ -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)
}
}

View File

@ -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",
], ],

View File

@ -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,
}, },
} }

View File

@ -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 {

View File

@ -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)
}
}) })
} }
} }

View File

@ -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},

View File

@ -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",
], ],
) )

View File

@ -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
} }

View File

@ -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"},
}, },
} }