1
0
mirror of https://github.com/kubernetes-sigs/descheduler.git synced 2026-01-25 20:59:28 +01:00

use plugin registry and prepare for conversion (#1003)

* use plugin registry and prepare for conersion

* Register plugins explicitly to a registry

* check interface impl instead of struc var

* setup plugins at top level

* treat plugin type combinations

* pass registry as arg of V1alpha1ToInternal

* move registry yet another level up

* check interface type separately
This commit is contained in:
Lucas Severo Alves
2022-12-01 15:05:54 +01:00
committed by GitHub
parent 6e953b2ff3
commit da8b145980
22 changed files with 234 additions and 196 deletions

View File

@@ -20,6 +20,7 @@ package app
import (
"context"
"io"
"os"
"os/signal"
"syscall"
@@ -112,3 +113,8 @@ func NewDeschedulerCommand(out io.Writer) *cobra.Command {
func Run(ctx context.Context, rs *options.DeschedulerServer) error {
return descheduler.Run(ctx, rs)
}
func SetupLogs() {
klog.SetOutput(os.Stdout)
klog.InitFlags(nil)
}

View File

@@ -20,13 +20,13 @@ import (
"os"
"k8s.io/component-base/cli"
"k8s.io/klog/v2"
"sigs.k8s.io/descheduler/cmd/descheduler/app"
"sigs.k8s.io/descheduler/pkg/descheduler"
)
func init() {
klog.SetOutput(os.Stdout)
klog.InitFlags(nil)
app.SetupLogs()
descheduler.SetupPlugins()
}
func main() {

View File

@@ -45,6 +45,7 @@ import (
podutil "sigs.k8s.io/descheduler/pkg/descheduler/pod"
"sigs.k8s.io/descheduler/pkg/framework"
"sigs.k8s.io/descheduler/pkg/framework/plugins/defaultevictor"
"sigs.k8s.io/descheduler/pkg/framework/plugins/pluginbuilder"
"sigs.k8s.io/descheduler/pkg/utils"
)
@@ -58,7 +59,7 @@ func Run(ctx context.Context, rs *options.DeschedulerServer) error {
rs.Client = rsclient
rs.EventClient = eventClient
deschedulerPolicy, err := LoadPolicyConfig(rs.PolicyConfigFile, rs.Client)
deschedulerPolicy, err := LoadPolicyConfig(rs.PolicyConfigFile, rs.Client, pluginbuilder.PluginRegistry)
if err != nil {
return err
}
@@ -357,11 +358,15 @@ func RunDeschedulerStrategies(ctx context.Context, rs *options.DeschedulerServer
klog.ErrorS(fmt.Errorf("unable to get plugin config"), "skipping plugin", "plugin", plugin)
continue
}
pgFnc, ok := pluginsMap[plugin]
registryPlugin, ok := pluginbuilder.PluginRegistry[plugin]
pgFnc := registryPlugin.PluginBuilder
if !ok {
klog.ErrorS(fmt.Errorf("unable to find plugin in the pluginsMap"), "skipping plugin", "plugin", plugin)
}
pg := pgFnc(pc.Args, handle)
pg, err := pgFnc(pc.Args, handle)
if err != nil {
klog.ErrorS(err, "unable to initialize a plugin", "pluginName", plugin)
}
if pg != nil {
switch v := pg.(type) {
case framework.DeschedulePlugin:

View File

@@ -15,10 +15,15 @@ import (
"sigs.k8s.io/descheduler/cmd/descheduler/app/options"
"sigs.k8s.io/descheduler/pkg/api"
"sigs.k8s.io/descheduler/pkg/api/v1alpha1"
"sigs.k8s.io/descheduler/pkg/framework/plugins/pluginbuilder"
"sigs.k8s.io/descheduler/pkg/framework/plugins/removeduplicates"
"sigs.k8s.io/descheduler/pkg/framework/plugins/removepodsviolatingnodetaints"
"sigs.k8s.io/descheduler/test"
)
func TestTaintsUpdated(t *testing.T) {
pluginbuilder.PluginRegistry = pluginbuilder.NewRegistry()
pluginbuilder.Register(removepodsviolatingnodetaints.PluginName, removepodsviolatingnodetaints.New, &removepodsviolatingnodetaints.RemovePodsViolatingNodeTaintsArgs{}, pluginbuilder.PluginRegistry)
ctx := context.Background()
n1 := test.BuildTestNode("n1", 2000, 3000, 10, nil)
n2 := test.BuildTestNode("n2", 2000, 3000, 10, nil)
@@ -69,7 +74,7 @@ func TestTaintsUpdated(t *testing.T) {
var evictedPods []string
client.PrependReactor("create", "pods", podEvictionReactionFuc(&evictedPods))
internalDeschedulerPolicy, err := V1alpha1ToInternal(client, dp)
internalDeschedulerPolicy, err := V1alpha1ToInternal(client, dp, pluginbuilder.PluginRegistry)
if err != nil {
t.Fatalf("Unable to convert v1alpha1 to v1alpha2: %v", err)
}
@@ -84,6 +89,8 @@ func TestTaintsUpdated(t *testing.T) {
}
func TestDuplicate(t *testing.T) {
pluginbuilder.PluginRegistry = pluginbuilder.NewRegistry()
pluginbuilder.Register(removeduplicates.PluginName, removeduplicates.New, &removeduplicates.RemoveDuplicatesArgs{}, pluginbuilder.PluginRegistry)
ctx := context.Background()
node1 := test.BuildTestNode("n1", 2000, 3000, 10, nil)
node2 := test.BuildTestNode("n2", 2000, 3000, 10, nil)
@@ -129,7 +136,7 @@ func TestDuplicate(t *testing.T) {
var evictedPods []string
client.PrependReactor("create", "pods", podEvictionReactionFuc(&evictedPods))
internalDeschedulerPolicy, err := V1alpha1ToInternal(client, dp)
internalDeschedulerPolicy, err := V1alpha1ToInternal(client, dp, pluginbuilder.PluginRegistry)
if err != nil {
t.Fatalf("Unable to convert v1alpha1 to v1alpha2: %v", err)
}

View File

@@ -28,11 +28,13 @@ import (
"sigs.k8s.io/descheduler/pkg/api"
"sigs.k8s.io/descheduler/pkg/api/v1alpha1"
"sigs.k8s.io/descheduler/pkg/descheduler/scheme"
"sigs.k8s.io/descheduler/pkg/framework"
"sigs.k8s.io/descheduler/pkg/framework/plugins/defaultevictor"
"sigs.k8s.io/descheduler/pkg/framework/plugins/pluginbuilder"
"sigs.k8s.io/descheduler/pkg/utils"
)
func LoadPolicyConfig(policyConfigFile string, client clientset.Interface) (*api.DeschedulerPolicy, error) {
func LoadPolicyConfig(policyConfigFile string, client clientset.Interface, registry pluginbuilder.Registry) (*api.DeschedulerPolicy, error) {
if policyConfigFile == "" {
klog.V(1).InfoS("Policy config file not specified")
return nil, nil
@@ -51,8 +53,7 @@ func LoadPolicyConfig(policyConfigFile string, client clientset.Interface) (*api
}
// Build profiles
// TODO(jchaloup): replace this with v1alpha1 -> v1alpha2 conversion
internalPolicy, err := V1alpha1ToInternal(client, versionedPolicy)
internalPolicy, err := V1alpha1ToInternal(client, versionedPolicy, registry)
if err != nil {
return nil, fmt.Errorf("failed converting versioned policy to internal policy version: %v", err)
}
@@ -63,20 +64,8 @@ func LoadPolicyConfig(policyConfigFile string, client clientset.Interface) (*api
func V1alpha1ToInternal(
client clientset.Interface,
deschedulerPolicy *v1alpha1.DeschedulerPolicy,
registry pluginbuilder.Registry,
) (*api.DeschedulerPolicy, error) {
validStrategyNames := map[v1alpha1.StrategyName]interface{}{
"RemoveDuplicates": nil,
"LowNodeUtilization": nil,
"HighNodeUtilization": nil,
"RemovePodsViolatingInterPodAntiAffinity": nil,
"RemovePodsViolatingNodeAffinity": nil,
"RemovePodsViolatingNodeTaints": nil,
"RemovePodsHavingTooManyRestarts": nil,
"PodLifeTime": nil,
"RemovePodsViolatingTopologySpreadConstraint": nil,
"RemoveFailedPods": nil,
}
var evictLocalStoragePods bool
if deschedulerPolicy.EvictLocalStoragePods != nil {
evictLocalStoragePods = *deschedulerPolicy.EvictLocalStoragePods
@@ -107,7 +96,7 @@ func V1alpha1ToInternal(
// Build profiles
for name, strategy := range deschedulerPolicy.Strategies {
if _, ok := validStrategyNames[name]; ok {
if _, ok := pluginbuilder.PluginRegistry[string(name)]; ok {
if strategy.Enabled {
params := strategy.Params
if params == nil {
@@ -175,13 +164,16 @@ func V1alpha1ToInternal(
},
}
// Plugins have either of the two extension points
switch pluginToExtensionPoint[pluginConfig.Name] {
case descheduleEP:
profile.Plugins.Deschedule.Enabled = []string{pluginConfig.Name}
case balanceEP:
profile.Plugins.Balance.Enabled = []string{pluginConfig.Name}
pluginArgs := registry[string(name)].PluginArgInstance
pluginInstance, err := registry[string(name)].PluginBuilder(pluginArgs, &handleImpl{})
if err != nil {
klog.ErrorS(fmt.Errorf("could not build plugin"), "plugin build error", "plugin", name)
return nil, fmt.Errorf("could not build plugin: %v", name)
}
// pluginInstance can be of any of each type, or both
profilePlugins := profile.Plugins
profile.Plugins = enableProfilePluginsByType(profilePlugins, pluginInstance, pluginConfig)
profiles = append(profiles, profile)
}
} else {
@@ -197,3 +189,27 @@ func V1alpha1ToInternal(
MaxNoOfPodsToEvictPerNamespace: deschedulerPolicy.MaxNoOfPodsToEvictPerNamespace,
}, nil
}
func enableProfilePluginsByType(profilePlugins api.Plugins, pluginInstance framework.Plugin, pluginConfig *api.PluginConfig) api.Plugins {
profilePlugins = checkBalance(profilePlugins, pluginInstance, pluginConfig)
profilePlugins = checkDeschedule(profilePlugins, pluginInstance, pluginConfig)
return profilePlugins
}
func checkBalance(profilePlugins api.Plugins, pluginInstance framework.Plugin, pluginConfig *api.PluginConfig) api.Plugins {
switch p := pluginInstance.(type) {
case framework.BalancePlugin:
klog.V(3).Info("converting Balance plugin: %s", p.Name())
profilePlugins.Balance.Enabled = []string{pluginConfig.Name}
}
return profilePlugins
}
func checkDeschedule(profilePlugins api.Plugins, pluginInstance framework.Plugin, pluginConfig *api.PluginConfig) api.Plugins {
switch p := pluginInstance.(type) {
case framework.DeschedulePlugin:
klog.V(3).Info("converting Deschedule plugin: %s", p.Name())
profilePlugins.Deschedule.Enabled = []string{pluginConfig.Name}
}
return profilePlugins
}

View File

@@ -27,6 +27,7 @@ import (
"sigs.k8s.io/descheduler/pkg/api/v1alpha1"
"sigs.k8s.io/descheduler/pkg/framework/plugins/defaultevictor"
"sigs.k8s.io/descheduler/pkg/framework/plugins/nodeutilization"
"sigs.k8s.io/descheduler/pkg/framework/plugins/pluginbuilder"
"sigs.k8s.io/descheduler/pkg/framework/plugins/removeduplicates"
"sigs.k8s.io/descheduler/pkg/framework/plugins/removefailedpods"
"sigs.k8s.io/descheduler/pkg/framework/plugins/removepodshavingtoomanyrestarts"
@@ -38,6 +39,7 @@ import (
)
func TestV1alpha1ToV1alpha2(t *testing.T) {
SetupPlugins()
defaultEvictorPluginConfig := api.PluginConfig{
Name: defaultevictor.PluginName,
Args: &defaultevictor.DefaultEvictorArgs{
@@ -680,7 +682,7 @@ func TestV1alpha1ToV1alpha2(t *testing.T) {
for _, tc := range testCases {
t.Run(tc.description, func(t *testing.T) {
client := fakeclientset.NewSimpleClientset()
result, err := V1alpha1ToInternal(client, tc.policy)
result, err := V1alpha1ToInternal(client, tc.policy, pluginbuilder.PluginRegistry)
if err != nil {
if err.Error() != tc.err.Error() {
t.Errorf("unexpected error: %s", err.Error())

View File

@@ -0,0 +1,50 @@
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package descheduler
import (
"sigs.k8s.io/descheduler/pkg/framework/plugins/defaultevictor"
"sigs.k8s.io/descheduler/pkg/framework/plugins/nodeutilization"
"sigs.k8s.io/descheduler/pkg/framework/plugins/pluginbuilder"
"sigs.k8s.io/descheduler/pkg/framework/plugins/podlifetime"
"sigs.k8s.io/descheduler/pkg/framework/plugins/removeduplicates"
"sigs.k8s.io/descheduler/pkg/framework/plugins/removefailedpods"
"sigs.k8s.io/descheduler/pkg/framework/plugins/removepodshavingtoomanyrestarts"
"sigs.k8s.io/descheduler/pkg/framework/plugins/removepodsviolatinginterpodantiaffinity"
"sigs.k8s.io/descheduler/pkg/framework/plugins/removepodsviolatingnodeaffinity"
"sigs.k8s.io/descheduler/pkg/framework/plugins/removepodsviolatingnodetaints"
"sigs.k8s.io/descheduler/pkg/framework/plugins/removepodsviolatingtopologyspreadconstraint"
)
func SetupPlugins() {
pluginbuilder.PluginRegistry = pluginbuilder.NewRegistry()
RegisterDefaultPlugins(pluginbuilder.PluginRegistry)
}
func RegisterDefaultPlugins(registry pluginbuilder.Registry) {
pluginbuilder.Register(defaultevictor.PluginName, defaultevictor.New, &defaultevictor.DefaultEvictorArgs{}, registry)
pluginbuilder.Register(nodeutilization.LowNodeUtilizationPluginName, nodeutilization.NewLowNodeUtilization, &nodeutilization.LowNodeUtilizationArgs{}, registry)
pluginbuilder.Register(nodeutilization.HighNodeUtilizationPluginName, nodeutilization.NewHighNodeUtilization, &nodeutilization.HighNodeUtilizationArgs{}, registry)
pluginbuilder.Register(podlifetime.PluginName, podlifetime.New, &podlifetime.PodLifeTimeArgs{}, registry)
pluginbuilder.Register(removeduplicates.PluginName, removeduplicates.New, &removeduplicates.RemoveDuplicatesArgs{}, registry)
pluginbuilder.Register(removefailedpods.PluginName, removefailedpods.New, &removefailedpods.RemoveFailedPodsArgs{}, registry)
pluginbuilder.Register(removepodshavingtoomanyrestarts.PluginName, removepodshavingtoomanyrestarts.New, &removepodshavingtoomanyrestarts.RemovePodsHavingTooManyRestartsArgs{}, registry)
pluginbuilder.Register(removepodsviolatinginterpodantiaffinity.PluginName, removepodsviolatinginterpodantiaffinity.New, &removepodsviolatinginterpodantiaffinity.RemovePodsViolatingInterPodAntiAffinityArgs{}, registry)
pluginbuilder.Register(removepodsviolatingnodeaffinity.PluginName, removepodsviolatingnodeaffinity.New, &removepodsviolatingnodeaffinity.RemovePodsViolatingNodeAffinityArgs{}, registry)
pluginbuilder.Register(removepodsviolatingnodetaints.PluginName, removepodsviolatingnodetaints.New, &removepodsviolatingnodetaints.RemovePodsViolatingNodeTaintsArgs{}, registry)
pluginbuilder.Register(removepodsviolatingtopologyspreadconstraint.PluginName, removepodsviolatingtopologyspreadconstraint.New, &removepodsviolatingtopologyspreadconstraint.RemovePodsViolatingTopologySpreadConstraintArgs{}, registry)
}

View File

@@ -19,11 +19,9 @@ package descheduler
import (
"fmt"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/klog/v2"
"sigs.k8s.io/descheduler/pkg/api"
"sigs.k8s.io/descheduler/pkg/api/v1alpha1"
"sigs.k8s.io/descheduler/pkg/framework"
"sigs.k8s.io/descheduler/pkg/framework/plugins/nodeutilization"
"sigs.k8s.io/descheduler/pkg/framework/plugins/podlifetime"
"sigs.k8s.io/descheduler/pkg/framework/plugins/removeduplicates"
@@ -250,106 +248,3 @@ func v1alpha1ThresholdToInternal(thresholds v1alpha1.ResourceThresholds) api.Res
}
return internal
}
type extensionPoint string
const (
descheduleEP extensionPoint = "deschedule"
balanceEP extensionPoint = "balance"
)
var pluginToExtensionPoint = map[string]extensionPoint{
removepodsviolatingnodetaints.PluginName: descheduleEP,
removefailedpods.PluginName: descheduleEP,
removepodsviolatingnodeaffinity.PluginName: descheduleEP,
removepodsviolatinginterpodantiaffinity.PluginName: descheduleEP,
removepodshavingtoomanyrestarts.PluginName: descheduleEP,
podlifetime.PluginName: descheduleEP,
removeduplicates.PluginName: balanceEP,
removepodsviolatingtopologyspreadconstraint.PluginName: balanceEP,
nodeutilization.HighNodeUtilizationPluginName: balanceEP,
nodeutilization.LowNodeUtilizationPluginName: balanceEP,
}
var pluginsMap = map[string]func(args runtime.Object, handle *handleImpl) framework.Plugin{
removepodsviolatingnodetaints.PluginName: func(args runtime.Object, handle *handleImpl) framework.Plugin {
pg, err := removepodsviolatingnodetaints.New(args, handle)
if err != nil {
klog.ErrorS(err, "unable to initialize a plugin", "pluginName", removepodsviolatingnodetaints.PluginName)
return nil
}
return pg
},
removefailedpods.PluginName: func(args runtime.Object, handle *handleImpl) framework.Plugin {
pg, err := removefailedpods.New(args, handle)
if err != nil {
klog.ErrorS(err, "unable to initialize a plugin", "pluginName", removefailedpods.PluginName)
return nil
}
return pg
},
removepodsviolatingnodeaffinity.PluginName: func(args runtime.Object, handle *handleImpl) framework.Plugin {
pg, err := removepodsviolatingnodeaffinity.New(args, handle)
if err != nil {
klog.ErrorS(err, "unable to initialize a plugin", "pluginName", removepodsviolatingnodeaffinity.PluginName)
return nil
}
return pg
},
removepodsviolatinginterpodantiaffinity.PluginName: func(args runtime.Object, handle *handleImpl) framework.Plugin {
pg, err := removepodsviolatinginterpodantiaffinity.New(args, handle)
if err != nil {
klog.ErrorS(err, "unable to initialize a plugin", "pluginName", removepodsviolatinginterpodantiaffinity.PluginName)
return nil
}
return pg
},
removepodshavingtoomanyrestarts.PluginName: func(args runtime.Object, handle *handleImpl) framework.Plugin {
pg, err := removepodshavingtoomanyrestarts.New(args, handle)
if err != nil {
klog.ErrorS(err, "unable to initialize a plugin", "pluginName", removepodshavingtoomanyrestarts.PluginName)
return nil
}
return pg
},
podlifetime.PluginName: func(args runtime.Object, handle *handleImpl) framework.Plugin {
pg, err := podlifetime.New(args, handle)
if err != nil {
klog.ErrorS(err, "unable to initialize a plugin", "pluginName", podlifetime.PluginName)
return nil
}
return pg
},
removeduplicates.PluginName: func(args runtime.Object, handle *handleImpl) framework.Plugin {
pg, err := removeduplicates.New(args, handle)
if err != nil {
klog.ErrorS(err, "unable to initialize a plugin", "pluginName", removeduplicates.PluginName)
return nil
}
return pg
},
removepodsviolatingtopologyspreadconstraint.PluginName: func(args runtime.Object, handle *handleImpl) framework.Plugin {
pg, err := removepodsviolatingtopologyspreadconstraint.New(args, handle)
if err != nil {
klog.ErrorS(err, "unable to initialize a plugin", "pluginName", removepodsviolatingtopologyspreadconstraint.PluginName)
return nil
}
return pg
},
nodeutilization.HighNodeUtilizationPluginName: func(args runtime.Object, handle *handleImpl) framework.Plugin {
pg, err := nodeutilization.NewHighNodeUtilization(args, handle)
if err != nil {
klog.ErrorS(err, "unable to initialize a plugin", "pluginName", nodeutilization.HighNodeUtilizationPluginName)
return nil
}
return pg
},
nodeutilization.LowNodeUtilizationPluginName: func(args runtime.Object, handle *handleImpl) framework.Plugin {
pg, err := nodeutilization.NewLowNodeUtilization(args, handle)
if err != nil {
klog.ErrorS(err, "unable to initialize a plugin", "pluginName", nodeutilization.LowNodeUtilizationPluginName)
return nil
}
return pg
},
}

View File

@@ -19,6 +19,7 @@ import (
"fmt"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/errors"
@@ -129,9 +130,13 @@ func New(args runtime.Object, handle framework.Handle) (framework.Plugin, error)
return nil
})
}
if defaultEvictorArgs.LabelSelector != nil && !defaultEvictorArgs.LabelSelector.Empty() {
selector, err := metav1.LabelSelectorAsSelector(defaultEvictorArgs.LabelSelector)
if err != nil {
return nil, fmt.Errorf("could not get selector from label selector")
}
if defaultEvictorArgs.LabelSelector != nil && !selector.Empty() {
ev.constraints = append(ev.constraints, func(pod *v1.Pod) error {
if !defaultEvictorArgs.LabelSelector.Matches(labels.Set(pod.Labels)) {
if !selector.Matches(labels.Set(pod.Labels)) {
return fmt.Errorf("pod labels do not match the labelSelector filter in the policy parameter")
}
return nil

View File

@@ -15,7 +15,6 @@ package defaultevictor
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
"sigs.k8s.io/descheduler/pkg/api"
)
@@ -24,14 +23,14 @@ import (
// DefaultEvictorArgs holds arguments used to configure DefaultEvictor plugin.
type DefaultEvictorArgs struct {
metav1.TypeMeta
metav1.TypeMeta `json:",inline"`
NodeSelector string
EvictLocalStoragePods bool
EvictSystemCriticalPods bool
IgnorePvcPods bool
EvictFailedBarePods bool
LabelSelector labels.Selector
PriorityThreshold *api.PriorityThreshold
NodeFit bool
NodeSelector string `json:"nodeSelector"`
EvictLocalStoragePods bool `json:"evictLocalStoragePods"`
EvictSystemCriticalPods bool `json:"evictSystemCriticalPods"`
IgnorePvcPods bool `json:"ignorePvcPods"`
EvictFailedBarePods bool `json:"evictFailedBarePods"`
LabelSelector *metav1.LabelSelector `json:"labelSelector"`
PriorityThreshold *api.PriorityThreshold `json:"priorityThreshold"`
NodeFit bool `json:"nodeFit"`
}

View File

@@ -22,6 +22,7 @@ limitations under the License.
package defaultevictor
import (
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
api "sigs.k8s.io/descheduler/pkg/api"
)
@@ -31,7 +32,9 @@ func (in *DefaultEvictorArgs) DeepCopyInto(out *DefaultEvictorArgs) {
*out = *in
out.TypeMeta = in.TypeMeta
if in.LabelSelector != nil {
out.LabelSelector = in.LabelSelector.DeepCopySelector()
in, out := &in.LabelSelector, &out.LabelSelector
*out = new(v1.LabelSelector)
(*in).DeepCopyInto(*out)
}
if in.PriorityThreshold != nil {
in, out := &in.PriorityThreshold, &out.PriorityThreshold

View File

@@ -22,28 +22,29 @@ import (
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type LowNodeUtilizationArgs struct {
metav1.TypeMeta
metav1.TypeMeta `json:",inline"`
UseDeviationThresholds bool `json:"useDeviationThresholds"`
Thresholds api.ResourceThresholds `json:"thresholds"`
TargetThresholds api.ResourceThresholds `json:"targetThresholds"`
NumberOfNodes int `json:"numberOfNodes"`
UseDeviationThresholds bool
Thresholds api.ResourceThresholds
TargetThresholds api.ResourceThresholds
NumberOfNodes int
// Naming this one differently since namespaces are still
// considered while considering resoures used by pods
// but then filtered out before eviction
EvictableNamespaces *api.Namespaces
EvictableNamespaces *api.Namespaces `json:"evictableNamespaces"`
}
// +k8s:deepcopy-gen=true
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type HighNodeUtilizationArgs struct {
metav1.TypeMeta
metav1.TypeMeta `json:",inline"`
Thresholds api.ResourceThresholds
NumberOfNodes int
Thresholds api.ResourceThresholds `json:"thresholds"`
NumberOfNodes int `json:"numberOfNodes"`
// Naming this one differently since namespaces are still
// considered while considering resoures used by pods
// but then filtered out before eviction
EvictableNamespaces *api.Namespaces
EvictableNamespaces *api.Namespaces `json:"evictableNamespaces"`
}

View File

@@ -0,0 +1,48 @@
/*
Copyright 2022 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package pluginbuilder
import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/klog/v2"
"sigs.k8s.io/descheduler/pkg/framework"
)
var PluginRegistry Registry
type PluginBuilderAndArgsInstance struct {
PluginBuilder PluginBuilder
// Just an example instance of this PluginArg so we can avoid having
// to deal with reflect Types
PluginArgInstance runtime.Object
}
type PluginBuilder = func(args runtime.Object, handle framework.Handle) (framework.Plugin, error)
type Registry = map[string]PluginBuilderAndArgsInstance
func NewRegistry() Registry {
return Registry{}
}
func Register(name string, builderFunc PluginBuilder, exampleArg runtime.Object, registry Registry) {
if _, ok := registry[name]; ok {
klog.V(10).InfoS("Plugin already registered", "plugin", name)
} else {
registry[name] = PluginBuilderAndArgsInstance{
PluginBuilder: builderFunc,
PluginArgInstance: exampleArg,
}
}
}

View File

@@ -23,10 +23,10 @@ import (
// PodLifeTimeArgs holds arguments used to configure PodLifeTime plugin.
type PodLifeTimeArgs struct {
metav1.TypeMeta
metav1.TypeMeta `json:",inline"`
Namespaces *api.Namespaces
LabelSelector *metav1.LabelSelector
MaxPodLifeTimeSeconds *uint
States []string
Namespaces *api.Namespaces `json:"namespaces"`
LabelSelector *metav1.LabelSelector `json:"labelSelector"`
MaxPodLifeTimeSeconds *uint `json:"maxPodLifeTimeSeconds"`
States []string `json:"states"`
}

View File

@@ -22,8 +22,8 @@ import (
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type RemoveDuplicatesArgs struct {
metav1.TypeMeta
metav1.TypeMeta `json:",inline"`
Namespaces *api.Namespaces
ExcludeOwnerKinds []string
Namespaces *api.Namespaces `json:"namespaces"`
ExcludeOwnerKinds []string `json:"excludeOwnerKinds"`
}

View File

@@ -23,12 +23,12 @@ import (
// RemoveFailedPodsArgs holds arguments used to configure RemoveFailedPods plugin.
type RemoveFailedPodsArgs struct {
metav1.TypeMeta
metav1.TypeMeta `json:",inline"`
Namespaces *api.Namespaces
LabelSelector *metav1.LabelSelector
ExcludeOwnerKinds []string
MinPodLifetimeSeconds *uint
Reasons []string
IncludingInitContainers bool
Namespaces *api.Namespaces `json:"namespaces"`
LabelSelector *metav1.LabelSelector `json:"labelSelector"`
ExcludeOwnerKinds []string `json:"excludeOwnerKinds"`
MinPodLifetimeSeconds *uint `json:"minPodLifetimeSeconds"`
Reasons []string `json:"reasons"`
IncludingInitContainers bool `json:"includingInitContainers"`
}

View File

@@ -23,10 +23,10 @@ import (
// RemovePodsHavingTooManyRestartsArgs holds arguments used to configure RemovePodsHavingTooManyRestarts plugin.
type RemovePodsHavingTooManyRestartsArgs struct {
metav1.TypeMeta
metav1.TypeMeta `json:",inline"`
Namespaces *api.Namespaces
LabelSelector *metav1.LabelSelector
PodRestartThreshold int32
IncludingInitContainers bool
Namespaces *api.Namespaces `json:"namespaces"`
LabelSelector *metav1.LabelSelector `json:"labelSelector"`
PodRestartThreshold int32 `json:"podRestartThreshold"`
IncludingInitContainers bool `json:"includingInitContainers"`
}

View File

@@ -26,8 +26,8 @@ import (
// RemovePodsViolatingInterPodAntiAffinity holds arguments used to configure RemovePodsViolatingInterPodAntiAffinity plugin.
type RemovePodsViolatingInterPodAntiAffinityArgs struct {
metav1.TypeMeta
metav1.TypeMeta `json:",inline"`
Namespaces *api.Namespaces
LabelSelector *metav1.LabelSelector
Namespaces *api.Namespaces `json:"namespaces"`
LabelSelector *metav1.LabelSelector `json:"labelSelector"`
}

View File

@@ -26,9 +26,9 @@ import (
// RemovePodsViolatingNodeAffinityArgs holds arguments used to configure RemovePodsViolatingNodeAffinity plugin.
type RemovePodsViolatingNodeAffinityArgs struct {
metav1.TypeMeta
metav1.TypeMeta `json:",inline"`
Namespaces *api.Namespaces
LabelSelector *metav1.LabelSelector
NodeAffinityType []string
Namespaces *api.Namespaces `json:"namespaces"`
LabelSelector *metav1.LabelSelector `json:"labelSelector"`
NodeAffinityType []string `json:"nodeAffinityType"`
}

View File

@@ -26,10 +26,10 @@ import (
// RemovePodsViolatingNodeTaintsArgs holds arguments used to configure the RemovePodsViolatingNodeTaints plugin.
type RemovePodsViolatingNodeTaintsArgs struct {
metav1.TypeMeta
metav1.TypeMeta `json:",inline"`
Namespaces *api.Namespaces
LabelSelector *metav1.LabelSelector
IncludePreferNoSchedule bool
ExcludedTaints []string
Namespaces *api.Namespaces `json:"namespaces"`
LabelSelector *metav1.LabelSelector `json:"labelSelector"`
IncludePreferNoSchedule bool `json:"includePreferNoSchedule"`
ExcludedTaints []string `json:"excludedTaints"`
}

View File

@@ -26,9 +26,9 @@ import (
// RemovePodsViolatingTopologySpreadConstraintArgs holds arguments used to configure RemovePodsViolatingTopologySpreadConstraint plugin.
type RemovePodsViolatingTopologySpreadConstraintArgs struct {
metav1.TypeMeta
metav1.TypeMeta `json:",inline"`
Namespaces *api.Namespaces
LabelSelector *metav1.LabelSelector
IncludeSoftConstraints bool
Namespaces *api.Namespaces `json:"namespaces"`
LabelSelector *metav1.LabelSelector `json:"labelSelector"`
IncludeSoftConstraints bool `json:"includeSoftConstraints"`
}

View File

@@ -38,6 +38,7 @@ import (
)
func TestLeaderElection(t *testing.T) {
descheduler.SetupPlugins()
ctx := context.Background()
clientSet, _, _, _, stopCh := initializeClient(t)