diff --git a/pkg/api/conversion.go b/pkg/api/conversion.go new file mode 100644 index 0000000000..0f4f59e71b --- /dev/null +++ b/pkg/api/conversion.go @@ -0,0 +1,17 @@ +/* +Copyright 2023 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 api diff --git a/pkg/api/v1alpha1/conversion.go b/pkg/api/v1alpha1/conversion.go new file mode 100644 index 0000000000..a805e3b9b6 --- /dev/null +++ b/pkg/api/v1alpha1/conversion.go @@ -0,0 +1,244 @@ +/* +Copyright 2023 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 v1alpha1 + +import ( + "context" + "fmt" + + v1 "k8s.io/api/core/v1" + "k8s.io/client-go/informers" + clientset "k8s.io/client-go/kubernetes" + "k8s.io/klog/v2" + "sigs.k8s.io/descheduler/pkg/api" + "sigs.k8s.io/descheduler/pkg/descheduler/evictions" + podutil "sigs.k8s.io/descheduler/pkg/descheduler/pod" + "sigs.k8s.io/descheduler/pkg/framework" + "sigs.k8s.io/descheduler/pkg/framework/pluginregistry" + "sigs.k8s.io/descheduler/pkg/framework/plugins/defaultevictor" + "sigs.k8s.io/descheduler/pkg/utils" +) + +// evictorImpl implements the Evictor interface so plugins +// can evict a pod without importing a specific pod evictor +type evictorImpl struct { + podEvictor *evictions.PodEvictor + evictorFilter framework.EvictorPlugin +} + +var _ framework.Evictor = &evictorImpl{} + +// Filter checks if a pod can be evicted +func (ei *evictorImpl) Filter(pod *v1.Pod) bool { + return ei.evictorFilter.Filter(pod) +} + +// PreEvictionFilter checks if pod can be evicted right before eviction +func (ei *evictorImpl) PreEvictionFilter(pod *v1.Pod) bool { + return ei.evictorFilter.PreEvictionFilter(pod) +} + +// Evict evicts a pod (no pre-check performed) +func (ei *evictorImpl) Evict(ctx context.Context, pod *v1.Pod, opts evictions.EvictOptions) bool { + return ei.podEvictor.EvictPod(ctx, pod, opts) +} + +func (ei *evictorImpl) NodeLimitExceeded(node *v1.Node) bool { + return ei.podEvictor.NodeLimitExceeded(node) +} + +// handleImpl implements the framework handle which gets passed to plugins +type handleImpl struct { + clientSet clientset.Interface + getPodsAssignedToNodeFunc podutil.GetPodsAssignedToNodeFunc + sharedInformerFactory informers.SharedInformerFactory + evictor *evictorImpl +} + +var _ framework.Handle = &handleImpl{} + +// ClientSet retrieves kube client set +func (hi *handleImpl) ClientSet() clientset.Interface { + return hi.clientSet +} + +// GetPodsAssignedToNodeFunc retrieves GetPodsAssignedToNodeFunc implementation +func (hi *handleImpl) GetPodsAssignedToNodeFunc() podutil.GetPodsAssignedToNodeFunc { + return hi.getPodsAssignedToNodeFunc +} + +// SharedInformerFactory retrieves shared informer factory +func (hi *handleImpl) SharedInformerFactory() informers.SharedInformerFactory { + return hi.sharedInformerFactory +} + +// Evictor retrieves evictor so plugins can filter and evict pods +func (hi *handleImpl) Evictor() framework.Evictor { + return hi.evictor +} + +func V1alpha1ToInternal( + client clientset.Interface, + deschedulerPolicy *DeschedulerPolicy, + registry pluginregistry.Registry, +) (*api.DeschedulerPolicy, error) { + var evictLocalStoragePods bool + if deschedulerPolicy.EvictLocalStoragePods != nil { + evictLocalStoragePods = *deschedulerPolicy.EvictLocalStoragePods + } + + evictBarePods := false + if deschedulerPolicy.EvictFailedBarePods != nil { + evictBarePods = *deschedulerPolicy.EvictFailedBarePods + if evictBarePods { + klog.V(1).Info("Warning: EvictFailedBarePods is set to True. This could cause eviction of pods without ownerReferences.") + } + } + + evictSystemCriticalPods := false + if deschedulerPolicy.EvictSystemCriticalPods != nil { + evictSystemCriticalPods = *deschedulerPolicy.EvictSystemCriticalPods + if evictSystemCriticalPods { + klog.V(1).Info("Warning: EvictSystemCriticalPods is set to True. This could cause eviction of Kubernetes system pods.") + } + } + + ignorePvcPods := false + if deschedulerPolicy.IgnorePVCPods != nil { + ignorePvcPods = *deschedulerPolicy.IgnorePVCPods + } + + var profiles []api.Profile + + // Build profiles + for name, strategy := range deschedulerPolicy.Strategies { + if _, ok := pluginregistry.PluginRegistry[string(name)]; ok { + if strategy.Enabled { + params := strategy.Params + if params == nil { + params = &StrategyParameters{} + } + + nodeFit := false + if name != "PodLifeTime" { + nodeFit = params.NodeFit + } + + if params.ThresholdPriority != nil && params.ThresholdPriorityClassName != "" { + klog.ErrorS(fmt.Errorf("priority threshold misconfigured"), "only one of priorityThreshold fields can be set", "pluginName", name) + return nil, fmt.Errorf("priority threshold misconfigured for plugin %v", name) + } + + var priorityThreshold *api.PriorityThreshold + if strategy.Params != nil { + priorityThreshold = &api.PriorityThreshold{ + Value: strategy.Params.ThresholdPriority, + Name: strategy.Params.ThresholdPriorityClassName, + } + } + thresholdPriority, err := utils.GetPriorityFromStrategyParams(context.TODO(), client, priorityThreshold) + if err != nil { + klog.ErrorS(err, "Failed to get threshold priority from strategy's params") + return nil, fmt.Errorf("failed to get threshold priority from strategy's params: %v", err) + } + + var pluginConfig *api.PluginConfig + if pcFnc, exists := StrategyParamsToPluginArgs[string(name)]; exists { + pluginConfig, err = pcFnc(params) + if err != nil { + klog.ErrorS(err, "skipping strategy", "strategy", name) + return nil, fmt.Errorf("failed to get plugin config for strategy %v: %v", name, err) + } + } else { + klog.ErrorS(fmt.Errorf("unknown strategy name"), "skipping strategy", "strategy", name) + return nil, fmt.Errorf("unknown strategy name: %v", name) + } + + profile := api.Profile{ + Name: fmt.Sprintf("strategy-%v-profile", name), + PluginConfigs: []api.PluginConfig{ + { + Name: defaultevictor.PluginName, + Args: &defaultevictor.DefaultEvictorArgs{ + EvictLocalStoragePods: evictLocalStoragePods, + EvictSystemCriticalPods: evictSystemCriticalPods, + IgnorePvcPods: ignorePvcPods, + EvictFailedBarePods: evictBarePods, + NodeFit: nodeFit, + PriorityThreshold: &api.PriorityThreshold{ + Value: &thresholdPriority, + }, + }, + }, + *pluginConfig, + }, + Plugins: api.Plugins{ + Evict: api.PluginSet{ + Enabled: []string{defaultevictor.PluginName}, + }, + }, + } + + 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 { + klog.ErrorS(fmt.Errorf("unknown strategy name"), "skipping strategy", "strategy", name) + return nil, fmt.Errorf("unknown strategy name: %v", name) + } + } + + return &api.DeschedulerPolicy{ + Profiles: profiles, + NodeSelector: deschedulerPolicy.NodeSelector, + MaxNoOfPodsToEvictPerNode: deschedulerPolicy.MaxNoOfPodsToEvictPerNode, + 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 { + _, ok := pluginInstance.(framework.BalancePlugin) + if ok { + klog.V(3).Info("converting Balance plugin: %s", pluginInstance.Name()) + profilePlugins.Balance.Enabled = []string{pluginConfig.Name} + } + return profilePlugins +} + +func checkDeschedule(profilePlugins api.Plugins, pluginInstance framework.Plugin, pluginConfig *api.PluginConfig) api.Plugins { + _, ok := pluginInstance.(framework.DeschedulePlugin) + if ok { + klog.V(3).Info("converting Deschedule plugin: %s", pluginInstance.Name()) + profilePlugins.Deschedule.Enabled = []string{pluginConfig.Name} + } + return profilePlugins +} diff --git a/pkg/descheduler/strategy_migration.go b/pkg/api/v1alpha1/strategymigration.go similarity index 85% rename from pkg/descheduler/strategy_migration.go rename to pkg/api/v1alpha1/strategymigration.go index 09fafac9db..302b768ce9 100644 --- a/pkg/descheduler/strategy_migration.go +++ b/pkg/api/v1alpha1/strategymigration.go @@ -1,5 +1,5 @@ /* -Copyright 2022 The Kubernetes Authors. +Copyright 2023 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. @@ -14,14 +14,13 @@ See the License for the specific language governing permissions and limitations under the License. */ -package descheduler +package v1alpha1 import ( "fmt" "k8s.io/klog/v2" "sigs.k8s.io/descheduler/pkg/api" - "sigs.k8s.io/descheduler/pkg/api/v1alpha1" "sigs.k8s.io/descheduler/pkg/framework/plugins/nodeutilization" "sigs.k8s.io/descheduler/pkg/framework/plugins/podlifetime" "sigs.k8s.io/descheduler/pkg/framework/plugins/removeduplicates" @@ -37,8 +36,8 @@ import ( // without any wiring. Keeping the wiring here so the descheduler can still use // the v1alpha1 configuration during the strategy migration to plugins. -var strategyParamsToPluginArgs = map[string]func(params *v1alpha1.StrategyParameters) (*api.PluginConfig, error){ - "RemovePodsViolatingNodeTaints": func(params *v1alpha1.StrategyParameters) (*api.PluginConfig, error) { +var StrategyParamsToPluginArgs = map[string]func(params *StrategyParameters) (*api.PluginConfig, error){ + "RemovePodsViolatingNodeTaints": func(params *StrategyParameters) (*api.PluginConfig, error) { args := &removepodsviolatingnodetaints.RemovePodsViolatingNodeTaintsArgs{ Namespaces: v1alpha1NamespacesToInternal(params.Namespaces), LabelSelector: params.LabelSelector, @@ -54,10 +53,10 @@ var strategyParamsToPluginArgs = map[string]func(params *v1alpha1.StrategyParame Args: args, }, nil }, - "RemoveFailedPods": func(params *v1alpha1.StrategyParameters) (*api.PluginConfig, error) { + "RemoveFailedPods": func(params *StrategyParameters) (*api.PluginConfig, error) { failedPodsParams := params.FailedPods if failedPodsParams == nil { - failedPodsParams = &v1alpha1.FailedPods{} + failedPodsParams = &FailedPods{} } args := &removefailedpods.RemoveFailedPodsArgs{ Namespaces: v1alpha1NamespacesToInternal(params.Namespaces), @@ -76,7 +75,7 @@ var strategyParamsToPluginArgs = map[string]func(params *v1alpha1.StrategyParame Args: args, }, nil }, - "RemovePodsViolatingNodeAffinity": func(params *v1alpha1.StrategyParameters) (*api.PluginConfig, error) { + "RemovePodsViolatingNodeAffinity": func(params *StrategyParameters) (*api.PluginConfig, error) { args := &removepodsviolatingnodeaffinity.RemovePodsViolatingNodeAffinityArgs{ Namespaces: v1alpha1NamespacesToInternal(params.Namespaces), LabelSelector: params.LabelSelector, @@ -91,7 +90,7 @@ var strategyParamsToPluginArgs = map[string]func(params *v1alpha1.StrategyParame Args: args, }, nil }, - "RemovePodsViolatingInterPodAntiAffinity": func(params *v1alpha1.StrategyParameters) (*api.PluginConfig, error) { + "RemovePodsViolatingInterPodAntiAffinity": func(params *StrategyParameters) (*api.PluginConfig, error) { args := &removepodsviolatinginterpodantiaffinity.RemovePodsViolatingInterPodAntiAffinityArgs{ Namespaces: v1alpha1NamespacesToInternal(params.Namespaces), LabelSelector: params.LabelSelector, @@ -105,10 +104,10 @@ var strategyParamsToPluginArgs = map[string]func(params *v1alpha1.StrategyParame Args: args, }, nil }, - "RemovePodsHavingTooManyRestarts": func(params *v1alpha1.StrategyParameters) (*api.PluginConfig, error) { + "RemovePodsHavingTooManyRestarts": func(params *StrategyParameters) (*api.PluginConfig, error) { tooManyRestartsParams := params.PodsHavingTooManyRestarts if tooManyRestartsParams == nil { - tooManyRestartsParams = &v1alpha1.PodsHavingTooManyRestarts{} + tooManyRestartsParams = &PodsHavingTooManyRestarts{} } args := &removepodshavingtoomanyrestarts.RemovePodsHavingTooManyRestartsArgs{ Namespaces: v1alpha1NamespacesToInternal(params.Namespaces), @@ -125,10 +124,10 @@ var strategyParamsToPluginArgs = map[string]func(params *v1alpha1.StrategyParame Args: args, }, nil }, - "PodLifeTime": func(params *v1alpha1.StrategyParameters) (*api.PluginConfig, error) { + "PodLifeTime": func(params *StrategyParameters) (*api.PluginConfig, error) { podLifeTimeParams := params.PodLifeTime if podLifeTimeParams == nil { - podLifeTimeParams = &v1alpha1.PodLifeTime{} + podLifeTimeParams = &PodLifeTime{} } var states []string @@ -154,7 +153,7 @@ var strategyParamsToPluginArgs = map[string]func(params *v1alpha1.StrategyParame Args: args, }, nil }, - "RemoveDuplicates": func(params *v1alpha1.StrategyParameters) (*api.PluginConfig, error) { + "RemoveDuplicates": func(params *StrategyParameters) (*api.PluginConfig, error) { args := &removeduplicates.RemoveDuplicatesArgs{ Namespaces: v1alpha1NamespacesToInternal(params.Namespaces), } @@ -170,7 +169,7 @@ var strategyParamsToPluginArgs = map[string]func(params *v1alpha1.StrategyParame Args: args, }, nil }, - "RemovePodsViolatingTopologySpreadConstraint": func(params *v1alpha1.StrategyParameters) (*api.PluginConfig, error) { + "RemovePodsViolatingTopologySpreadConstraint": func(params *StrategyParameters) (*api.PluginConfig, error) { args := &removepodsviolatingtopologyspreadconstraint.RemovePodsViolatingTopologySpreadConstraintArgs{ Namespaces: v1alpha1NamespacesToInternal(params.Namespaces), LabelSelector: params.LabelSelector, @@ -185,9 +184,9 @@ var strategyParamsToPluginArgs = map[string]func(params *v1alpha1.StrategyParame Args: args, }, nil }, - "HighNodeUtilization": func(params *v1alpha1.StrategyParameters) (*api.PluginConfig, error) { + "HighNodeUtilization": func(params *StrategyParameters) (*api.PluginConfig, error) { if params.NodeResourceUtilizationThresholds == nil { - params.NodeResourceUtilizationThresholds = &v1alpha1.NodeResourceUtilizationThresholds{} + params.NodeResourceUtilizationThresholds = &NodeResourceUtilizationThresholds{} } args := &nodeutilization.HighNodeUtilizationArgs{ EvictableNamespaces: v1alpha1NamespacesToInternal(params.Namespaces), @@ -203,9 +202,9 @@ var strategyParamsToPluginArgs = map[string]func(params *v1alpha1.StrategyParame Args: args, }, nil }, - "LowNodeUtilization": func(params *v1alpha1.StrategyParameters) (*api.PluginConfig, error) { + "LowNodeUtilization": func(params *StrategyParameters) (*api.PluginConfig, error) { if params.NodeResourceUtilizationThresholds == nil { - params.NodeResourceUtilizationThresholds = &v1alpha1.NodeResourceUtilizationThresholds{} + params.NodeResourceUtilizationThresholds = &NodeResourceUtilizationThresholds{} } args := &nodeutilization.LowNodeUtilizationArgs{ EvictableNamespaces: v1alpha1NamespacesToInternal(params.Namespaces), @@ -226,7 +225,7 @@ var strategyParamsToPluginArgs = map[string]func(params *v1alpha1.StrategyParame }, } -func v1alpha1NamespacesToInternal(namespaces *v1alpha1.Namespaces) *api.Namespaces { +func v1alpha1NamespacesToInternal(namespaces *Namespaces) *api.Namespaces { internal := &api.Namespaces{} if namespaces != nil { if namespaces.Exclude != nil { @@ -241,7 +240,7 @@ func v1alpha1NamespacesToInternal(namespaces *v1alpha1.Namespaces) *api.Namespac return internal } -func v1alpha1ThresholdToInternal(thresholds v1alpha1.ResourceThresholds) api.ResourceThresholds { +func v1alpha1ThresholdToInternal(thresholds ResourceThresholds) api.ResourceThresholds { internal := make(api.ResourceThresholds, len(thresholds)) for k, v := range thresholds { internal[k] = api.Percentage(float64(v)) diff --git a/pkg/descheduler/strategy_migration_test.go b/pkg/api/v1alpha1/strategymigration_test.go similarity index 79% rename from pkg/descheduler/strategy_migration_test.go rename to pkg/api/v1alpha1/strategymigration_test.go index da342c3d23..9831680142 100644 --- a/pkg/descheduler/strategy_migration_test.go +++ b/pkg/api/v1alpha1/strategymigration_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package descheduler +package v1alpha1 import ( "fmt" @@ -23,7 +23,6 @@ import ( "github.com/google/go-cmp/cmp" utilpointer "k8s.io/utils/pointer" "sigs.k8s.io/descheduler/pkg/api" - "sigs.k8s.io/descheduler/pkg/api/v1alpha1" "sigs.k8s.io/descheduler/pkg/framework/plugins/nodeutilization" "sigs.k8s.io/descheduler/pkg/framework/plugins/podlifetime" "sigs.k8s.io/descheduler/pkg/framework/plugins/removeduplicates" @@ -39,20 +38,20 @@ func TestStrategyParamsToPluginArgsRemovePodsViolatingNodeTaints(t *testing.T) { strategyName := "RemovePodsViolatingNodeTaints" type testCase struct { description string - params *v1alpha1.StrategyParameters + params *StrategyParameters err error result *api.PluginConfig } testCases := []testCase{ { description: "wire in all valid parameters", - params: &v1alpha1.StrategyParameters{ + params: &StrategyParameters{ ExcludedTaints: []string{ "dedicated=special-user", "reserved", }, ThresholdPriority: utilpointer.Int32(100), - Namespaces: &v1alpha1.Namespaces{ + Namespaces: &Namespaces{ Exclude: []string{"test1"}, }, }, @@ -69,8 +68,8 @@ func TestStrategyParamsToPluginArgsRemovePodsViolatingNodeTaints(t *testing.T) { }, { description: "invalid params namespaces", - params: &v1alpha1.StrategyParameters{ - Namespaces: &v1alpha1.Namespaces{ + params: &StrategyParameters{ + Namespaces: &Namespaces{ Exclude: []string{"test1"}, Include: []string{"test2"}, }, @@ -84,7 +83,7 @@ func TestStrategyParamsToPluginArgsRemovePodsViolatingNodeTaints(t *testing.T) { t.Run(tc.description, func(t *testing.T) { var result *api.PluginConfig var err error - if pcFnc, exists := strategyParamsToPluginArgs[strategyName]; exists { + if pcFnc, exists := StrategyParamsToPluginArgs[strategyName]; exists { result, err = pcFnc(tc.params) } if err != nil { @@ -107,22 +106,22 @@ func TestStrategyParamsToPluginArgsRemoveFailedPods(t *testing.T) { strategyName := "RemoveFailedPods" type testCase struct { description string - params *v1alpha1.StrategyParameters + params *StrategyParameters err error result *api.PluginConfig } testCases := []testCase{ { description: "wire in all valid parameters", - params: &v1alpha1.StrategyParameters{ - FailedPods: &v1alpha1.FailedPods{ + params: &StrategyParameters{ + FailedPods: &FailedPods{ MinPodLifetimeSeconds: utilpointer.Uint(3600), ExcludeOwnerKinds: []string{"Job"}, Reasons: []string{"NodeAffinity"}, IncludingInitContainers: true, }, ThresholdPriority: utilpointer.Int32(100), - Namespaces: &v1alpha1.Namespaces{ + Namespaces: &Namespaces{ Exclude: []string{"test1"}, }, }, @@ -142,8 +141,8 @@ func TestStrategyParamsToPluginArgsRemoveFailedPods(t *testing.T) { }, { description: "invalid params namespaces", - params: &v1alpha1.StrategyParameters{ - Namespaces: &v1alpha1.Namespaces{ + params: &StrategyParameters{ + Namespaces: &Namespaces{ Exclude: []string{"test1"}, Include: []string{"test2"}, }, @@ -157,7 +156,7 @@ func TestStrategyParamsToPluginArgsRemoveFailedPods(t *testing.T) { t.Run(tc.description, func(t *testing.T) { var result *api.PluginConfig var err error - if pcFnc, exists := strategyParamsToPluginArgs[strategyName]; exists { + if pcFnc, exists := StrategyParamsToPluginArgs[strategyName]; exists { result, err = pcFnc(tc.params) } if err != nil { @@ -180,17 +179,17 @@ func TestStrategyParamsToPluginArgsRemovePodsViolatingNodeAffinity(t *testing.T) strategyName := "RemovePodsViolatingNodeAffinity" type testCase struct { description string - params *v1alpha1.StrategyParameters + params *StrategyParameters err error result *api.PluginConfig } testCases := []testCase{ { description: "wire in all valid parameters", - params: &v1alpha1.StrategyParameters{ + params: &StrategyParameters{ NodeAffinityType: []string{"requiredDuringSchedulingIgnoredDuringExecution"}, ThresholdPriority: utilpointer.Int32(100), - Namespaces: &v1alpha1.Namespaces{ + Namespaces: &Namespaces{ Exclude: []string{"test1"}, }, }, @@ -207,15 +206,15 @@ func TestStrategyParamsToPluginArgsRemovePodsViolatingNodeAffinity(t *testing.T) }, { description: "invalid params, not setting nodeaffinity type", - params: &v1alpha1.StrategyParameters{}, + params: &StrategyParameters{}, err: fmt.Errorf("strategy \"%s\" param validation failed: nodeAffinityType needs to be set", strategyName), result: nil, }, { description: "invalid params namespaces", - params: &v1alpha1.StrategyParameters{ + params: &StrategyParameters{ NodeAffinityType: []string{"requiredDuringSchedulingIgnoredDuringExecution"}, - Namespaces: &v1alpha1.Namespaces{ + Namespaces: &Namespaces{ Exclude: []string{"test1"}, Include: []string{"test2"}, }, @@ -229,7 +228,7 @@ func TestStrategyParamsToPluginArgsRemovePodsViolatingNodeAffinity(t *testing.T) t.Run(tc.description, func(t *testing.T) { var result *api.PluginConfig var err error - if pcFnc, exists := strategyParamsToPluginArgs[strategyName]; exists { + if pcFnc, exists := StrategyParamsToPluginArgs[strategyName]; exists { result, err = pcFnc(tc.params) } if err != nil { @@ -252,16 +251,16 @@ func TestStrategyParamsToPluginArgsRemovePodsViolatingInterPodAntiAffinity(t *te strategyName := "RemovePodsViolatingInterPodAntiAffinity" type testCase struct { description string - params *v1alpha1.StrategyParameters + params *StrategyParameters err error result *api.PluginConfig } testCases := []testCase{ { description: "wire in all valid parameters", - params: &v1alpha1.StrategyParameters{ + params: &StrategyParameters{ ThresholdPriority: utilpointer.Int32(100), - Namespaces: &v1alpha1.Namespaces{ + Namespaces: &Namespaces{ Exclude: []string{"test1"}, }, }, @@ -277,8 +276,8 @@ func TestStrategyParamsToPluginArgsRemovePodsViolatingInterPodAntiAffinity(t *te }, { description: "invalid params namespaces", - params: &v1alpha1.StrategyParameters{ - Namespaces: &v1alpha1.Namespaces{ + params: &StrategyParameters{ + Namespaces: &Namespaces{ Exclude: []string{"test1"}, Include: []string{"test2"}, }, @@ -292,7 +291,7 @@ func TestStrategyParamsToPluginArgsRemovePodsViolatingInterPodAntiAffinity(t *te t.Run(tc.description, func(t *testing.T) { var result *api.PluginConfig var err error - if pcFnc, exists := strategyParamsToPluginArgs[strategyName]; exists { + if pcFnc, exists := StrategyParamsToPluginArgs[strategyName]; exists { result, err = pcFnc(tc.params) } if err != nil { @@ -315,20 +314,20 @@ func TestStrategyParamsToPluginArgsRemovePodsHavingTooManyRestarts(t *testing.T) strategyName := "RemovePodsHavingTooManyRestarts" type testCase struct { description string - params *v1alpha1.StrategyParameters + params *StrategyParameters err error result *api.PluginConfig } testCases := []testCase{ { description: "wire in all valid parameters", - params: &v1alpha1.StrategyParameters{ - PodsHavingTooManyRestarts: &v1alpha1.PodsHavingTooManyRestarts{ + params: &StrategyParameters{ + PodsHavingTooManyRestarts: &PodsHavingTooManyRestarts{ PodRestartThreshold: 100, IncludingInitContainers: true, }, ThresholdPriority: utilpointer.Int32(100), - Namespaces: &v1alpha1.Namespaces{ + Namespaces: &Namespaces{ Exclude: []string{"test1"}, }, }, @@ -346,8 +345,8 @@ func TestStrategyParamsToPluginArgsRemovePodsHavingTooManyRestarts(t *testing.T) }, { description: "invalid params namespaces", - params: &v1alpha1.StrategyParameters{ - Namespaces: &v1alpha1.Namespaces{ + params: &StrategyParameters{ + Namespaces: &Namespaces{ Exclude: []string{"test1"}, Include: []string{"test2"}, }, @@ -357,8 +356,8 @@ func TestStrategyParamsToPluginArgsRemovePodsHavingTooManyRestarts(t *testing.T) }, { description: "invalid params restart threshold", - params: &v1alpha1.StrategyParameters{ - PodsHavingTooManyRestarts: &v1alpha1.PodsHavingTooManyRestarts{ + params: &StrategyParameters{ + PodsHavingTooManyRestarts: &PodsHavingTooManyRestarts{ PodRestartThreshold: 0, }, }, @@ -371,7 +370,7 @@ func TestStrategyParamsToPluginArgsRemovePodsHavingTooManyRestarts(t *testing.T) t.Run(tc.description, func(t *testing.T) { var result *api.PluginConfig var err error - if pcFnc, exists := strategyParamsToPluginArgs[strategyName]; exists { + if pcFnc, exists := StrategyParamsToPluginArgs[strategyName]; exists { result, err = pcFnc(tc.params) } if err != nil { @@ -394,15 +393,15 @@ func TestStrategyParamsToPluginArgsPodLifeTime(t *testing.T) { strategyName := "PodLifeTime" type testCase struct { description string - params *v1alpha1.StrategyParameters + params *StrategyParameters err error result *api.PluginConfig } testCases := []testCase{ { description: "wire in all valid parameters", - params: &v1alpha1.StrategyParameters{ - PodLifeTime: &v1alpha1.PodLifeTime{ + params: &StrategyParameters{ + PodLifeTime: &PodLifeTime{ MaxPodLifeTimeSeconds: utilpointer.Uint(86400), States: []string{ "Pending", @@ -410,7 +409,7 @@ func TestStrategyParamsToPluginArgsPodLifeTime(t *testing.T) { }, }, ThresholdPriority: utilpointer.Int32(100), - Namespaces: &v1alpha1.Namespaces{ + Namespaces: &Namespaces{ Exclude: []string{"test1"}, }, }, @@ -431,11 +430,11 @@ func TestStrategyParamsToPluginArgsPodLifeTime(t *testing.T) { }, { description: "invalid params namespaces", - params: &v1alpha1.StrategyParameters{ - PodLifeTime: &v1alpha1.PodLifeTime{ + params: &StrategyParameters{ + PodLifeTime: &PodLifeTime{ MaxPodLifeTimeSeconds: utilpointer.Uint(86400), }, - Namespaces: &v1alpha1.Namespaces{ + Namespaces: &Namespaces{ Exclude: []string{"test1"}, Include: []string{"test2"}, }, @@ -445,8 +444,8 @@ func TestStrategyParamsToPluginArgsPodLifeTime(t *testing.T) { }, { description: "invalid params MaxPodLifeTimeSeconds not set", - params: &v1alpha1.StrategyParameters{ - PodLifeTime: &v1alpha1.PodLifeTime{}, + params: &StrategyParameters{ + PodLifeTime: &PodLifeTime{}, }, err: fmt.Errorf("strategy \"%s\" param validation failed: MaxPodLifeTimeSeconds not set", strategyName), result: nil, @@ -457,7 +456,7 @@ func TestStrategyParamsToPluginArgsPodLifeTime(t *testing.T) { t.Run(tc.description, func(t *testing.T) { var result *api.PluginConfig var err error - if pcFnc, exists := strategyParamsToPluginArgs[strategyName]; exists { + if pcFnc, exists := StrategyParamsToPluginArgs[strategyName]; exists { result, err = pcFnc(tc.params) } if err != nil { @@ -480,19 +479,19 @@ func TestStrategyParamsToPluginArgsRemoveDuplicates(t *testing.T) { strategyName := "RemoveDuplicates" type testCase struct { description string - params *v1alpha1.StrategyParameters + params *StrategyParameters err error result *api.PluginConfig } testCases := []testCase{ { description: "wire in all valid parameters", - params: &v1alpha1.StrategyParameters{ - RemoveDuplicates: &v1alpha1.RemoveDuplicates{ + params: &StrategyParameters{ + RemoveDuplicates: &RemoveDuplicates{ ExcludeOwnerKinds: []string{"ReplicaSet"}, }, ThresholdPriority: utilpointer.Int32(100), - Namespaces: &v1alpha1.Namespaces{ + Namespaces: &Namespaces{ Exclude: []string{"test1"}, }, }, @@ -509,11 +508,11 @@ func TestStrategyParamsToPluginArgsRemoveDuplicates(t *testing.T) { }, { description: "invalid params namespaces", - params: &v1alpha1.StrategyParameters{ - PodLifeTime: &v1alpha1.PodLifeTime{ + params: &StrategyParameters{ + PodLifeTime: &PodLifeTime{ MaxPodLifeTimeSeconds: utilpointer.Uint(86400), }, - Namespaces: &v1alpha1.Namespaces{ + Namespaces: &Namespaces{ Exclude: []string{"test1"}, Include: []string{"test2"}, }, @@ -527,7 +526,7 @@ func TestStrategyParamsToPluginArgsRemoveDuplicates(t *testing.T) { t.Run(tc.description, func(t *testing.T) { var result *api.PluginConfig var err error - if pcFnc, exists := strategyParamsToPluginArgs[strategyName]; exists { + if pcFnc, exists := StrategyParamsToPluginArgs[strategyName]; exists { result, err = pcFnc(tc.params) } if err != nil { @@ -550,17 +549,17 @@ func TestStrategyParamsToPluginArgsRemovePodsViolatingTopologySpreadConstraint(t strategyName := "RemovePodsViolatingTopologySpreadConstraint" type testCase struct { description string - params *v1alpha1.StrategyParameters + params *StrategyParameters err error result *api.PluginConfig } testCases := []testCase{ { description: "wire in all valid parameters", - params: &v1alpha1.StrategyParameters{ + params: &StrategyParameters{ IncludeSoftConstraints: true, ThresholdPriority: utilpointer.Int32(100), - Namespaces: &v1alpha1.Namespaces{ + Namespaces: &Namespaces{ Exclude: []string{"test1"}, }, }, @@ -577,8 +576,8 @@ func TestStrategyParamsToPluginArgsRemovePodsViolatingTopologySpreadConstraint(t }, { description: "invalid params namespaces", - params: &v1alpha1.StrategyParameters{ - Namespaces: &v1alpha1.Namespaces{ + params: &StrategyParameters{ + Namespaces: &Namespaces{ Exclude: []string{"test1"}, Include: []string{"test2"}, }, @@ -592,7 +591,7 @@ func TestStrategyParamsToPluginArgsRemovePodsViolatingTopologySpreadConstraint(t t.Run(tc.description, func(t *testing.T) { var result *api.PluginConfig var err error - if pcFnc, exists := strategyParamsToPluginArgs[strategyName]; exists { + if pcFnc, exists := StrategyParamsToPluginArgs[strategyName]; exists { result, err = pcFnc(tc.params) } if err != nil { @@ -615,24 +614,24 @@ func TestStrategyParamsToPluginArgsHighNodeUtilization(t *testing.T) { strategyName := "HighNodeUtilization" type testCase struct { description string - params *v1alpha1.StrategyParameters + params *StrategyParameters err error result *api.PluginConfig } testCases := []testCase{ { description: "wire in all valid parameters", - params: &v1alpha1.StrategyParameters{ - NodeResourceUtilizationThresholds: &v1alpha1.NodeResourceUtilizationThresholds{ + params: &StrategyParameters{ + NodeResourceUtilizationThresholds: &NodeResourceUtilizationThresholds{ NumberOfNodes: 3, - Thresholds: v1alpha1.ResourceThresholds{ - "cpu": v1alpha1.Percentage(20), - "memory": v1alpha1.Percentage(20), - "pods": v1alpha1.Percentage(20), + Thresholds: ResourceThresholds{ + "cpu": Percentage(20), + "memory": Percentage(20), + "pods": Percentage(20), }, }, ThresholdPriority: utilpointer.Int32(100), - Namespaces: &v1alpha1.Namespaces{ + Namespaces: &Namespaces{ Exclude: []string{"test1"}, }, }, @@ -654,16 +653,16 @@ func TestStrategyParamsToPluginArgsHighNodeUtilization(t *testing.T) { }, { description: "invalid params namespaces", - params: &v1alpha1.StrategyParameters{ - NodeResourceUtilizationThresholds: &v1alpha1.NodeResourceUtilizationThresholds{ + params: &StrategyParameters{ + NodeResourceUtilizationThresholds: &NodeResourceUtilizationThresholds{ NumberOfNodes: 3, - Thresholds: v1alpha1.ResourceThresholds{ - "cpu": v1alpha1.Percentage(20), - "memory": v1alpha1.Percentage(20), - "pods": v1alpha1.Percentage(20), + Thresholds: ResourceThresholds{ + "cpu": Percentage(20), + "memory": Percentage(20), + "pods": Percentage(20), }, }, - Namespaces: &v1alpha1.Namespaces{ + Namespaces: &Namespaces{ Include: []string{"test2"}, }, }, @@ -672,8 +671,8 @@ func TestStrategyParamsToPluginArgsHighNodeUtilization(t *testing.T) { }, { description: "invalid params nil ResourceThresholds", - params: &v1alpha1.StrategyParameters{ - NodeResourceUtilizationThresholds: &v1alpha1.NodeResourceUtilizationThresholds{ + params: &StrategyParameters{ + NodeResourceUtilizationThresholds: &NodeResourceUtilizationThresholds{ NumberOfNodes: 3, }, }, @@ -682,11 +681,11 @@ func TestStrategyParamsToPluginArgsHighNodeUtilization(t *testing.T) { }, { description: "invalid params out of bounds threshold", - params: &v1alpha1.StrategyParameters{ - NodeResourceUtilizationThresholds: &v1alpha1.NodeResourceUtilizationThresholds{ + params: &StrategyParameters{ + NodeResourceUtilizationThresholds: &NodeResourceUtilizationThresholds{ NumberOfNodes: 3, - Thresholds: v1alpha1.ResourceThresholds{ - "cpu": v1alpha1.Percentage(150), + Thresholds: ResourceThresholds{ + "cpu": Percentage(150), }, }, }, @@ -699,7 +698,7 @@ func TestStrategyParamsToPluginArgsHighNodeUtilization(t *testing.T) { t.Run(tc.description, func(t *testing.T) { var result *api.PluginConfig var err error - if pcFnc, exists := strategyParamsToPluginArgs[strategyName]; exists { + if pcFnc, exists := StrategyParamsToPluginArgs[strategyName]; exists { result, err = pcFnc(tc.params) } if err != nil { @@ -722,30 +721,30 @@ func TestStrategyParamsToPluginArgsLowNodeUtilization(t *testing.T) { strategyName := "LowNodeUtilization" type testCase struct { description string - params *v1alpha1.StrategyParameters + params *StrategyParameters err error result *api.PluginConfig } testCases := []testCase{ { description: "wire in all valid parameters", - params: &v1alpha1.StrategyParameters{ - NodeResourceUtilizationThresholds: &v1alpha1.NodeResourceUtilizationThresholds{ + params: &StrategyParameters{ + NodeResourceUtilizationThresholds: &NodeResourceUtilizationThresholds{ NumberOfNodes: 3, - Thresholds: v1alpha1.ResourceThresholds{ - "cpu": v1alpha1.Percentage(20), - "memory": v1alpha1.Percentage(20), - "pods": v1alpha1.Percentage(20), + Thresholds: ResourceThresholds{ + "cpu": Percentage(20), + "memory": Percentage(20), + "pods": Percentage(20), }, - TargetThresholds: v1alpha1.ResourceThresholds{ - "cpu": v1alpha1.Percentage(50), - "memory": v1alpha1.Percentage(50), - "pods": v1alpha1.Percentage(50), + TargetThresholds: ResourceThresholds{ + "cpu": Percentage(50), + "memory": Percentage(50), + "pods": Percentage(50), }, UseDeviationThresholds: true, }, ThresholdPriority: utilpointer.Int32(100), - Namespaces: &v1alpha1.Namespaces{ + Namespaces: &Namespaces{ Exclude: []string{"test1"}, }, }, @@ -773,22 +772,22 @@ func TestStrategyParamsToPluginArgsLowNodeUtilization(t *testing.T) { }, { description: "invalid params namespaces", - params: &v1alpha1.StrategyParameters{ - NodeResourceUtilizationThresholds: &v1alpha1.NodeResourceUtilizationThresholds{ + params: &StrategyParameters{ + NodeResourceUtilizationThresholds: &NodeResourceUtilizationThresholds{ NumberOfNodes: 3, - Thresholds: v1alpha1.ResourceThresholds{ - "cpu": v1alpha1.Percentage(20), - "memory": v1alpha1.Percentage(20), - "pods": v1alpha1.Percentage(20), + Thresholds: ResourceThresholds{ + "cpu": Percentage(20), + "memory": Percentage(20), + "pods": Percentage(20), }, - TargetThresholds: v1alpha1.ResourceThresholds{ - "cpu": v1alpha1.Percentage(50), - "memory": v1alpha1.Percentage(50), - "pods": v1alpha1.Percentage(50), + TargetThresholds: ResourceThresholds{ + "cpu": Percentage(50), + "memory": Percentage(50), + "pods": Percentage(50), }, UseDeviationThresholds: true, }, - Namespaces: &v1alpha1.Namespaces{ + Namespaces: &Namespaces{ Include: []string{"test2"}, }, }, @@ -797,8 +796,8 @@ func TestStrategyParamsToPluginArgsLowNodeUtilization(t *testing.T) { }, { description: "invalid params nil ResourceThresholds", - params: &v1alpha1.StrategyParameters{ - NodeResourceUtilizationThresholds: &v1alpha1.NodeResourceUtilizationThresholds{ + params: &StrategyParameters{ + NodeResourceUtilizationThresholds: &NodeResourceUtilizationThresholds{ NumberOfNodes: 3, }, }, @@ -807,11 +806,11 @@ func TestStrategyParamsToPluginArgsLowNodeUtilization(t *testing.T) { }, { description: "invalid params out of bounds threshold", - params: &v1alpha1.StrategyParameters{ - NodeResourceUtilizationThresholds: &v1alpha1.NodeResourceUtilizationThresholds{ + params: &StrategyParameters{ + NodeResourceUtilizationThresholds: &NodeResourceUtilizationThresholds{ NumberOfNodes: 3, - Thresholds: v1alpha1.ResourceThresholds{ - "cpu": v1alpha1.Percentage(150), + Thresholds: ResourceThresholds{ + "cpu": Percentage(150), }, }, }, @@ -824,7 +823,7 @@ func TestStrategyParamsToPluginArgsLowNodeUtilization(t *testing.T) { t.Run(tc.description, func(t *testing.T) { var result *api.PluginConfig var err error - if pcFnc, exists := strategyParamsToPluginArgs[strategyName]; exists { + if pcFnc, exists := StrategyParamsToPluginArgs[strategyName]; exists { result, err = pcFnc(tc.params) } if err != nil { diff --git a/pkg/api/v1alpha1/zz_generated.deepcopy.go b/pkg/api/v1alpha1/zz_generated.deepcopy.go index 2a45492c5d..a73ef1f88e 100644 --- a/pkg/api/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/api/v1alpha1/zz_generated.deepcopy.go @@ -2,7 +2,7 @@ // +build !ignore_autogenerated /* -Copyright 2022 The Kubernetes Authors. +Copyright 2023 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. diff --git a/pkg/api/v1alpha1/zz_generated.defaults.go b/pkg/api/v1alpha1/zz_generated.defaults.go index c450647048..94e098c8da 100644 --- a/pkg/api/v1alpha1/zz_generated.defaults.go +++ b/pkg/api/v1alpha1/zz_generated.defaults.go @@ -2,7 +2,7 @@ // +build !ignore_autogenerated /* -Copyright 2022 The Kubernetes Authors. +Copyright 2023 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. diff --git a/pkg/api/v1alpha2/conversion.go b/pkg/api/v1alpha2/conversion.go new file mode 100644 index 0000000000..36c95e5ca1 --- /dev/null +++ b/pkg/api/v1alpha2/conversion.go @@ -0,0 +1,136 @@ +/* +Copyright 2023 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 v1alpha2 + +import ( + "fmt" + "sync" + + "k8s.io/apimachinery/pkg/conversion" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/serializer" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + api "sigs.k8s.io/descheduler/pkg/api" + + "sigs.k8s.io/descheduler/pkg/framework/pluginregistry" +) + +var ( + // pluginArgConversionScheme is a scheme with internal and v1alpha2 registered, + // used for defaulting/converting typed PluginConfig Args. + // Access via getPluginArgConversionScheme() + pluginArgConversionScheme *runtime.Scheme + initPluginArgConversionScheme sync.Once + + Scheme = runtime.NewScheme() + Codecs = serializer.NewCodecFactory(Scheme, serializer.EnableStrict) +) + +func GetPluginArgConversionScheme() *runtime.Scheme { + initPluginArgConversionScheme.Do(func() { + // set up the scheme used for plugin arg conversion + pluginArgConversionScheme = runtime.NewScheme() + utilruntime.Must(AddToScheme(pluginArgConversionScheme)) + utilruntime.Must(api.AddToScheme(pluginArgConversionScheme)) + }) + return pluginArgConversionScheme +} + +func Convert_v1alpha2_DeschedulerPolicy_To_api_DeschedulerPolicy(in *DeschedulerPolicy, out *api.DeschedulerPolicy, s conversion.Scope) error { + if err := autoConvert_v1alpha2_DeschedulerPolicy_To_api_DeschedulerPolicy(in, out, s); err != nil { + return err + } + return convertToInternalPluginConfigArgs(out) +} + +// convertToInternalPluginConfigArgs converts PluginConfig#Args into internal +// types using a scheme, after applying defaults. +func convertToInternalPluginConfigArgs(out *api.DeschedulerPolicy) error { + scheme := GetPluginArgConversionScheme() + for i := range out.Profiles { + prof := &out.Profiles[i] + for j := range prof.PluginConfigs { + args := prof.PluginConfigs[j].Args + if args == nil { + continue + } + if _, isUnknown := args.(*runtime.Unknown); isUnknown { + continue + } + internalArgs, err := scheme.ConvertToVersion(args, api.SchemeGroupVersion) + if err != nil { + err = nil + internalArgs = args + if err != nil { + return fmt.Errorf("converting .Profiles[%d].PluginConfigs[%d].Args into internal type: %w", i, j, err) + } + } + prof.PluginConfigs[j].Args = internalArgs + } + } + return nil +} + +func Convert_v1alpha2_PluginConfig_To_api_PluginConfig(in *PluginConfig, out *api.PluginConfig, s conversion.Scope) error { + out.Name = in.Name + if _, ok := pluginregistry.PluginRegistry[in.Name]; ok { + out.Args = pluginregistry.PluginRegistry[in.Name].PluginArgInstance + if in.Args.Raw != nil { + _, _, err := Codecs.UniversalDecoder().Decode(in.Args.Raw, nil, out.Args) + if err != nil { + return err + } + } else if in.Args.Object != nil { + out.Args = in.Args.Object + } + } else { + if err := runtime.Convert_runtime_RawExtension_To_runtime_Object(&in.Args, &out.Args, s); err != nil { + return err + } + } + return nil +} + +func Convert_api_DeschedulerPolicy_To_v1alpha2_DeschedulerPolicy(in *api.DeschedulerPolicy, out *DeschedulerPolicy, s conversion.Scope) error { + if err := autoConvert_api_DeschedulerPolicy_To_v1alpha2_DeschedulerPolicy(in, out, s); err != nil { + return err + } + return convertToExternalPluginConfigArgs(out) +} + +// convertToExternalPluginConfigArgs converts PluginConfig#Args into +// external (versioned) types using a scheme. +func convertToExternalPluginConfigArgs(out *DeschedulerPolicy) error { + scheme := GetPluginArgConversionScheme() + for i := range out.Profiles { + for j := range out.Profiles[i].PluginConfigs { + args := out.Profiles[i].PluginConfigs[j].Args + if args.Object == nil { + continue + } + if _, isUnknown := args.Object.(*runtime.Unknown); isUnknown { + continue + } + externalArgs, err := scheme.ConvertToVersion(args.Object, SchemeGroupVersion) + if err != nil { + return err + } + out.Profiles[i].PluginConfigs[j].Args.Object = externalArgs + } + } + return nil +} diff --git a/pkg/api/v1alpha2/defaults.go b/pkg/api/v1alpha2/defaults.go new file mode 100644 index 0000000000..801d530cab --- /dev/null +++ b/pkg/api/v1alpha2/defaults.go @@ -0,0 +1,23 @@ +/* +Copyright 2023 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 v1alpha2 + +import "k8s.io/apimachinery/pkg/runtime" + +func addDefaultingFuncs(scheme *runtime.Scheme) error { + return RegisterDefaults(scheme) +} diff --git a/pkg/api/v1alpha2/doc.go b/pkg/api/v1alpha2/doc.go new file mode 100644 index 0000000000..2d7dff1ed5 --- /dev/null +++ b/pkg/api/v1alpha2/doc.go @@ -0,0 +1,24 @@ +/* +Copyright 2023 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. +*/ + +// +k8s:deepcopy-gen=package,register +// +k8s:conversion-gen=sigs.k8s.io/descheduler/pkg/api +// +k8s:defaulter-gen=TypeMeta + +// Package v1alpha2 is the v1alpha2 version of the descheduler API +// +groupName=descheduler + +package v1alpha2 // import "sigs.k8s.io/descheduler/pkg/api/v1alpha2" diff --git a/pkg/api/v1alpha2/register.go b/pkg/api/v1alpha2/register.go new file mode 100644 index 0000000000..b975e416bc --- /dev/null +++ b/pkg/api/v1alpha2/register.go @@ -0,0 +1,61 @@ +/* +Copyright 2023 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 v1alpha2 + +import ( + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +var ( + SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) + localSchemeBuilder = &SchemeBuilder + AddToScheme = SchemeBuilder.AddToScheme +) + +// GroupName is the group name used in this package +const GroupName = "descheduler" +const GroupVersion = "v1alpha2" + +// SchemeGroupVersion is group version used to register these objects +var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: GroupVersion} + +// Kind takes an unqualified kind and returns a Group qualified GroupKind +func Kind(kind string) schema.GroupKind { + return SchemeGroupVersion.WithKind(kind).GroupKind() +} + +// Resource takes an unqualified resource and returns a Group qualified GroupResource +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} + +func init() { + // We only register manually written functions here. The registration of the + // generated functions takes place in the generated files. The separation + // makes the code compile even when the generated files are missing. + localSchemeBuilder.Register(addKnownTypes, addDefaultingFuncs) +} + +func addKnownTypes(scheme *runtime.Scheme) error { + // TODO this will get cleaned up with the scheme types are fixed + scheme.AddKnownTypes(SchemeGroupVersion, + &DeschedulerPolicy{}, + ) + + return nil +} diff --git a/pkg/api/v1alpha2/sort.go b/pkg/api/v1alpha2/sort.go new file mode 100644 index 0000000000..a3f659df3f --- /dev/null +++ b/pkg/api/v1alpha2/sort.go @@ -0,0 +1,26 @@ +/* +Copyright 2023 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 v1alpha2 + +import "sort" + +func SortProfilesByName(profiles []Profile) []Profile { + sort.Slice(profiles, func(i, j int) bool { + return profiles[i].Name < profiles[j].Name + }) + return profiles +} diff --git a/pkg/api/v1alpha2/types.go b/pkg/api/v1alpha2/types.go new file mode 100644 index 0000000000..b1b47467fb --- /dev/null +++ b/pkg/api/v1alpha2/types.go @@ -0,0 +1,66 @@ +/* +Copyright 2023 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 v1alpha2 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" +) + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +type DeschedulerPolicy struct { + metav1.TypeMeta `json:",inline"` + + // Profiles + Profiles []Profile `json:"profiles,omitempty"` + + // NodeSelector for a set of nodes to operate over + NodeSelector *string `json:"nodeSelector,omitempty"` + + // MaxNoOfPodsToEvictPerNode restricts maximum of pods to be evicted per node. + MaxNoOfPodsToEvictPerNode *uint `json:"maxNoOfPodsToEvictPerNode,omitempty"` + + // MaxNoOfPodsToEvictPerNamespace restricts maximum of pods to be evicted per namespace. + MaxNoOfPodsToEvictPerNamespace *uint `json:"maxNoOfPodsToEvictPerNamespace,omitempty"` +} + +type Profile struct { + Name string `json:"name"` + PluginConfigs []PluginConfig `json:"pluginConfig"` + Plugins Plugins `json:"plugins"` +} + +type Plugins struct { + PreSort PluginSet `json:"presort"` + Sort PluginSet `json:"sort"` + Deschedule PluginSet `json:"deschedule"` + Balance PluginSet `json:"balance"` + Evict PluginSet `json:"evict"` + Filter PluginSet `json:"filter"` + PreEvictionFilter PluginSet `json:"preevictionfilter"` +} + +type PluginConfig struct { + Name string `json:"name"` + Args runtime.RawExtension `json:"args"` +} + +type PluginSet struct { + Enabled []string `json:"enabled"` + Disabled []string `json:"disabled"` +} diff --git a/pkg/api/v1alpha2/zz_generated.conversion.go b/pkg/api/v1alpha2/zz_generated.conversion.go new file mode 100644 index 0000000000..0852ba0e37 --- /dev/null +++ b/pkg/api/v1alpha2/zz_generated.conversion.go @@ -0,0 +1,277 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +/* +Copyright 2023 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. +*/ + +// Code generated by conversion-gen. DO NOT EDIT. + +package v1alpha2 + +import ( + unsafe "unsafe" + + conversion "k8s.io/apimachinery/pkg/conversion" + runtime "k8s.io/apimachinery/pkg/runtime" + api "sigs.k8s.io/descheduler/pkg/api" +) + +func init() { + localSchemeBuilder.Register(RegisterConversions) +} + +// RegisterConversions adds conversion functions to the given scheme. +// Public to allow building arbitrary schemes. +func RegisterConversions(s *runtime.Scheme) error { + if err := s.AddGeneratedConversionFunc((*api.PluginConfig)(nil), (*PluginConfig)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_api_PluginConfig_To_v1alpha2_PluginConfig(a.(*api.PluginConfig), b.(*PluginConfig), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*PluginSet)(nil), (*api.PluginSet)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha2_PluginSet_To_api_PluginSet(a.(*PluginSet), b.(*api.PluginSet), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*api.PluginSet)(nil), (*PluginSet)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_api_PluginSet_To_v1alpha2_PluginSet(a.(*api.PluginSet), b.(*PluginSet), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*Plugins)(nil), (*api.Plugins)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha2_Plugins_To_api_Plugins(a.(*Plugins), b.(*api.Plugins), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*api.Plugins)(nil), (*Plugins)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_api_Plugins_To_v1alpha2_Plugins(a.(*api.Plugins), b.(*Plugins), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*Profile)(nil), (*api.Profile)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha2_Profile_To_api_Profile(a.(*Profile), b.(*api.Profile), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*api.Profile)(nil), (*Profile)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_api_Profile_To_v1alpha2_Profile(a.(*api.Profile), b.(*Profile), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*api.DeschedulerPolicy)(nil), (*DeschedulerPolicy)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_api_DeschedulerPolicy_To_v1alpha2_DeschedulerPolicy(a.(*api.DeschedulerPolicy), b.(*DeschedulerPolicy), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*DeschedulerPolicy)(nil), (*api.DeschedulerPolicy)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha2_DeschedulerPolicy_To_api_DeschedulerPolicy(a.(*DeschedulerPolicy), b.(*api.DeschedulerPolicy), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*PluginConfig)(nil), (*api.PluginConfig)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha2_PluginConfig_To_api_PluginConfig(a.(*PluginConfig), b.(*api.PluginConfig), scope) + }); err != nil { + return err + } + return nil +} + +func autoConvert_v1alpha2_DeschedulerPolicy_To_api_DeschedulerPolicy(in *DeschedulerPolicy, out *api.DeschedulerPolicy, s conversion.Scope) error { + if in.Profiles != nil { + in, out := &in.Profiles, &out.Profiles + *out = make([]api.Profile, len(*in)) + for i := range *in { + if err := Convert_v1alpha2_Profile_To_api_Profile(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.Profiles = nil + } + out.NodeSelector = (*string)(unsafe.Pointer(in.NodeSelector)) + out.MaxNoOfPodsToEvictPerNode = (*uint)(unsafe.Pointer(in.MaxNoOfPodsToEvictPerNode)) + out.MaxNoOfPodsToEvictPerNamespace = (*uint)(unsafe.Pointer(in.MaxNoOfPodsToEvictPerNamespace)) + return nil +} + +func autoConvert_api_DeschedulerPolicy_To_v1alpha2_DeschedulerPolicy(in *api.DeschedulerPolicy, out *DeschedulerPolicy, s conversion.Scope) error { + if in.Profiles != nil { + in, out := &in.Profiles, &out.Profiles + *out = make([]Profile, len(*in)) + for i := range *in { + if err := Convert_api_Profile_To_v1alpha2_Profile(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.Profiles = nil + } + out.NodeSelector = (*string)(unsafe.Pointer(in.NodeSelector)) + out.MaxNoOfPodsToEvictPerNode = (*uint)(unsafe.Pointer(in.MaxNoOfPodsToEvictPerNode)) + out.MaxNoOfPodsToEvictPerNamespace = (*uint)(unsafe.Pointer(in.MaxNoOfPodsToEvictPerNamespace)) + return nil +} + +func autoConvert_v1alpha2_PluginConfig_To_api_PluginConfig(in *PluginConfig, out *api.PluginConfig, s conversion.Scope) error { + out.Name = in.Name + if err := runtime.Convert_runtime_RawExtension_To_runtime_Object(&in.Args, &out.Args, s); err != nil { + return err + } + return nil +} + +func autoConvert_api_PluginConfig_To_v1alpha2_PluginConfig(in *api.PluginConfig, out *PluginConfig, s conversion.Scope) error { + out.Name = in.Name + if err := runtime.Convert_runtime_Object_To_runtime_RawExtension(&in.Args, &out.Args, s); err != nil { + return err + } + return nil +} + +// Convert_api_PluginConfig_To_v1alpha2_PluginConfig is an autogenerated conversion function. +func Convert_api_PluginConfig_To_v1alpha2_PluginConfig(in *api.PluginConfig, out *PluginConfig, s conversion.Scope) error { + return autoConvert_api_PluginConfig_To_v1alpha2_PluginConfig(in, out, s) +} + +func autoConvert_v1alpha2_PluginSet_To_api_PluginSet(in *PluginSet, out *api.PluginSet, s conversion.Scope) error { + out.Enabled = *(*[]string)(unsafe.Pointer(&in.Enabled)) + out.Disabled = *(*[]string)(unsafe.Pointer(&in.Disabled)) + return nil +} + +// Convert_v1alpha2_PluginSet_To_api_PluginSet is an autogenerated conversion function. +func Convert_v1alpha2_PluginSet_To_api_PluginSet(in *PluginSet, out *api.PluginSet, s conversion.Scope) error { + return autoConvert_v1alpha2_PluginSet_To_api_PluginSet(in, out, s) +} + +func autoConvert_api_PluginSet_To_v1alpha2_PluginSet(in *api.PluginSet, out *PluginSet, s conversion.Scope) error { + out.Enabled = *(*[]string)(unsafe.Pointer(&in.Enabled)) + out.Disabled = *(*[]string)(unsafe.Pointer(&in.Disabled)) + return nil +} + +// Convert_api_PluginSet_To_v1alpha2_PluginSet is an autogenerated conversion function. +func Convert_api_PluginSet_To_v1alpha2_PluginSet(in *api.PluginSet, out *PluginSet, s conversion.Scope) error { + return autoConvert_api_PluginSet_To_v1alpha2_PluginSet(in, out, s) +} + +func autoConvert_v1alpha2_Plugins_To_api_Plugins(in *Plugins, out *api.Plugins, s conversion.Scope) error { + if err := Convert_v1alpha2_PluginSet_To_api_PluginSet(&in.PreSort, &out.PreSort, s); err != nil { + return err + } + if err := Convert_v1alpha2_PluginSet_To_api_PluginSet(&in.Sort, &out.Sort, s); err != nil { + return err + } + if err := Convert_v1alpha2_PluginSet_To_api_PluginSet(&in.Deschedule, &out.Deschedule, s); err != nil { + return err + } + if err := Convert_v1alpha2_PluginSet_To_api_PluginSet(&in.Balance, &out.Balance, s); err != nil { + return err + } + if err := Convert_v1alpha2_PluginSet_To_api_PluginSet(&in.Evict, &out.Evict, s); err != nil { + return err + } + if err := Convert_v1alpha2_PluginSet_To_api_PluginSet(&in.Filter, &out.Filter, s); err != nil { + return err + } + if err := Convert_v1alpha2_PluginSet_To_api_PluginSet(&in.PreEvictionFilter, &out.PreEvictionFilter, s); err != nil { + return err + } + return nil +} + +// Convert_v1alpha2_Plugins_To_api_Plugins is an autogenerated conversion function. +func Convert_v1alpha2_Plugins_To_api_Plugins(in *Plugins, out *api.Plugins, s conversion.Scope) error { + return autoConvert_v1alpha2_Plugins_To_api_Plugins(in, out, s) +} + +func autoConvert_api_Plugins_To_v1alpha2_Plugins(in *api.Plugins, out *Plugins, s conversion.Scope) error { + if err := Convert_api_PluginSet_To_v1alpha2_PluginSet(&in.PreSort, &out.PreSort, s); err != nil { + return err + } + if err := Convert_api_PluginSet_To_v1alpha2_PluginSet(&in.Sort, &out.Sort, s); err != nil { + return err + } + if err := Convert_api_PluginSet_To_v1alpha2_PluginSet(&in.Deschedule, &out.Deschedule, s); err != nil { + return err + } + if err := Convert_api_PluginSet_To_v1alpha2_PluginSet(&in.Balance, &out.Balance, s); err != nil { + return err + } + if err := Convert_api_PluginSet_To_v1alpha2_PluginSet(&in.Evict, &out.Evict, s); err != nil { + return err + } + if err := Convert_api_PluginSet_To_v1alpha2_PluginSet(&in.Filter, &out.Filter, s); err != nil { + return err + } + if err := Convert_api_PluginSet_To_v1alpha2_PluginSet(&in.PreEvictionFilter, &out.PreEvictionFilter, s); err != nil { + return err + } + return nil +} + +// Convert_api_Plugins_To_v1alpha2_Plugins is an autogenerated conversion function. +func Convert_api_Plugins_To_v1alpha2_Plugins(in *api.Plugins, out *Plugins, s conversion.Scope) error { + return autoConvert_api_Plugins_To_v1alpha2_Plugins(in, out, s) +} + +func autoConvert_v1alpha2_Profile_To_api_Profile(in *Profile, out *api.Profile, s conversion.Scope) error { + out.Name = in.Name + if in.PluginConfigs != nil { + in, out := &in.PluginConfigs, &out.PluginConfigs + *out = make([]api.PluginConfig, len(*in)) + for i := range *in { + if err := Convert_v1alpha2_PluginConfig_To_api_PluginConfig(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.PluginConfigs = nil + } + if err := Convert_v1alpha2_Plugins_To_api_Plugins(&in.Plugins, &out.Plugins, s); err != nil { + return err + } + return nil +} + +// Convert_v1alpha2_Profile_To_api_Profile is an autogenerated conversion function. +func Convert_v1alpha2_Profile_To_api_Profile(in *Profile, out *api.Profile, s conversion.Scope) error { + return autoConvert_v1alpha2_Profile_To_api_Profile(in, out, s) +} + +func autoConvert_api_Profile_To_v1alpha2_Profile(in *api.Profile, out *Profile, s conversion.Scope) error { + out.Name = in.Name + if in.PluginConfigs != nil { + in, out := &in.PluginConfigs, &out.PluginConfigs + *out = make([]PluginConfig, len(*in)) + for i := range *in { + if err := Convert_api_PluginConfig_To_v1alpha2_PluginConfig(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.PluginConfigs = nil + } + if err := Convert_api_Plugins_To_v1alpha2_Plugins(&in.Plugins, &out.Plugins, s); err != nil { + return err + } + return nil +} + +// Convert_api_Profile_To_v1alpha2_Profile is an autogenerated conversion function. +func Convert_api_Profile_To_v1alpha2_Profile(in *api.Profile, out *Profile, s conversion.Scope) error { + return autoConvert_api_Profile_To_v1alpha2_Profile(in, out, s) +} diff --git a/pkg/api/v1alpha2/zz_generated.deepcopy.go b/pkg/api/v1alpha2/zz_generated.deepcopy.go new file mode 100644 index 0000000000..63f375381a --- /dev/null +++ b/pkg/api/v1alpha2/zz_generated.deepcopy.go @@ -0,0 +1,163 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +/* +Copyright 2023 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. +*/ + +// Code generated by deepcopy-gen. DO NOT EDIT. + +package v1alpha2 + +import ( + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DeschedulerPolicy) DeepCopyInto(out *DeschedulerPolicy) { + *out = *in + out.TypeMeta = in.TypeMeta + if in.Profiles != nil { + in, out := &in.Profiles, &out.Profiles + *out = make([]Profile, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.NodeSelector != nil { + in, out := &in.NodeSelector, &out.NodeSelector + *out = new(string) + **out = **in + } + if in.MaxNoOfPodsToEvictPerNode != nil { + in, out := &in.MaxNoOfPodsToEvictPerNode, &out.MaxNoOfPodsToEvictPerNode + *out = new(uint) + **out = **in + } + if in.MaxNoOfPodsToEvictPerNamespace != nil { + in, out := &in.MaxNoOfPodsToEvictPerNamespace, &out.MaxNoOfPodsToEvictPerNamespace + *out = new(uint) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DeschedulerPolicy. +func (in *DeschedulerPolicy) DeepCopy() *DeschedulerPolicy { + if in == nil { + return nil + } + out := new(DeschedulerPolicy) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *DeschedulerPolicy) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PluginConfig) DeepCopyInto(out *PluginConfig) { + *out = *in + in.Args.DeepCopyInto(&out.Args) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PluginConfig. +func (in *PluginConfig) DeepCopy() *PluginConfig { + if in == nil { + return nil + } + out := new(PluginConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PluginSet) DeepCopyInto(out *PluginSet) { + *out = *in + if in.Enabled != nil { + in, out := &in.Enabled, &out.Enabled + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.Disabled != nil { + in, out := &in.Disabled, &out.Disabled + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PluginSet. +func (in *PluginSet) DeepCopy() *PluginSet { + if in == nil { + return nil + } + out := new(PluginSet) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Plugins) DeepCopyInto(out *Plugins) { + *out = *in + in.PreSort.DeepCopyInto(&out.PreSort) + in.Sort.DeepCopyInto(&out.Sort) + in.Deschedule.DeepCopyInto(&out.Deschedule) + in.Balance.DeepCopyInto(&out.Balance) + in.Evict.DeepCopyInto(&out.Evict) + in.Filter.DeepCopyInto(&out.Filter) + in.PreEvictionFilter.DeepCopyInto(&out.PreEvictionFilter) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Plugins. +func (in *Plugins) DeepCopy() *Plugins { + if in == nil { + return nil + } + out := new(Plugins) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Profile) DeepCopyInto(out *Profile) { + *out = *in + if in.PluginConfigs != nil { + in, out := &in.PluginConfigs, &out.PluginConfigs + *out = make([]PluginConfig, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + in.Plugins.DeepCopyInto(&out.Plugins) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Profile. +func (in *Profile) DeepCopy() *Profile { + if in == nil { + return nil + } + out := new(Profile) + in.DeepCopyInto(out) + return out +} diff --git a/pkg/api/v1alpha2/zz_generated.defaults.go b/pkg/api/v1alpha2/zz_generated.defaults.go new file mode 100644 index 0000000000..eb8c39049c --- /dev/null +++ b/pkg/api/v1alpha2/zz_generated.defaults.go @@ -0,0 +1,33 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +/* +Copyright 2023 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. +*/ + +// Code generated by defaulter-gen. DO NOT EDIT. + +package v1alpha2 + +import ( + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// RegisterDefaults adds defaulters functions to the given scheme. +// Public to allow building arbitrary schemes. +// All generated defaulters are covering - they call all nested defaulters. +func RegisterDefaults(scheme *runtime.Scheme) error { + return nil +} diff --git a/pkg/api/zz_generated.deepcopy.go b/pkg/api/zz_generated.deepcopy.go index 71346b0343..0858e240fa 100644 --- a/pkg/api/zz_generated.deepcopy.go +++ b/pkg/api/zz_generated.deepcopy.go @@ -2,7 +2,7 @@ // +build !ignore_autogenerated /* -Copyright 2022 The Kubernetes Authors. +Copyright 2023 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. diff --git a/pkg/apis/componentconfig/v1alpha1/zz_generated.conversion.go b/pkg/apis/componentconfig/v1alpha1/zz_generated.conversion.go index f93cc8e4f9..7bed6a6bb2 100644 --- a/pkg/apis/componentconfig/v1alpha1/zz_generated.conversion.go +++ b/pkg/apis/componentconfig/v1alpha1/zz_generated.conversion.go @@ -2,7 +2,7 @@ // +build !ignore_autogenerated /* -Copyright 2022 The Kubernetes Authors. +Copyright 2023 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. diff --git a/pkg/apis/componentconfig/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/componentconfig/v1alpha1/zz_generated.deepcopy.go index 89296808bd..138674d939 100644 --- a/pkg/apis/componentconfig/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/componentconfig/v1alpha1/zz_generated.deepcopy.go @@ -2,7 +2,7 @@ // +build !ignore_autogenerated /* -Copyright 2022 The Kubernetes Authors. +Copyright 2023 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. diff --git a/pkg/apis/componentconfig/v1alpha1/zz_generated.defaults.go b/pkg/apis/componentconfig/v1alpha1/zz_generated.defaults.go index c450647048..94e098c8da 100644 --- a/pkg/apis/componentconfig/v1alpha1/zz_generated.defaults.go +++ b/pkg/apis/componentconfig/v1alpha1/zz_generated.defaults.go @@ -2,7 +2,7 @@ // +build !ignore_autogenerated /* -Copyright 2022 The Kubernetes Authors. +Copyright 2023 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. diff --git a/pkg/apis/componentconfig/zz_generated.deepcopy.go b/pkg/apis/componentconfig/zz_generated.deepcopy.go index f450e704ca..c0bbd2ccbd 100644 --- a/pkg/apis/componentconfig/zz_generated.deepcopy.go +++ b/pkg/apis/componentconfig/zz_generated.deepcopy.go @@ -2,7 +2,7 @@ // +build !ignore_autogenerated /* -Copyright 2022 The Kubernetes Authors. +Copyright 2023 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. diff --git a/pkg/descheduler/descheduler.go b/pkg/descheduler/descheduler.go index 8611e5491f..c83ba1f302 100644 --- a/pkg/descheduler/descheduler.go +++ b/pkg/descheduler/descheduler.go @@ -44,8 +44,8 @@ import ( nodeutil "sigs.k8s.io/descheduler/pkg/descheduler/node" podutil "sigs.k8s.io/descheduler/pkg/descheduler/pod" "sigs.k8s.io/descheduler/pkg/framework" + "sigs.k8s.io/descheduler/pkg/framework/pluginregistry" "sigs.k8s.io/descheduler/pkg/framework/plugins/defaultevictor" - "sigs.k8s.io/descheduler/pkg/framework/plugins/pluginbuilder" "sigs.k8s.io/descheduler/pkg/utils" ) @@ -59,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, pluginbuilder.PluginRegistry) + deschedulerPolicy, err := LoadPolicyConfig(rs.PolicyConfigFile, rs.Client, pluginregistry.PluginRegistry) if err != nil { return err } @@ -358,7 +358,7 @@ func RunDeschedulerStrategies(ctx context.Context, rs *options.DeschedulerServer klog.ErrorS(fmt.Errorf("unable to get plugin config"), "skipping plugin", "plugin", plugin) continue } - registryPlugin, ok := pluginbuilder.PluginRegistry[plugin] + registryPlugin, ok := pluginregistry.PluginRegistry[plugin] pgFnc := registryPlugin.PluginBuilder if !ok { klog.ErrorS(fmt.Errorf("unable to find plugin in the pluginsMap"), "skipping plugin", "plugin", plugin) @@ -368,14 +368,8 @@ func RunDeschedulerStrategies(ctx context.Context, rs *options.DeschedulerServer klog.ErrorS(err, "unable to initialize a plugin", "pluginName", plugin) } if pg != nil { - switch v := pg.(type) { - case framework.DeschedulePlugin: - enabledDeschedulePlugins = append(enabledDeschedulePlugins, v) - case framework.BalancePlugin: - enabledBalancePlugins = append(enabledBalancePlugins, v) - default: - klog.ErrorS(fmt.Errorf("unknown plugin extension point"), "skipping plugin", "plugin", plugin) - } + // pg can be of any of each type, or both + enabledDeschedulePlugins, enabledBalancePlugins = includeProfilePluginsByType(enabledDeschedulePlugins, enabledBalancePlugins, pg) } } } @@ -416,6 +410,28 @@ func RunDeschedulerStrategies(ctx context.Context, rs *options.DeschedulerServer return nil } +func includeProfilePluginsByType(enabledDeschedulePlugins []framework.DeschedulePlugin, enabledBalancePlugins []framework.BalancePlugin, pg framework.Plugin) ([]framework.DeschedulePlugin, []framework.BalancePlugin) { + enabledDeschedulePlugins = includeDeschedule(enabledDeschedulePlugins, pg) + enabledBalancePlugins = includeBalance(enabledBalancePlugins, pg) + return enabledDeschedulePlugins, enabledBalancePlugins +} + +func includeDeschedule(enabledDeschedulePlugins []framework.DeschedulePlugin, pg framework.Plugin) []framework.DeschedulePlugin { + _, ok := pg.(framework.DeschedulePlugin) + if ok { + enabledDeschedulePlugins = append(enabledDeschedulePlugins, pg.(framework.DeschedulePlugin)) + } + return enabledDeschedulePlugins +} + +func includeBalance(enabledBalancePlugins []framework.BalancePlugin, pg framework.Plugin) []framework.BalancePlugin { + _, ok := pg.(framework.BalancePlugin) + if ok { + enabledBalancePlugins = append(enabledBalancePlugins, pg.(framework.BalancePlugin)) + } + return enabledBalancePlugins +} + func getPluginConfig(pluginName string, pluginConfigs []api.PluginConfig) *api.PluginConfig { for _, pluginConfig := range pluginConfigs { if pluginConfig.Name == pluginName { diff --git a/pkg/descheduler/descheduler_test.go b/pkg/descheduler/descheduler_test.go index c00512f7be..fa74823082 100644 --- a/pkg/descheduler/descheduler_test.go +++ b/pkg/descheduler/descheduler_test.go @@ -15,15 +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/pluginregistry" "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) + pluginregistry.PluginRegistry = pluginregistry.NewRegistry() + pluginregistry.Register(removepodsviolatingnodetaints.PluginName, removepodsviolatingnodetaints.New, &removepodsviolatingnodetaints.RemovePodsViolatingNodeTaintsArgs{}, removepodsviolatingnodetaints.ValidateRemovePodsViolatingNodeTaintsArgs, removepodsviolatingnodetaints.SetDefaults_RemovePodsViolatingNodeTaintsArgs, pluginregistry.PluginRegistry) ctx := context.Background() n1 := test.BuildTestNode("n1", 2000, 3000, 10, nil) n2 := test.BuildTestNode("n2", 2000, 3000, 10, nil) @@ -74,7 +74,7 @@ func TestTaintsUpdated(t *testing.T) { var evictedPods []string client.PrependReactor("create", "pods", podEvictionReactionFuc(&evictedPods)) - internalDeschedulerPolicy, err := V1alpha1ToInternal(client, dp, pluginbuilder.PluginRegistry) + internalDeschedulerPolicy, err := v1alpha1.V1alpha1ToInternal(client, dp, pluginregistry.PluginRegistry) if err != nil { t.Fatalf("Unable to convert v1alpha1 to v1alpha2: %v", err) } @@ -89,8 +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) + pluginregistry.PluginRegistry = pluginregistry.NewRegistry() + pluginregistry.Register(removeduplicates.PluginName, removeduplicates.New, &removeduplicates.RemoveDuplicatesArgs{}, removeduplicates.ValidateRemoveDuplicatesArgs, removeduplicates.SetDefaults_RemoveDuplicatesArgs, pluginregistry.PluginRegistry) ctx := context.Background() node1 := test.BuildTestNode("n1", 2000, 3000, 10, nil) node2 := test.BuildTestNode("n2", 2000, 3000, 10, nil) @@ -136,7 +136,7 @@ func TestDuplicate(t *testing.T) { var evictedPods []string client.PrependReactor("create", "pods", podEvictionReactionFuc(&evictedPods)) - internalDeschedulerPolicy, err := V1alpha1ToInternal(client, dp, pluginbuilder.PluginRegistry) + internalDeschedulerPolicy, err := v1alpha1.V1alpha1ToInternal(client, dp, pluginregistry.PluginRegistry) if err != nil { t.Fatalf("Unable to convert v1alpha1 to v1alpha2: %v", err) } diff --git a/pkg/descheduler/policyconfig.go b/pkg/descheduler/policyconfig.go index 0801402297..a35909609d 100644 --- a/pkg/descheduler/policyconfig.go +++ b/pkg/descheduler/policyconfig.go @@ -17,7 +17,6 @@ limitations under the License. package descheduler import ( - "context" "fmt" "io/ioutil" @@ -27,14 +26,13 @@ import ( "sigs.k8s.io/descheduler/pkg/api" "sigs.k8s.io/descheduler/pkg/api/v1alpha1" + "sigs.k8s.io/descheduler/pkg/api/v1alpha2" "sigs.k8s.io/descheduler/pkg/descheduler/scheme" - "sigs.k8s.io/descheduler/pkg/framework" + "sigs.k8s.io/descheduler/pkg/framework/pluginregistry" "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, registry pluginbuilder.Registry) (*api.DeschedulerPolicy, error) { +func LoadPolicyConfig(policyConfigFile string, client clientset.Interface, registry pluginregistry.Registry) (*api.DeschedulerPolicy, error) { if policyConfigFile == "" { klog.V(1).InfoS("Policy config file not specified") return nil, nil @@ -45,171 +43,128 @@ func LoadPolicyConfig(policyConfigFile string, client clientset.Interface, regis return nil, fmt.Errorf("failed to read policy config file %q: %+v", policyConfigFile, err) } + return decode(policyConfigFile, policy, client, registry) +} + +func decode(policyConfigFile string, policy []byte, client clientset.Interface, registry pluginregistry.Registry) (*api.DeschedulerPolicy, error) { versionedPolicy := &v1alpha1.DeschedulerPolicy{} + internalPolicy := &api.DeschedulerPolicy{} + var err error - decoder := scheme.Codecs.UniversalDecoder(v1alpha1.SchemeGroupVersion) + decoder := scheme.Codecs.UniversalDecoder(v1alpha1.SchemeGroupVersion, v1alpha2.SchemeGroupVersion, api.SchemeGroupVersion) if err := runtime.DecodeInto(decoder, policy, versionedPolicy); err != nil { - return nil, fmt.Errorf("failed decoding descheduler's policy config %q: %v", policyConfigFile, err) + // TODO: Right now we are checking this error string because we couldn't make a native + // Convert_v1alpha1_DeschedulerPolicy_To_api_DeschedulerPolicy in conversion.go + // and we are just calling V1alpha1ToInternal directly (since it needs a client as an argument). + // We need to make V1alpha1ToInternal stop needing a client, use a native conversion function + // and just rely in a DecodeInto that would pick up any policy file directly into our internal api. + // An attempt of doing that is in b25a44c51c0fa31a7831b899e73d83abd12a789a. Relevant discussions in following comments: + // https://github.com/kubernetes-sigs/descheduler/pull/1006#discussion_r1062630128 + if err.Error() == "converting (v1alpha2.DeschedulerPolicy) to (v1alpha1.DeschedulerPolicy): unknown conversion" { + klog.V(1).InfoS("Tried reading v1alpha2.DeschedulerPolicy and failed. Trying legacy conversion now.") + } else { + return nil, fmt.Errorf("failed decoding descheduler's policy config %q: %v", policyConfigFile, err) + } + } + if versionedPolicy.APIVersion == "descheduler/v1alpha1" { + // Build profiles + internalPolicy, err = v1alpha1.V1alpha1ToInternal(client, versionedPolicy, registry) + if err != nil { + return nil, fmt.Errorf("failed converting versioned policy to internal policy version: %v", err) + } + } else { + if err := runtime.DecodeInto(decoder, policy, internalPolicy); err != nil { + return nil, fmt.Errorf("failed decoding descheduler's policy config %q: %v", policyConfigFile, err) + } } - // Build profiles - internalPolicy, err := V1alpha1ToInternal(client, versionedPolicy, registry) + err = validateDeschedulerConfiguration(*internalPolicy, registry) if err != nil { - return nil, fmt.Errorf("failed converting versioned policy to internal policy version: %v", err) + return nil, err } + setDefaults(*internalPolicy, registry) + return internalPolicy, nil } -func V1alpha1ToInternal( - client clientset.Interface, - deschedulerPolicy *v1alpha1.DeschedulerPolicy, - registry pluginbuilder.Registry, -) (*api.DeschedulerPolicy, error) { - var evictLocalStoragePods bool - if deschedulerPolicy.EvictLocalStoragePods != nil { - evictLocalStoragePods = *deschedulerPolicy.EvictLocalStoragePods - } - - evictBarePods := false - if deschedulerPolicy.EvictFailedBarePods != nil { - evictBarePods = *deschedulerPolicy.EvictFailedBarePods - if evictBarePods { - klog.V(1).InfoS("Warning: EvictFailedBarePods is set to True. This could cause eviction of pods without ownerReferences.") +func setDefaults(in api.DeschedulerPolicy, registry pluginregistry.Registry) *api.DeschedulerPolicy { + for idx, profile := range in.Profiles { + // If we need to set defaults coming from loadtime in each profile we do it here + in.Profiles[idx] = setDefaultEvictor(profile) + for _, pluginConfig := range profile.PluginConfigs { + setDefaultsPluginConfig(&pluginConfig, registry) } } + return &in +} - evictSystemCriticalPods := false - if deschedulerPolicy.EvictSystemCriticalPods != nil { - evictSystemCriticalPods = *deschedulerPolicy.EvictSystemCriticalPods - if evictSystemCriticalPods { - klog.V(1).InfoS("Warning: EvictSystemCriticalPods is set to True. This could cause eviction of Kubernetes system pods.") +func setDefaultsPluginConfig(pluginConfig *api.PluginConfig, registry pluginregistry.Registry) { + if _, ok := registry[pluginConfig.Name]; ok { + pluginUtilities := registry[pluginConfig.Name] + if pluginUtilities.PluginArgDefaulter != nil { + pluginUtilities.PluginArgDefaulter(pluginConfig.Args) } } +} - ignorePvcPods := false - if deschedulerPolicy.IgnorePVCPods != nil { - ignorePvcPods = *deschedulerPolicy.IgnorePVCPods +func setDefaultEvictor(profile api.Profile) api.Profile { + newPluginConfig := api.PluginConfig{ + Name: defaultevictor.PluginName, + Args: &defaultevictor.DefaultEvictorArgs{ + EvictLocalStoragePods: false, + EvictSystemCriticalPods: false, + IgnorePvcPods: false, + EvictFailedBarePods: false, + }, } + if len(profile.Plugins.Evict.Enabled) == 0 && !hasPluginConfigsWithSameName(newPluginConfig, profile.PluginConfigs) { + profile.Plugins.Evict.Enabled = append(profile.Plugins.Evict.Enabled, defaultevictor.PluginName) + profile.PluginConfigs = append(profile.PluginConfigs, newPluginConfig) + } + return profile +} - var profiles []api.Profile - - // Build profiles - for name, strategy := range deschedulerPolicy.Strategies { - if _, ok := pluginbuilder.PluginRegistry[string(name)]; ok { - if strategy.Enabled { - params := strategy.Params - if params == nil { - params = &v1alpha1.StrategyParameters{} - } - - nodeFit := false - if name != "PodLifeTime" { - nodeFit = params.NodeFit - } - - // TODO(jchaloup): once all strategies are migrated move this check under - // the default evictor args validation - if params.ThresholdPriority != nil && params.ThresholdPriorityClassName != "" { - klog.ErrorS(fmt.Errorf("priority threshold misconfigured"), "only one of priorityThreshold fields can be set", "pluginName", name) - return nil, fmt.Errorf("priority threshold misconfigured for plugin %v", name) - } - var priorityThreshold *api.PriorityThreshold - if strategy.Params != nil { - priorityThreshold = &api.PriorityThreshold{ - Value: strategy.Params.ThresholdPriority, - Name: strategy.Params.ThresholdPriorityClassName, - } - } - thresholdPriority, err := utils.GetPriorityFromStrategyParams(context.TODO(), client, priorityThreshold) - if err != nil { - klog.ErrorS(err, "Failed to get threshold priority from strategy's params") - return nil, fmt.Errorf("failed to get threshold priority from strategy's params: %v", err) - } - - var pluginConfig *api.PluginConfig - if pcFnc, exists := strategyParamsToPluginArgs[string(name)]; exists { - pluginConfig, err = pcFnc(params) - if err != nil { - klog.ErrorS(err, "skipping strategy", "strategy", name) - return nil, fmt.Errorf("failed to get plugin config for strategy %v: %v", name, err) - } - } else { - klog.ErrorS(fmt.Errorf("unknown strategy name"), "skipping strategy", "strategy", name) - return nil, fmt.Errorf("unknown strategy name: %v", name) - } - - profile := api.Profile{ - Name: fmt.Sprintf("strategy-%v-profile", name), - PluginConfigs: []api.PluginConfig{ - { - Name: defaultevictor.PluginName, - Args: &defaultevictor.DefaultEvictorArgs{ - EvictLocalStoragePods: evictLocalStoragePods, - EvictSystemCriticalPods: evictSystemCriticalPods, - IgnorePvcPods: ignorePvcPods, - EvictFailedBarePods: evictBarePods, - NodeFit: nodeFit, - PriorityThreshold: &api.PriorityThreshold{ - Value: &thresholdPriority, - }, - }, - }, - *pluginConfig, - }, - Plugins: api.Plugins{ - Evict: api.PluginSet{ - Enabled: []string{defaultevictor.PluginName}, - }, - }, - } - - 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) +func validateDeschedulerConfiguration(in api.DeschedulerPolicy, registry pluginregistry.Registry) error { + var errorsInProfiles error + for _, profile := range in.Profiles { + // api.DeschedulerPolicy needs only 1 evictor plugin enabled + if len(profile.Plugins.Evict.Enabled) != 1 { + errTooManyEvictors := fmt.Errorf("profile with invalid number of evictor plugins enabled found. Please enable a single evictor plugin.") + errorsInProfiles = setErrorsInProfiles(errTooManyEvictors, profile.Name, errorsInProfiles) + } + for _, pluginConfig := range profile.PluginConfigs { + if _, ok := registry[pluginConfig.Name]; ok { + pluginUtilities := registry[pluginConfig.Name] + if pluginUtilities.PluginArgValidator != nil { + err := pluginUtilities.PluginArgValidator(pluginConfig.Args) + errorsInProfiles = setErrorsInProfiles(err, profile.Name, errorsInProfiles) } - - // pluginInstance can be of any of each type, or both - profilePlugins := profile.Plugins - profile.Plugins = enableProfilePluginsByType(profilePlugins, pluginInstance, pluginConfig) - profiles = append(profiles, profile) } - } else { - klog.ErrorS(fmt.Errorf("unknown strategy name"), "skipping strategy", "strategy", name) - return nil, fmt.Errorf("unknown strategy name: %v", name) } } - - return &api.DeschedulerPolicy{ - Profiles: profiles, - NodeSelector: deschedulerPolicy.NodeSelector, - MaxNoOfPodsToEvictPerNode: deschedulerPolicy.MaxNoOfPodsToEvictPerNode, - 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 + if errorsInProfiles != nil { + return errorsInProfiles + } + return nil } -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} +func setErrorsInProfiles(err error, profileName string, errorsInProfiles error) error { + if err != nil { + if errorsInProfiles == nil { + errorsInProfiles = fmt.Errorf("in profile %s: %s", profileName, err.Error()) + } else { + errorsInProfiles = fmt.Errorf("%w: %s", errorsInProfiles, fmt.Sprintf("in profile %s: %s", profileName, err.Error())) + } } - return profilePlugins + return errorsInProfiles } -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} +func hasPluginConfigsWithSameName(newPluginConfig api.PluginConfig, pluginConfigs []api.PluginConfig) bool { + for _, pluginConfig := range pluginConfigs { + if newPluginConfig.Name == pluginConfig.Name { + return true + } } - return profilePlugins + return false } diff --git a/pkg/descheduler/policyconfig_test.go b/pkg/descheduler/policyconfig_test.go index 26922fc05b..719541b317 100644 --- a/pkg/descheduler/policyconfig_test.go +++ b/pkg/descheduler/policyconfig_test.go @@ -25,9 +25,10 @@ import ( utilpointer "k8s.io/utils/pointer" "sigs.k8s.io/descheduler/pkg/api" "sigs.k8s.io/descheduler/pkg/api/v1alpha1" + "sigs.k8s.io/descheduler/pkg/framework/pluginregistry" "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" @@ -682,7 +683,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, pluginbuilder.PluginRegistry) + result, err := v1alpha1.V1alpha1ToInternal(client, tc.policy, pluginregistry.PluginRegistry) if err != nil { if err.Error() != tc.err.Error() { t.Errorf("unexpected error: %s", err.Error()) @@ -699,3 +700,302 @@ func TestV1alpha1ToV1alpha2(t *testing.T) { }) } } + +func TestDecodeVersionedPolicy(t *testing.T) { + client := fakeclientset.NewSimpleClientset() + SetupPlugins() + defaultEvictorPluginConfig := api.PluginConfig{ + Name: defaultevictor.PluginName, + Args: &defaultevictor.DefaultEvictorArgs{ + PriorityThreshold: &api.PriorityThreshold{ + Value: utilpointer.Int32(utils.SystemCriticalPriority), + }, + }, + } + defaultEvictorPluginSet := api.PluginSet{ + Enabled: []string{defaultevictor.PluginName}, + } + type testCase struct { + description string + policy []byte + err error + result *api.DeschedulerPolicy + } + testCases := []testCase{ + { + description: "v1alpha1 to internal", + policy: []byte(`apiVersion: "descheduler/v1alpha1" +kind: "DeschedulerPolicy" +strategies: + "PodLifeTime": + enabled: true + params: + podLifeTime: + maxPodLifeTimeSeconds: 5 + namespaces: + include: + - "testleaderelection-a" +`), + result: &api.DeschedulerPolicy{ + Profiles: []api.Profile{ + { + Name: fmt.Sprintf("strategy-%s-profile", podlifetime.PluginName), + PluginConfigs: []api.PluginConfig{ + defaultEvictorPluginConfig, + { + Name: podlifetime.PluginName, + Args: &podlifetime.PodLifeTimeArgs{ + Namespaces: &api.Namespaces{ + Include: []string{"testleaderelection-a"}, + }, + MaxPodLifeTimeSeconds: utilpointer.Uint(5), + }, + }, + }, + Plugins: api.Plugins{ + Evict: defaultEvictorPluginSet, + Deschedule: api.PluginSet{ + Enabled: []string{podlifetime.PluginName}, + }, + }, + }, + }, + }, + }, + { + description: "v1aplha2 to internal", + policy: []byte(`apiVersion: "descheduler/v1alpha2" +kind: "DeschedulerPolicy" +profiles: + - name: ProfileName + pluginConfig: + - name: "DefaultEvictor" + args: + evictSystemCriticalPods: true + evictFailedBarePods: true + evictLocalStoragePods: true + nodeFit: true + - name: "RemovePodsHavingTooManyRestarts" + args: + podRestartThreshold: 100 + includingInitContainers: true + plugins: + filter: + enabled: + - "DefaultEvictor" + evict: + enabled: + - "DefaultEvictor" + deschedule: + enabled: + - "RemovePodsHavingTooManyRestarts" +`), + result: &api.DeschedulerPolicy{ + Profiles: []api.Profile{ + { + Name: "ProfileName", + PluginConfigs: []api.PluginConfig{ + { + Name: defaultevictor.PluginName, + Args: &defaultevictor.DefaultEvictorArgs{ + EvictSystemCriticalPods: true, + EvictFailedBarePods: true, + EvictLocalStoragePods: true, + NodeFit: true, + }, + }, + { + Name: removepodshavingtoomanyrestarts.PluginName, + Args: &removepodshavingtoomanyrestarts.RemovePodsHavingTooManyRestartsArgs{ + PodRestartThreshold: 100, + IncludingInitContainers: true, + }, + }, + }, + Plugins: api.Plugins{ + Evict: api.PluginSet{ + Enabled: []string{defaultevictor.PluginName}, + }, + Filter: api.PluginSet{ + Enabled: []string{defaultevictor.PluginName}, + }, + Deschedule: api.PluginSet{ + Enabled: []string{removepodshavingtoomanyrestarts.PluginName}, + }, + }, + }, + }, + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.description, func(t *testing.T) { + result, err := decode("filename", tc.policy, client, pluginregistry.PluginRegistry) + if err != nil { + if tc.err == nil { + t.Errorf("unexpected error: %s.", err.Error()) + } else { + t.Errorf("unexpected error: %s. Was expecting %s", err.Error(), tc.err.Error()) + } + } + diff := cmp.Diff(tc.result, result) + if diff != "" && err == nil { + t.Errorf("test '%s' failed. Results are not deep equal. mismatch (-want +got):\n%s", tc.description, diff) + } + }) + } +} + +func TestValidateDeschedulerConfiguration(t *testing.T) { + SetupPlugins() + type testCase struct { + description string + deschedulerPolicy api.DeschedulerPolicy + result error + } + testCases := []testCase{ + { + description: "multiple errors", + deschedulerPolicy: api.DeschedulerPolicy{ + Profiles: []api.Profile{ + { + Name: removefailedpods.PluginName, + Plugins: api.Plugins{ + Deschedule: api.PluginSet{Enabled: []string{removefailedpods.PluginName}}, + }, + PluginConfigs: []api.PluginConfig{ + { + Name: removefailedpods.PluginName, + Args: &removefailedpods.RemoveFailedPodsArgs{ + Namespaces: &api.Namespaces{ + Include: []string{"test1"}, + Exclude: []string{"test1"}, + }, + }, + }, + }, + }, + { + Name: removepodsviolatingtopologyspreadconstraint.PluginName, + Plugins: api.Plugins{ + Deschedule: api.PluginSet{Enabled: []string{removepodsviolatingtopologyspreadconstraint.PluginName}}, + }, + PluginConfigs: []api.PluginConfig{ + { + Name: removepodsviolatingtopologyspreadconstraint.PluginName, + Args: &removepodsviolatingtopologyspreadconstraint.RemovePodsViolatingTopologySpreadConstraintArgs{ + Namespaces: &api.Namespaces{ + Include: []string{"test1"}, + Exclude: []string{"test1"}, + }, + }, + }, + }, + }, + }, + }, + result: fmt.Errorf("in profile RemoveFailedPods: profile with invalid number of evictor plugins enabled found. Please enable a single evictor plugin.: in profile RemoveFailedPods: only one of Include/Exclude namespaces can be set: in profile RemovePodsViolatingTopologySpreadConstraint: profile with invalid number of evictor plugins enabled found. Please enable a single evictor plugin.: in profile RemovePodsViolatingTopologySpreadConstraint: only one of Include/Exclude namespaces can be set"), + }, + } + + for _, tc := range testCases { + t.Run(tc.description, func(t *testing.T) { + result := validateDeschedulerConfiguration(tc.deschedulerPolicy, pluginregistry.PluginRegistry) + if result.Error() != tc.result.Error() { + t.Errorf("test '%s' failed. expected \n'%s', got \n'%s'", tc.description, tc.result, result) + } + }) + } +} + +func TestDecodeDefaults(t *testing.T) { + client := fakeclientset.NewSimpleClientset() + SetupPlugins() + type testCase struct { + description string + policy []byte + err error + result *api.DeschedulerPolicy + } + testCases := []testCase{ + { + description: "use empty RemoveFailedPods, check MinPodLifetimeSeconds default", + policy: []byte(`apiVersion: "descheduler/v1alpha2" +kind: "DeschedulerPolicy" +profiles: + - name: ProfileName + pluginConfig: + - name: "DefaultEvictor" + args: + evictSystemCriticalPods: true + evictFailedBarePods: true + evictLocalStoragePods: true + nodeFit: true + - name: "RemoveFailedPods" + plugins: + filter: + enabled: + - "DefaultEvictor" + evict: + enabled: + - "DefaultEvictor" + deschedule: + enabled: + - "RemovePodsHavingTooManyRestarts" +`), + result: &api.DeschedulerPolicy{ + Profiles: []api.Profile{ + { + Name: "ProfileName", + PluginConfigs: []api.PluginConfig{ + { + Name: defaultevictor.PluginName, + Args: &defaultevictor.DefaultEvictorArgs{ + EvictSystemCriticalPods: true, + EvictFailedBarePods: true, + EvictLocalStoragePods: true, + NodeFit: true, + }, + }, + { + Name: removefailedpods.PluginName, + Args: &removefailedpods.RemoveFailedPodsArgs{ + MinPodLifetimeSeconds: utilpointer.Uint(3600), + }, + }, + }, + Plugins: api.Plugins{ + Evict: api.PluginSet{ + Enabled: []string{defaultevictor.PluginName}, + }, + Filter: api.PluginSet{ + Enabled: []string{defaultevictor.PluginName}, + }, + Deschedule: api.PluginSet{ + Enabled: []string{removepodshavingtoomanyrestarts.PluginName}, + }, + }, + }, + }, + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.description, func(t *testing.T) { + result, err := decode("filename", tc.policy, client, pluginregistry.PluginRegistry) + if err != nil { + if tc.err == nil { + t.Errorf("unexpected error: %s.", err.Error()) + } else { + t.Errorf("unexpected error: %s. Was expecting %s", err.Error(), tc.err.Error()) + } + } + diff := cmp.Diff(tc.result, result) + if diff != "" && err == nil { + t.Errorf("test '%s' failed. Results are not deep equal. mismatch (-want +got):\n%s", tc.description, diff) + } + }) + } +} diff --git a/pkg/descheduler/scheme/scheme.go b/pkg/descheduler/scheme/scheme.go index 2949193c1e..1e657abf41 100644 --- a/pkg/descheduler/scheme/scheme.go +++ b/pkg/descheduler/scheme/scheme.go @@ -22,8 +22,19 @@ import ( utilruntime "k8s.io/apimachinery/pkg/util/runtime" "sigs.k8s.io/descheduler/pkg/api" "sigs.k8s.io/descheduler/pkg/api/v1alpha1" + "sigs.k8s.io/descheduler/pkg/api/v1alpha2" "sigs.k8s.io/descheduler/pkg/apis/componentconfig" componentconfigv1alpha1 "sigs.k8s.io/descheduler/pkg/apis/componentconfig/v1alpha1" + "sigs.k8s.io/descheduler/pkg/framework/plugins/defaultevictor" + "sigs.k8s.io/descheduler/pkg/framework/plugins/nodeutilization" + "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" ) var ( @@ -33,8 +44,23 @@ var ( func init() { utilruntime.Must(api.AddToScheme(Scheme)) - utilruntime.Must(v1alpha1.AddToScheme(Scheme)) + utilruntime.Must(defaultevictor.AddToScheme(Scheme)) + utilruntime.Must(nodeutilization.AddToScheme(Scheme)) + utilruntime.Must(podlifetime.AddToScheme(Scheme)) + utilruntime.Must(removeduplicates.AddToScheme(Scheme)) + utilruntime.Must(removefailedpods.AddToScheme(Scheme)) + utilruntime.Must(removepodshavingtoomanyrestarts.AddToScheme(Scheme)) + utilruntime.Must(removepodsviolatinginterpodantiaffinity.AddToScheme(Scheme)) + utilruntime.Must(removepodsviolatingnodeaffinity.AddToScheme(Scheme)) + utilruntime.Must(removepodsviolatingnodetaints.AddToScheme(Scheme)) + utilruntime.Must(removepodsviolatingtopologyspreadconstraint.AddToScheme(Scheme)) utilruntime.Must(componentconfig.AddToScheme(Scheme)) utilruntime.Must(componentconfigv1alpha1.AddToScheme(Scheme)) + utilruntime.Must(v1alpha1.AddToScheme(Scheme)) + utilruntime.Must(v1alpha2.AddToScheme(Scheme)) + utilruntime.Must(Scheme.SetVersionPriority( + v1alpha2.SchemeGroupVersion, + v1alpha1.SchemeGroupVersion, + )) } diff --git a/pkg/descheduler/setupplugins.go b/pkg/descheduler/setupplugins.go index 35cf01b121..9b2b5ce511 100644 --- a/pkg/descheduler/setupplugins.go +++ b/pkg/descheduler/setupplugins.go @@ -17,9 +17,9 @@ limitations under the License. package descheduler import ( + "sigs.k8s.io/descheduler/pkg/framework/pluginregistry" "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" @@ -31,20 +31,20 @@ import ( ) func SetupPlugins() { - pluginbuilder.PluginRegistry = pluginbuilder.NewRegistry() - RegisterDefaultPlugins(pluginbuilder.PluginRegistry) + pluginregistry.PluginRegistry = pluginregistry.NewRegistry() + RegisterDefaultPlugins(pluginregistry.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) +func RegisterDefaultPlugins(registry pluginregistry.Registry) { + pluginregistry.Register(defaultevictor.PluginName, defaultevictor.New, &defaultevictor.DefaultEvictorArgs{}, defaultevictor.ValidateDefaultEvictorArgs, defaultevictor.SetDefaults_DefaultEvictorArgs, registry) + pluginregistry.Register(nodeutilization.LowNodeUtilizationPluginName, nodeutilization.NewLowNodeUtilization, &nodeutilization.LowNodeUtilizationArgs{}, nodeutilization.ValidateLowNodeUtilizationArgs, nodeutilization.SetDefaults_LowNodeUtilizationArgs, registry) + pluginregistry.Register(nodeutilization.HighNodeUtilizationPluginName, nodeutilization.NewHighNodeUtilization, &nodeutilization.HighNodeUtilizationArgs{}, nodeutilization.ValidateHighNodeUtilizationArgs, nodeutilization.SetDefaults_HighNodeUtilizationArgs, registry) + pluginregistry.Register(podlifetime.PluginName, podlifetime.New, &podlifetime.PodLifeTimeArgs{}, podlifetime.ValidatePodLifeTimeArgs, podlifetime.SetDefaults_PodLifeTimeArgs, registry) + pluginregistry.Register(removeduplicates.PluginName, removeduplicates.New, &removeduplicates.RemoveDuplicatesArgs{}, removeduplicates.ValidateRemoveDuplicatesArgs, removeduplicates.SetDefaults_RemoveDuplicatesArgs, registry) + pluginregistry.Register(removefailedpods.PluginName, removefailedpods.New, &removefailedpods.RemoveFailedPodsArgs{}, removefailedpods.ValidateRemoveFailedPodsArgs, removefailedpods.SetDefaults_RemoveFailedPodsArgs, registry) + pluginregistry.Register(removepodshavingtoomanyrestarts.PluginName, removepodshavingtoomanyrestarts.New, &removepodshavingtoomanyrestarts.RemovePodsHavingTooManyRestartsArgs{}, removepodshavingtoomanyrestarts.ValidateRemovePodsHavingTooManyRestartsArgs, removepodshavingtoomanyrestarts.SetDefaults_RemovePodsHavingTooManyRestartsArgs, registry) + pluginregistry.Register(removepodsviolatinginterpodantiaffinity.PluginName, removepodsviolatinginterpodantiaffinity.New, &removepodsviolatinginterpodantiaffinity.RemovePodsViolatingInterPodAntiAffinityArgs{}, removepodsviolatinginterpodantiaffinity.ValidateRemovePodsViolatingInterPodAntiAffinityArgs, removepodsviolatinginterpodantiaffinity.SetDefaults_RemovePodsViolatingInterPodAntiAffinityArgs, registry) + pluginregistry.Register(removepodsviolatingnodeaffinity.PluginName, removepodsviolatingnodeaffinity.New, &removepodsviolatingnodeaffinity.RemovePodsViolatingNodeAffinityArgs{}, removepodsviolatingnodeaffinity.ValidateRemovePodsViolatingNodeAffinityArgs, removepodsviolatingnodeaffinity.SetDefaults_RemovePodsViolatingNodeAffinityArgs, registry) + pluginregistry.Register(removepodsviolatingnodetaints.PluginName, removepodsviolatingnodetaints.New, &removepodsviolatingnodetaints.RemovePodsViolatingNodeTaintsArgs{}, removepodsviolatingnodetaints.ValidateRemovePodsViolatingNodeTaintsArgs, removepodsviolatingnodetaints.SetDefaults_RemovePodsViolatingNodeTaintsArgs, registry) + pluginregistry.Register(removepodsviolatingtopologyspreadconstraint.PluginName, removepodsviolatingtopologyspreadconstraint.New, &removepodsviolatingtopologyspreadconstraint.RemovePodsViolatingTopologySpreadConstraintArgs{}, removepodsviolatingtopologyspreadconstraint.ValidateRemovePodsViolatingTopologySpreadConstraintArgs, removepodsviolatingtopologyspreadconstraint.SetDefaults_RemovePodsViolatingTopologySpreadConstraintArgs, registry) } diff --git a/pkg/framework/plugins/pluginbuilder/pluginbuilder.go b/pkg/framework/pluginregistry/pluginregistry.go similarity index 62% rename from pkg/framework/plugins/pluginbuilder/pluginbuilder.go rename to pkg/framework/pluginregistry/pluginregistry.go index d7971f462b..f5b2dd27a7 100644 --- a/pkg/framework/plugins/pluginbuilder/pluginbuilder.go +++ b/pkg/framework/pluginregistry/pluginregistry.go @@ -1,9 +1,12 @@ /* -Copyright 2022 The Kubernetes Authors. +Copyright 2023 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. @@ -11,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package pluginbuilder +package pluginregistry import ( "k8s.io/apimachinery/pkg/runtime" @@ -21,28 +24,37 @@ import ( var PluginRegistry Registry -type PluginBuilderAndArgsInstance struct { +type PluginUtilities struct { PluginBuilder PluginBuilder // Just an example instance of this PluginArg so we can avoid having // to deal with reflect Types - PluginArgInstance runtime.Object + PluginArgInstance runtime.Object + PluginArgValidator PluginArgValidator + PluginArgDefaulter PluginArgDefaulter } type PluginBuilder = func(args runtime.Object, handle framework.Handle) (framework.Plugin, error) -type Registry = map[string]PluginBuilderAndArgsInstance +type ( + PluginArgValidator = func(args runtime.Object) error + PluginArgDefaulter = func(args runtime.Object) +) + +type Registry = map[string]PluginUtilities func NewRegistry() Registry { return Registry{} } -func Register(name string, builderFunc PluginBuilder, exampleArg runtime.Object, registry Registry) { +func Register(name string, builderFunc PluginBuilder, exampleArg runtime.Object, pluginArgValidator PluginArgValidator, pluginArgDefaulter PluginArgDefaulter, registry Registry) { if _, ok := registry[name]; ok { klog.V(10).InfoS("Plugin already registered", "plugin", name) } else { - registry[name] = PluginBuilderAndArgsInstance{ - PluginBuilder: builderFunc, - PluginArgInstance: exampleArg, + registry[name] = PluginUtilities{ + PluginBuilder: builderFunc, + PluginArgInstance: exampleArg, + PluginArgValidator: pluginArgValidator, + PluginArgDefaulter: pluginArgDefaulter, } } } diff --git a/pkg/framework/plugins/defaultevictor/defaults.go b/pkg/framework/plugins/defaultevictor/defaults.go index f71731c459..57838f2c77 100644 --- a/pkg/framework/plugins/defaultevictor/defaults.go +++ b/pkg/framework/plugins/defaultevictor/defaults.go @@ -23,29 +23,30 @@ func addDefaultingFuncs(scheme *runtime.Scheme) error { // SetDefaults_DefaultEvictorArgs // TODO: the final default values would be discussed in community -func SetDefaults_DefaultEvictorArgs(obj *DefaultEvictorArgs) { - if obj.NodeSelector == "" { - obj.NodeSelector = "" +func SetDefaults_DefaultEvictorArgs(obj runtime.Object) { + args := obj.(*DefaultEvictorArgs) + if args.NodeSelector == "" { + args.NodeSelector = "" } - if !obj.EvictLocalStoragePods { - obj.EvictSystemCriticalPods = false + if !args.EvictLocalStoragePods { + args.EvictSystemCriticalPods = false } - if !obj.EvictSystemCriticalPods { - obj.EvictSystemCriticalPods = false + if !args.EvictSystemCriticalPods { + args.EvictSystemCriticalPods = false } - if !obj.IgnorePvcPods { - obj.IgnorePvcPods = false + if !args.IgnorePvcPods { + args.IgnorePvcPods = false } - if !obj.EvictFailedBarePods { - obj.EvictFailedBarePods = false + if !args.EvictFailedBarePods { + args.EvictFailedBarePods = false } - if obj.LabelSelector == nil { - obj.LabelSelector = nil + if args.LabelSelector == nil { + args.LabelSelector = nil } - if obj.PriorityThreshold == nil { - obj.PriorityThreshold = nil + if args.PriorityThreshold == nil { + args.PriorityThreshold = nil } - if !obj.NodeFit { - obj.NodeFit = false + if !args.NodeFit { + args.NodeFit = false } } diff --git a/pkg/framework/plugins/defaultevictor/validation.go b/pkg/framework/plugins/defaultevictor/validation.go new file mode 100644 index 0000000000..75ad6fecc7 --- /dev/null +++ b/pkg/framework/plugins/defaultevictor/validation.go @@ -0,0 +1,30 @@ +/* +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 defaultevictor + +import ( + "fmt" + + "k8s.io/apimachinery/pkg/runtime" +) + +func ValidateDefaultEvictorArgs(obj runtime.Object) error { + args := obj.(*DefaultEvictorArgs) + + if args.PriorityThreshold != nil && len(args.PriorityThreshold.Name) > 0 { + return fmt.Errorf("priority threshold misconfigured, only one of priorityThreshold fields can be set, got %v", args) + } + + return nil +} diff --git a/pkg/framework/plugins/defaultevictor/zz_generated.deepcopy.go b/pkg/framework/plugins/defaultevictor/zz_generated.deepcopy.go index ed30617fbe..024b89c2e9 100644 --- a/pkg/framework/plugins/defaultevictor/zz_generated.deepcopy.go +++ b/pkg/framework/plugins/defaultevictor/zz_generated.deepcopy.go @@ -2,7 +2,7 @@ // +build !ignore_autogenerated /* -Copyright 2022 The Kubernetes Authors. +Copyright 2023 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. diff --git a/pkg/framework/plugins/defaultevictor/zz_generated.defaults.go b/pkg/framework/plugins/defaultevictor/zz_generated.defaults.go index 6e662a5a97..f69750785a 100644 --- a/pkg/framework/plugins/defaultevictor/zz_generated.defaults.go +++ b/pkg/framework/plugins/defaultevictor/zz_generated.defaults.go @@ -2,7 +2,7 @@ // +build !ignore_autogenerated /* -Copyright 2022 The Kubernetes Authors. +Copyright 2023 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. @@ -29,10 +29,5 @@ import ( // Public to allow building arbitrary schemes. // All generated defaulters are covering - they call all nested defaulters. func RegisterDefaults(scheme *runtime.Scheme) error { - scheme.AddTypeDefaultingFunc(&DefaultEvictorArgs{}, func(obj interface{}) { SetObjectDefaults_DefaultEvictorArgs(obj.(*DefaultEvictorArgs)) }) return nil } - -func SetObjectDefaults_DefaultEvictorArgs(in *DefaultEvictorArgs) { - SetDefaults_DefaultEvictorArgs(in) -} diff --git a/pkg/framework/plugins/nodeutilization/defaults.go b/pkg/framework/plugins/nodeutilization/defaults.go index 6621a18632..a1c6dfe0bc 100644 --- a/pkg/framework/plugins/nodeutilization/defaults.go +++ b/pkg/framework/plugins/nodeutilization/defaults.go @@ -23,28 +23,30 @@ func addDefaultingFuncs(scheme *runtime.Scheme) error { // SetDefaults_LowNodeUtilizationArgs // TODO: the final default values would be discussed in community -func SetDefaults_LowNodeUtilizationArgs(obj *LowNodeUtilizationArgs) { - if !obj.UseDeviationThresholds { - obj.UseDeviationThresholds = false +func SetDefaults_LowNodeUtilizationArgs(obj runtime.Object) { + args := obj.(*LowNodeUtilizationArgs) + if !args.UseDeviationThresholds { + args.UseDeviationThresholds = false } - if obj.Thresholds == nil { - obj.Thresholds = nil + if args.Thresholds == nil { + args.Thresholds = nil } - if obj.TargetThresholds == nil { - obj.TargetThresholds = nil + if args.TargetThresholds == nil { + args.TargetThresholds = nil } - if obj.NumberOfNodes == 0 { - obj.NumberOfNodes = 0 + if args.NumberOfNodes == 0 { + args.NumberOfNodes = 0 } } // SetDefaults_HighNodeUtilizationArgs // TODO: the final default values would be discussed in community -func SetDefaults_HighNodeUtilizationArgs(obj *HighNodeUtilizationArgs) { - if obj.Thresholds == nil { - obj.Thresholds = nil +func SetDefaults_HighNodeUtilizationArgs(obj runtime.Object) { + args := obj.(*HighNodeUtilizationArgs) + if args.Thresholds == nil { + args.Thresholds = nil } - if obj.NumberOfNodes == 0 { - obj.NumberOfNodes = 0 + if args.NumberOfNodes == 0 { + args.NumberOfNodes = 0 } } diff --git a/pkg/framework/plugins/nodeutilization/validation.go b/pkg/framework/plugins/nodeutilization/validation.go index ab7d450e1f..5df502483d 100644 --- a/pkg/framework/plugins/nodeutilization/validation.go +++ b/pkg/framework/plugins/nodeutilization/validation.go @@ -16,10 +16,12 @@ package nodeutilization import ( "fmt" + "k8s.io/apimachinery/pkg/runtime" "sigs.k8s.io/descheduler/pkg/api" ) -func ValidateHighNodeUtilizationArgs(args *HighNodeUtilizationArgs) error { +func ValidateHighNodeUtilizationArgs(obj runtime.Object) error { + args := obj.(*HighNodeUtilizationArgs) // only exclude can be set, or not at all if args.EvictableNamespaces != nil && len(args.EvictableNamespaces.Include) > 0 { return fmt.Errorf("only Exclude namespaces can be set, inclusion is not supported") @@ -32,7 +34,8 @@ func ValidateHighNodeUtilizationArgs(args *HighNodeUtilizationArgs) error { return nil } -func ValidateLowNodeUtilizationArgs(args *LowNodeUtilizationArgs) error { +func ValidateLowNodeUtilizationArgs(obj runtime.Object) error { + args := obj.(*LowNodeUtilizationArgs) // only exclude can be set, or not at all if args.EvictableNamespaces != nil && len(args.EvictableNamespaces.Include) > 0 { return fmt.Errorf("only Exclude namespaces can be set, inclusion is not supported") diff --git a/pkg/framework/plugins/nodeutilization/zz_generated.deepcopy.go b/pkg/framework/plugins/nodeutilization/zz_generated.deepcopy.go index efeab18167..66146e025c 100644 --- a/pkg/framework/plugins/nodeutilization/zz_generated.deepcopy.go +++ b/pkg/framework/plugins/nodeutilization/zz_generated.deepcopy.go @@ -2,7 +2,7 @@ // +build !ignore_autogenerated /* -Copyright 2022 The Kubernetes Authors. +Copyright 2023 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. diff --git a/pkg/framework/plugins/nodeutilization/zz_generated.defaults.go b/pkg/framework/plugins/nodeutilization/zz_generated.defaults.go index ede106f47c..42bf5d6dd2 100644 --- a/pkg/framework/plugins/nodeutilization/zz_generated.defaults.go +++ b/pkg/framework/plugins/nodeutilization/zz_generated.defaults.go @@ -2,7 +2,7 @@ // +build !ignore_autogenerated /* -Copyright 2022 The Kubernetes Authors. +Copyright 2023 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. @@ -29,15 +29,5 @@ import ( // Public to allow building arbitrary schemes. // All generated defaulters are covering - they call all nested defaulters. func RegisterDefaults(scheme *runtime.Scheme) error { - scheme.AddTypeDefaultingFunc(&HighNodeUtilizationArgs{}, func(obj interface{}) { SetObjectDefaults_HighNodeUtilizationArgs(obj.(*HighNodeUtilizationArgs)) }) - scheme.AddTypeDefaultingFunc(&LowNodeUtilizationArgs{}, func(obj interface{}) { SetObjectDefaults_LowNodeUtilizationArgs(obj.(*LowNodeUtilizationArgs)) }) return nil } - -func SetObjectDefaults_HighNodeUtilizationArgs(in *HighNodeUtilizationArgs) { - SetDefaults_HighNodeUtilizationArgs(in) -} - -func SetObjectDefaults_LowNodeUtilizationArgs(in *LowNodeUtilizationArgs) { - SetDefaults_LowNodeUtilizationArgs(in) -} diff --git a/pkg/framework/plugins/podlifetime/defaults.go b/pkg/framework/plugins/podlifetime/defaults.go index b4aaa36864..b669e781c6 100644 --- a/pkg/framework/plugins/podlifetime/defaults.go +++ b/pkg/framework/plugins/podlifetime/defaults.go @@ -23,17 +23,18 @@ func addDefaultingFuncs(scheme *runtime.Scheme) error { // SetDefaults_PodLifeTimeArgs // TODO: the final default values would be discussed in community -func SetDefaults_PodLifeTimeArgs(obj *PodLifeTimeArgs) { - if obj.Namespaces == nil { - obj.Namespaces = nil +func SetDefaults_PodLifeTimeArgs(obj runtime.Object) { + args := obj.(*PodLifeTimeArgs) + if args.Namespaces == nil { + args.Namespaces = nil } - if obj.LabelSelector == nil { - obj.LabelSelector = nil + if args.LabelSelector == nil { + args.LabelSelector = nil } - if obj.MaxPodLifeTimeSeconds == nil { - obj.MaxPodLifeTimeSeconds = nil + if args.MaxPodLifeTimeSeconds == nil { + args.MaxPodLifeTimeSeconds = nil } - if obj.States == nil { - obj.States = nil + if args.States == nil { + args.States = nil } } diff --git a/pkg/framework/plugins/podlifetime/validation.go b/pkg/framework/plugins/podlifetime/validation.go index c7dd72be25..144120beb5 100644 --- a/pkg/framework/plugins/podlifetime/validation.go +++ b/pkg/framework/plugins/podlifetime/validation.go @@ -19,13 +19,16 @@ package podlifetime import ( "fmt" + "k8s.io/apimachinery/pkg/runtime" + v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/sets" ) // ValidatePodLifeTimeArgs validates PodLifeTime arguments -func ValidatePodLifeTimeArgs(args *PodLifeTimeArgs) error { +func ValidatePodLifeTimeArgs(obj runtime.Object) error { + args := obj.(*PodLifeTimeArgs) if args.MaxPodLifeTimeSeconds == nil { return fmt.Errorf("MaxPodLifeTimeSeconds not set") } diff --git a/pkg/framework/plugins/podlifetime/zz_generated.deepcopy.go b/pkg/framework/plugins/podlifetime/zz_generated.deepcopy.go index 277c92ba97..d79486c89f 100644 --- a/pkg/framework/plugins/podlifetime/zz_generated.deepcopy.go +++ b/pkg/framework/plugins/podlifetime/zz_generated.deepcopy.go @@ -2,7 +2,7 @@ // +build !ignore_autogenerated /* -Copyright 2022 The Kubernetes Authors. +Copyright 2023 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. diff --git a/pkg/framework/plugins/podlifetime/zz_generated.defaults.go b/pkg/framework/plugins/podlifetime/zz_generated.defaults.go index fc593d17d3..d5eeb657c7 100644 --- a/pkg/framework/plugins/podlifetime/zz_generated.defaults.go +++ b/pkg/framework/plugins/podlifetime/zz_generated.defaults.go @@ -2,7 +2,7 @@ // +build !ignore_autogenerated /* -Copyright 2022 The Kubernetes Authors. +Copyright 2023 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. @@ -29,10 +29,5 @@ import ( // Public to allow building arbitrary schemes. // All generated defaulters are covering - they call all nested defaulters. func RegisterDefaults(scheme *runtime.Scheme) error { - scheme.AddTypeDefaultingFunc(&PodLifeTimeArgs{}, func(obj interface{}) { SetObjectDefaults_PodLifeTimeArgs(obj.(*PodLifeTimeArgs)) }) return nil } - -func SetObjectDefaults_PodLifeTimeArgs(in *PodLifeTimeArgs) { - SetDefaults_PodLifeTimeArgs(in) -} diff --git a/pkg/framework/plugins/removeduplicates/defaults.go b/pkg/framework/plugins/removeduplicates/defaults.go index 7da4f68989..1ed3020e79 100644 --- a/pkg/framework/plugins/removeduplicates/defaults.go +++ b/pkg/framework/plugins/removeduplicates/defaults.go @@ -23,11 +23,12 @@ func addDefaultingFuncs(scheme *runtime.Scheme) error { // SetDefaults_RemoveDuplicatesArgs // TODO: the final default values would be discussed in community -func SetDefaults_RemoveDuplicatesArgs(obj *RemoveDuplicatesArgs) { - if obj.Namespaces == nil { - obj.Namespaces = nil +func SetDefaults_RemoveDuplicatesArgs(obj runtime.Object) { + args := obj.(*RemoveDuplicatesArgs) + if args.Namespaces == nil { + args.Namespaces = nil } - if obj.ExcludeOwnerKinds == nil { - obj.ExcludeOwnerKinds = nil + if args.ExcludeOwnerKinds == nil { + args.ExcludeOwnerKinds = nil } } diff --git a/pkg/framework/plugins/removeduplicates/validation.go b/pkg/framework/plugins/removeduplicates/validation.go index 240bd36e92..a2e359e442 100644 --- a/pkg/framework/plugins/removeduplicates/validation.go +++ b/pkg/framework/plugins/removeduplicates/validation.go @@ -15,9 +15,12 @@ package removeduplicates import ( "fmt" + + "k8s.io/apimachinery/pkg/runtime" ) -func ValidateRemoveDuplicatesArgs(args *RemoveDuplicatesArgs) error { +func ValidateRemoveDuplicatesArgs(obj runtime.Object) error { + args := obj.(*RemoveDuplicatesArgs) // At most one of include/exclude can be set if args.Namespaces != nil && len(args.Namespaces.Include) > 0 && len(args.Namespaces.Exclude) > 0 { return fmt.Errorf("only one of Include/Exclude namespaces can be set") diff --git a/pkg/framework/plugins/removeduplicates/zz_generated.deepcopy.go b/pkg/framework/plugins/removeduplicates/zz_generated.deepcopy.go index bc3652f1d0..fb9fbc2e8a 100644 --- a/pkg/framework/plugins/removeduplicates/zz_generated.deepcopy.go +++ b/pkg/framework/plugins/removeduplicates/zz_generated.deepcopy.go @@ -2,7 +2,7 @@ // +build !ignore_autogenerated /* -Copyright 2022 The Kubernetes Authors. +Copyright 2023 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. diff --git a/pkg/framework/plugins/removeduplicates/zz_generated.defaults.go b/pkg/framework/plugins/removeduplicates/zz_generated.defaults.go index 2ee3e64b74..6148aa0c83 100644 --- a/pkg/framework/plugins/removeduplicates/zz_generated.defaults.go +++ b/pkg/framework/plugins/removeduplicates/zz_generated.defaults.go @@ -2,7 +2,7 @@ // +build !ignore_autogenerated /* -Copyright 2022 The Kubernetes Authors. +Copyright 2023 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. @@ -29,10 +29,5 @@ import ( // Public to allow building arbitrary schemes. // All generated defaulters are covering - they call all nested defaulters. func RegisterDefaults(scheme *runtime.Scheme) error { - scheme.AddTypeDefaultingFunc(&RemoveDuplicatesArgs{}, func(obj interface{}) { SetObjectDefaults_RemoveDuplicatesArgs(obj.(*RemoveDuplicatesArgs)) }) return nil } - -func SetObjectDefaults_RemoveDuplicatesArgs(in *RemoveDuplicatesArgs) { - SetDefaults_RemoveDuplicatesArgs(in) -} diff --git a/pkg/framework/plugins/removefailedpods/defaults.go b/pkg/framework/plugins/removefailedpods/defaults.go index 52f95e1c6e..3fa38d1650 100644 --- a/pkg/framework/plugins/removefailedpods/defaults.go +++ b/pkg/framework/plugins/removefailedpods/defaults.go @@ -15,6 +15,7 @@ package removefailedpods import ( "k8s.io/apimachinery/pkg/runtime" + utilpointer "k8s.io/utils/pointer" ) func addDefaultingFuncs(scheme *runtime.Scheme) error { @@ -23,23 +24,24 @@ func addDefaultingFuncs(scheme *runtime.Scheme) error { // SetDefaults_RemoveFailedPodsArgs // TODO: the final default values would be discussed in community -func SetDefaults_RemoveFailedPodsArgs(obj *RemoveFailedPodsArgs) { - if obj.Namespaces == nil { - obj.Namespaces = nil +func SetDefaults_RemoveFailedPodsArgs(obj runtime.Object) { + args := obj.(*RemoveFailedPodsArgs) + if args.Namespaces == nil { + args.Namespaces = nil } - if obj.LabelSelector == nil { - obj.LabelSelector = nil + if args.LabelSelector == nil { + args.LabelSelector = nil } - if obj.ExcludeOwnerKinds == nil { - obj.ExcludeOwnerKinds = nil + if args.ExcludeOwnerKinds == nil { + args.ExcludeOwnerKinds = nil } - if obj.MinPodLifetimeSeconds == nil { - obj.MinPodLifetimeSeconds = nil + if args.MinPodLifetimeSeconds == nil { + args.MinPodLifetimeSeconds = utilpointer.Uint(3600) } - if obj.Reasons == nil { - obj.Reasons = nil + if args.Reasons == nil { + args.Reasons = nil } - if !obj.IncludingInitContainers { - obj.IncludingInitContainers = false + if !args.IncludingInitContainers { + args.IncludingInitContainers = false } } diff --git a/pkg/framework/plugins/removefailedpods/validation.go b/pkg/framework/plugins/removefailedpods/validation.go index 11aa6c7d3a..6d04065bab 100644 --- a/pkg/framework/plugins/removefailedpods/validation.go +++ b/pkg/framework/plugins/removefailedpods/validation.go @@ -17,10 +17,12 @@ import ( "fmt" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" ) // ValidateRemoveFailedPodsArgs validates RemoveFailedPods arguments -func ValidateRemoveFailedPodsArgs(args *RemoveFailedPodsArgs) error { +func ValidateRemoveFailedPodsArgs(obj runtime.Object) error { + args := obj.(*RemoveFailedPodsArgs) // At most one of include/exclude can be set if args.Namespaces != nil && len(args.Namespaces.Include) > 0 && len(args.Namespaces.Exclude) > 0 { return fmt.Errorf("only one of Include/Exclude namespaces can be set") diff --git a/pkg/framework/plugins/removefailedpods/zz_generated.deepcopy.go b/pkg/framework/plugins/removefailedpods/zz_generated.deepcopy.go index 67fbf5f8fb..a2cd85c1f6 100644 --- a/pkg/framework/plugins/removefailedpods/zz_generated.deepcopy.go +++ b/pkg/framework/plugins/removefailedpods/zz_generated.deepcopy.go @@ -2,7 +2,7 @@ // +build !ignore_autogenerated /* -Copyright 2022 The Kubernetes Authors. +Copyright 2023 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. diff --git a/pkg/framework/plugins/removefailedpods/zz_generated.defaults.go b/pkg/framework/plugins/removefailedpods/zz_generated.defaults.go index 62c6d8052d..85e9449f4c 100644 --- a/pkg/framework/plugins/removefailedpods/zz_generated.defaults.go +++ b/pkg/framework/plugins/removefailedpods/zz_generated.defaults.go @@ -2,7 +2,7 @@ // +build !ignore_autogenerated /* -Copyright 2022 The Kubernetes Authors. +Copyright 2023 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. @@ -29,10 +29,5 @@ import ( // Public to allow building arbitrary schemes. // All generated defaulters are covering - they call all nested defaulters. func RegisterDefaults(scheme *runtime.Scheme) error { - scheme.AddTypeDefaultingFunc(&RemoveFailedPodsArgs{}, func(obj interface{}) { SetObjectDefaults_RemoveFailedPodsArgs(obj.(*RemoveFailedPodsArgs)) }) return nil } - -func SetObjectDefaults_RemoveFailedPodsArgs(in *RemoveFailedPodsArgs) { - SetDefaults_RemoveFailedPodsArgs(in) -} diff --git a/pkg/framework/plugins/removepodshavingtoomanyrestarts/defaults.go b/pkg/framework/plugins/removepodshavingtoomanyrestarts/defaults.go index e62af8e729..539f661602 100644 --- a/pkg/framework/plugins/removepodshavingtoomanyrestarts/defaults.go +++ b/pkg/framework/plugins/removepodshavingtoomanyrestarts/defaults.go @@ -23,17 +23,18 @@ func addDefaultingFuncs(scheme *runtime.Scheme) error { // SetDefaults_RemovePodsHavingTooManyRestartsArgs // TODO: the final default values would be discussed in community -func SetDefaults_RemovePodsHavingTooManyRestartsArgs(obj *RemovePodsHavingTooManyRestartsArgs) { - if obj.Namespaces == nil { - obj.Namespaces = nil +func SetDefaults_RemovePodsHavingTooManyRestartsArgs(obj runtime.Object) { + args := obj.(*RemovePodsHavingTooManyRestartsArgs) + if args.Namespaces == nil { + args.Namespaces = nil } - if obj.LabelSelector == nil { - obj.LabelSelector = nil + if args.LabelSelector == nil { + args.LabelSelector = nil } - if obj.PodRestartThreshold == 0 { - obj.PodRestartThreshold = 0 + if args.PodRestartThreshold == 0 { + args.PodRestartThreshold = 0 } - if !obj.IncludingInitContainers { - obj.IncludingInitContainers = false + if !args.IncludingInitContainers { + args.IncludingInitContainers = false } } diff --git a/pkg/framework/plugins/removepodshavingtoomanyrestarts/validation.go b/pkg/framework/plugins/removepodshavingtoomanyrestarts/validation.go index cfb7365329..d734f3c74c 100644 --- a/pkg/framework/plugins/removepodshavingtoomanyrestarts/validation.go +++ b/pkg/framework/plugins/removepodshavingtoomanyrestarts/validation.go @@ -17,10 +17,12 @@ import ( "fmt" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" ) // ValidateRemovePodsHavingTooManyRestartsArgs validates RemovePodsHavingTooManyRestarts arguments -func ValidateRemovePodsHavingTooManyRestartsArgs(args *RemovePodsHavingTooManyRestartsArgs) error { +func ValidateRemovePodsHavingTooManyRestartsArgs(obj runtime.Object) error { + args := obj.(*RemovePodsHavingTooManyRestartsArgs) // At most one of include/exclude can be set if args.Namespaces != nil && len(args.Namespaces.Include) > 0 && len(args.Namespaces.Exclude) > 0 { return fmt.Errorf("only one of Include/Exclude namespaces can be set") diff --git a/pkg/framework/plugins/removepodshavingtoomanyrestarts/zz_generated.deepcopy.go b/pkg/framework/plugins/removepodshavingtoomanyrestarts/zz_generated.deepcopy.go index f4e25f17ae..0971574eee 100644 --- a/pkg/framework/plugins/removepodshavingtoomanyrestarts/zz_generated.deepcopy.go +++ b/pkg/framework/plugins/removepodshavingtoomanyrestarts/zz_generated.deepcopy.go @@ -2,7 +2,7 @@ // +build !ignore_autogenerated /* -Copyright 2022 The Kubernetes Authors. +Copyright 2023 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. diff --git a/pkg/framework/plugins/removepodshavingtoomanyrestarts/zz_generated.defaults.go b/pkg/framework/plugins/removepodshavingtoomanyrestarts/zz_generated.defaults.go index 7705a78a9d..fb8110bb11 100644 --- a/pkg/framework/plugins/removepodshavingtoomanyrestarts/zz_generated.defaults.go +++ b/pkg/framework/plugins/removepodshavingtoomanyrestarts/zz_generated.defaults.go @@ -2,7 +2,7 @@ // +build !ignore_autogenerated /* -Copyright 2022 The Kubernetes Authors. +Copyright 2023 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. @@ -29,12 +29,5 @@ import ( // Public to allow building arbitrary schemes. // All generated defaulters are covering - they call all nested defaulters. func RegisterDefaults(scheme *runtime.Scheme) error { - scheme.AddTypeDefaultingFunc(&RemovePodsHavingTooManyRestartsArgs{}, func(obj interface{}) { - SetObjectDefaults_RemovePodsHavingTooManyRestartsArgs(obj.(*RemovePodsHavingTooManyRestartsArgs)) - }) return nil } - -func SetObjectDefaults_RemovePodsHavingTooManyRestartsArgs(in *RemovePodsHavingTooManyRestartsArgs) { - SetDefaults_RemovePodsHavingTooManyRestartsArgs(in) -} diff --git a/pkg/framework/plugins/removepodsviolatinginterpodantiaffinity/defaults.go b/pkg/framework/plugins/removepodsviolatinginterpodantiaffinity/defaults.go index 75a51362fb..bfbdb5b820 100644 --- a/pkg/framework/plugins/removepodsviolatinginterpodantiaffinity/defaults.go +++ b/pkg/framework/plugins/removepodsviolatinginterpodantiaffinity/defaults.go @@ -23,11 +23,12 @@ func addDefaultingFuncs(scheme *runtime.Scheme) error { // SetDefaults_RemovePodsViolatingInterPodAntiAffinityArgs // TODO: the final default values would be discussed in community -func SetDefaults_RemovePodsViolatingInterPodAntiAffinityArgs(obj *RemovePodsViolatingInterPodAntiAffinityArgs) { - if obj.Namespaces == nil { - obj.Namespaces = nil +func SetDefaults_RemovePodsViolatingInterPodAntiAffinityArgs(obj runtime.Object) { + args := obj.(*RemovePodsViolatingInterPodAntiAffinityArgs) + if args.Namespaces == nil { + args.Namespaces = nil } - if obj.LabelSelector == nil { - obj.LabelSelector = nil + if args.LabelSelector == nil { + args.LabelSelector = nil } } diff --git a/pkg/framework/plugins/removepodsviolatinginterpodantiaffinity/validation.go b/pkg/framework/plugins/removepodsviolatinginterpodantiaffinity/validation.go index c20708efd5..514cdb8e45 100644 --- a/pkg/framework/plugins/removepodsviolatinginterpodantiaffinity/validation.go +++ b/pkg/framework/plugins/removepodsviolatinginterpodantiaffinity/validation.go @@ -17,10 +17,12 @@ import ( "fmt" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" ) // ValidateRemovePodsViolatingInterPodAntiAffinityArgs validates ValidateRemovePodsViolatingInterPodAntiAffinity arguments -func ValidateRemovePodsViolatingInterPodAntiAffinityArgs(args *RemovePodsViolatingInterPodAntiAffinityArgs) error { +func ValidateRemovePodsViolatingInterPodAntiAffinityArgs(obj runtime.Object) error { + args := obj.(*RemovePodsViolatingInterPodAntiAffinityArgs) // At most one of include/exclude can be set if args.Namespaces != nil && len(args.Namespaces.Include) > 0 && len(args.Namespaces.Exclude) > 0 { return fmt.Errorf("only one of Include/Exclude namespaces can be set") diff --git a/pkg/framework/plugins/removepodsviolatinginterpodantiaffinity/zz_generated.deepcopy.go b/pkg/framework/plugins/removepodsviolatinginterpodantiaffinity/zz_generated.deepcopy.go index 0a3cee85a9..b2b2f190a9 100644 --- a/pkg/framework/plugins/removepodsviolatinginterpodantiaffinity/zz_generated.deepcopy.go +++ b/pkg/framework/plugins/removepodsviolatinginterpodantiaffinity/zz_generated.deepcopy.go @@ -2,7 +2,7 @@ // +build !ignore_autogenerated /* -Copyright 2022 The Kubernetes Authors. +Copyright 2023 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. diff --git a/pkg/framework/plugins/removepodsviolatinginterpodantiaffinity/zz_generated.defaults.go b/pkg/framework/plugins/removepodsviolatinginterpodantiaffinity/zz_generated.defaults.go index 95c93e12df..b6bdebf769 100644 --- a/pkg/framework/plugins/removepodsviolatinginterpodantiaffinity/zz_generated.defaults.go +++ b/pkg/framework/plugins/removepodsviolatinginterpodantiaffinity/zz_generated.defaults.go @@ -2,7 +2,7 @@ // +build !ignore_autogenerated /* -Copyright 2022 The Kubernetes Authors. +Copyright 2023 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. @@ -29,12 +29,5 @@ import ( // Public to allow building arbitrary schemes. // All generated defaulters are covering - they call all nested defaulters. func RegisterDefaults(scheme *runtime.Scheme) error { - scheme.AddTypeDefaultingFunc(&RemovePodsViolatingInterPodAntiAffinityArgs{}, func(obj interface{}) { - SetObjectDefaults_RemovePodsViolatingInterPodAntiAffinityArgs(obj.(*RemovePodsViolatingInterPodAntiAffinityArgs)) - }) return nil } - -func SetObjectDefaults_RemovePodsViolatingInterPodAntiAffinityArgs(in *RemovePodsViolatingInterPodAntiAffinityArgs) { - SetDefaults_RemovePodsViolatingInterPodAntiAffinityArgs(in) -} diff --git a/pkg/framework/plugins/removepodsviolatingnodeaffinity/defaults.go b/pkg/framework/plugins/removepodsviolatingnodeaffinity/defaults.go index e8f5cf2cba..1fac940c81 100644 --- a/pkg/framework/plugins/removepodsviolatingnodeaffinity/defaults.go +++ b/pkg/framework/plugins/removepodsviolatingnodeaffinity/defaults.go @@ -23,11 +23,12 @@ func addDefaultingFuncs(scheme *runtime.Scheme) error { // SetDefaults_RemovePodsViolatingNodeAffinityArgs // TODO: the final default values would be discussed in community -func SetDefaults_RemovePodsViolatingNodeAffinityArgs(obj *RemovePodsViolatingNodeAffinityArgs) { - if obj.Namespaces == nil { - obj.Namespaces = nil +func SetDefaults_RemovePodsViolatingNodeAffinityArgs(obj runtime.Object) { + args := obj.(*RemovePodsViolatingNodeAffinityArgs) + if args.Namespaces == nil { + args.Namespaces = nil } - if obj.LabelSelector == nil { - obj.LabelSelector = nil + if args.LabelSelector == nil { + args.LabelSelector = nil } } diff --git a/pkg/framework/plugins/removepodsviolatingnodeaffinity/validation.go b/pkg/framework/plugins/removepodsviolatingnodeaffinity/validation.go index 28130aca38..8c95291ebe 100644 --- a/pkg/framework/plugins/removepodsviolatingnodeaffinity/validation.go +++ b/pkg/framework/plugins/removepodsviolatingnodeaffinity/validation.go @@ -20,10 +20,12 @@ import ( "fmt" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" ) // ValidateRemovePodsViolatingNodeAffinityArgs validates RemovePodsViolatingNodeAffinity arguments -func ValidateRemovePodsViolatingNodeAffinityArgs(args *RemovePodsViolatingNodeAffinityArgs) error { +func ValidateRemovePodsViolatingNodeAffinityArgs(obj runtime.Object) error { + args := obj.(*RemovePodsViolatingNodeAffinityArgs) if args == nil || len(args.NodeAffinityType) == 0 { return fmt.Errorf("nodeAffinityType needs to be set") } diff --git a/pkg/framework/plugins/removepodsviolatingnodeaffinity/zz_generated.deepcopy.go b/pkg/framework/plugins/removepodsviolatingnodeaffinity/zz_generated.deepcopy.go index 4b74d52cc4..638277c252 100644 --- a/pkg/framework/plugins/removepodsviolatingnodeaffinity/zz_generated.deepcopy.go +++ b/pkg/framework/plugins/removepodsviolatingnodeaffinity/zz_generated.deepcopy.go @@ -2,7 +2,7 @@ // +build !ignore_autogenerated /* -Copyright 2022 The Kubernetes Authors. +Copyright 2023 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. diff --git a/pkg/framework/plugins/removepodsviolatingnodeaffinity/zz_generated.defaults.go b/pkg/framework/plugins/removepodsviolatingnodeaffinity/zz_generated.defaults.go index 610db082f9..b395c6ee98 100644 --- a/pkg/framework/plugins/removepodsviolatingnodeaffinity/zz_generated.defaults.go +++ b/pkg/framework/plugins/removepodsviolatingnodeaffinity/zz_generated.defaults.go @@ -2,7 +2,7 @@ // +build !ignore_autogenerated /* -Copyright 2022 The Kubernetes Authors. +Copyright 2023 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. @@ -29,12 +29,5 @@ import ( // Public to allow building arbitrary schemes. // All generated defaulters are covering - they call all nested defaulters. func RegisterDefaults(scheme *runtime.Scheme) error { - scheme.AddTypeDefaultingFunc(&RemovePodsViolatingNodeAffinityArgs{}, func(obj interface{}) { - SetObjectDefaults_RemovePodsViolatingNodeAffinityArgs(obj.(*RemovePodsViolatingNodeAffinityArgs)) - }) return nil } - -func SetObjectDefaults_RemovePodsViolatingNodeAffinityArgs(in *RemovePodsViolatingNodeAffinityArgs) { - SetDefaults_RemovePodsViolatingNodeAffinityArgs(in) -} diff --git a/pkg/framework/plugins/removepodsviolatingnodetaints/defaults.go b/pkg/framework/plugins/removepodsviolatingnodetaints/defaults.go index 12eebb91bf..ca026650bc 100644 --- a/pkg/framework/plugins/removepodsviolatingnodetaints/defaults.go +++ b/pkg/framework/plugins/removepodsviolatingnodetaints/defaults.go @@ -23,17 +23,18 @@ func addDefaultingFuncs(scheme *runtime.Scheme) error { // SetDefaults_RemovePodsViolatingNodeTaintsArgs // TODO: the final default values would be discussed in community -func SetDefaults_RemovePodsViolatingNodeTaintsArgs(obj *RemovePodsViolatingNodeTaintsArgs) { - if obj.Namespaces == nil { - obj.Namespaces = nil +func SetDefaults_RemovePodsViolatingNodeTaintsArgs(obj runtime.Object) { + args := obj.(*RemovePodsViolatingNodeTaintsArgs) + if args.Namespaces == nil { + args.Namespaces = nil } - if obj.LabelSelector == nil { - obj.LabelSelector = nil + if args.LabelSelector == nil { + args.LabelSelector = nil } - if !obj.IncludePreferNoSchedule { - obj.IncludePreferNoSchedule = false + if !args.IncludePreferNoSchedule { + args.IncludePreferNoSchedule = false } - if obj.ExcludedTaints == nil { - obj.ExcludedTaints = nil + if args.ExcludedTaints == nil { + args.ExcludedTaints = nil } } diff --git a/pkg/framework/plugins/removepodsviolatingnodetaints/validation.go b/pkg/framework/plugins/removepodsviolatingnodetaints/validation.go index 6bea7543f0..c7f6fc6b38 100644 --- a/pkg/framework/plugins/removepodsviolatingnodetaints/validation.go +++ b/pkg/framework/plugins/removepodsviolatingnodetaints/validation.go @@ -20,10 +20,12 @@ import ( "fmt" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" ) // ValidateRemovePodsViolatingNodeTaintsArgs validates RemovePodsViolatingNodeTaints arguments -func ValidateRemovePodsViolatingNodeTaintsArgs(args *RemovePodsViolatingNodeTaintsArgs) error { +func ValidateRemovePodsViolatingNodeTaintsArgs(obj runtime.Object) error { + args := obj.(*RemovePodsViolatingNodeTaintsArgs) // At most one of include/exclude can be set if args.Namespaces != nil && len(args.Namespaces.Include) > 0 && len(args.Namespaces.Exclude) > 0 { return fmt.Errorf("only one of Include/Exclude namespaces can be set") diff --git a/pkg/framework/plugins/removepodsviolatingnodetaints/zz_generated.deepcopy.go b/pkg/framework/plugins/removepodsviolatingnodetaints/zz_generated.deepcopy.go index 5efb12af6f..f3c14df339 100644 --- a/pkg/framework/plugins/removepodsviolatingnodetaints/zz_generated.deepcopy.go +++ b/pkg/framework/plugins/removepodsviolatingnodetaints/zz_generated.deepcopy.go @@ -2,7 +2,7 @@ // +build !ignore_autogenerated /* -Copyright 2022 The Kubernetes Authors. +Copyright 2023 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. diff --git a/pkg/framework/plugins/removepodsviolatingnodetaints/zz_generated.defaults.go b/pkg/framework/plugins/removepodsviolatingnodetaints/zz_generated.defaults.go index 0ea6f06be0..f400d54157 100644 --- a/pkg/framework/plugins/removepodsviolatingnodetaints/zz_generated.defaults.go +++ b/pkg/framework/plugins/removepodsviolatingnodetaints/zz_generated.defaults.go @@ -2,7 +2,7 @@ // +build !ignore_autogenerated /* -Copyright 2022 The Kubernetes Authors. +Copyright 2023 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. @@ -29,12 +29,5 @@ import ( // Public to allow building arbitrary schemes. // All generated defaulters are covering - they call all nested defaulters. func RegisterDefaults(scheme *runtime.Scheme) error { - scheme.AddTypeDefaultingFunc(&RemovePodsViolatingNodeTaintsArgs{}, func(obj interface{}) { - SetObjectDefaults_RemovePodsViolatingNodeTaintsArgs(obj.(*RemovePodsViolatingNodeTaintsArgs)) - }) return nil } - -func SetObjectDefaults_RemovePodsViolatingNodeTaintsArgs(in *RemovePodsViolatingNodeTaintsArgs) { - SetDefaults_RemovePodsViolatingNodeTaintsArgs(in) -} diff --git a/pkg/framework/plugins/removepodsviolatingtopologyspreadconstraint/defaults.go b/pkg/framework/plugins/removepodsviolatingtopologyspreadconstraint/defaults.go index 6d62ee6842..ff468c2158 100644 --- a/pkg/framework/plugins/removepodsviolatingtopologyspreadconstraint/defaults.go +++ b/pkg/framework/plugins/removepodsviolatingtopologyspreadconstraint/defaults.go @@ -23,14 +23,15 @@ func addDefaultingFuncs(scheme *runtime.Scheme) error { // SetDefaults_RemovePodsViolatingTopologySpreadConstraintArgs // TODO: the final default values would be discussed in community -func SetDefaults_RemovePodsViolatingTopologySpreadConstraintArgs(obj *RemovePodsViolatingTopologySpreadConstraintArgs) { - if obj.Namespaces == nil { - obj.Namespaces = nil +func SetDefaults_RemovePodsViolatingTopologySpreadConstraintArgs(obj runtime.Object) { + args := obj.(*RemovePodsViolatingTopologySpreadConstraintArgs) + if args.Namespaces == nil { + args.Namespaces = nil } - if obj.LabelSelector == nil { - obj.LabelSelector = nil + if args.LabelSelector == nil { + args.LabelSelector = nil } - if !obj.IncludeSoftConstraints { - obj.IncludeSoftConstraints = false + if !args.IncludeSoftConstraints { + args.IncludeSoftConstraints = false } } diff --git a/pkg/framework/plugins/removepodsviolatingtopologyspreadconstraint/validation.go b/pkg/framework/plugins/removepodsviolatingtopologyspreadconstraint/validation.go index 831e239220..60ebf68ef0 100644 --- a/pkg/framework/plugins/removepodsviolatingtopologyspreadconstraint/validation.go +++ b/pkg/framework/plugins/removepodsviolatingtopologyspreadconstraint/validation.go @@ -20,10 +20,12 @@ import ( "fmt" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" ) // ValidateRemovePodsViolatingTopologySpreadConstraintArgs validates RemovePodsViolatingTopologySpreadConstraint arguments -func ValidateRemovePodsViolatingTopologySpreadConstraintArgs(args *RemovePodsViolatingTopologySpreadConstraintArgs) error { +func ValidateRemovePodsViolatingTopologySpreadConstraintArgs(obj runtime.Object) error { + args := obj.(*RemovePodsViolatingTopologySpreadConstraintArgs) // At most one of include/exclude can be set if args.Namespaces != nil && len(args.Namespaces.Include) > 0 && len(args.Namespaces.Exclude) > 0 { return fmt.Errorf("only one of Include/Exclude namespaces can be set") diff --git a/pkg/framework/plugins/removepodsviolatingtopologyspreadconstraint/zz_generated.deepcopy.go b/pkg/framework/plugins/removepodsviolatingtopologyspreadconstraint/zz_generated.deepcopy.go index 93f242a1e5..dd15101a1c 100644 --- a/pkg/framework/plugins/removepodsviolatingtopologyspreadconstraint/zz_generated.deepcopy.go +++ b/pkg/framework/plugins/removepodsviolatingtopologyspreadconstraint/zz_generated.deepcopy.go @@ -2,7 +2,7 @@ // +build !ignore_autogenerated /* -Copyright 2022 The Kubernetes Authors. +Copyright 2023 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. diff --git a/pkg/framework/plugins/removepodsviolatingtopologyspreadconstraint/zz_generated.defaults.go b/pkg/framework/plugins/removepodsviolatingtopologyspreadconstraint/zz_generated.defaults.go index 2659305b24..0fbdd94617 100644 --- a/pkg/framework/plugins/removepodsviolatingtopologyspreadconstraint/zz_generated.defaults.go +++ b/pkg/framework/plugins/removepodsviolatingtopologyspreadconstraint/zz_generated.defaults.go @@ -2,7 +2,7 @@ // +build !ignore_autogenerated /* -Copyright 2022 The Kubernetes Authors. +Copyright 2023 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. @@ -29,12 +29,5 @@ import ( // Public to allow building arbitrary schemes. // All generated defaulters are covering - they call all nested defaulters. func RegisterDefaults(scheme *runtime.Scheme) error { - scheme.AddTypeDefaultingFunc(&RemovePodsViolatingTopologySpreadConstraintArgs{}, func(obj interface{}) { - SetObjectDefaults_RemovePodsViolatingTopologySpreadConstraintArgs(obj.(*RemovePodsViolatingTopologySpreadConstraintArgs)) - }) return nil } - -func SetObjectDefaults_RemovePodsViolatingTopologySpreadConstraintArgs(in *RemovePodsViolatingTopologySpreadConstraintArgs) { - SetDefaults_RemovePodsViolatingTopologySpreadConstraintArgs(in) -}