From 8b2cb93125250bf41e8235b9fcb1bb92911673bf Mon Sep 17 00:00:00 2001 From: Lucas Severo Alves Date: Thu, 1 Dec 2022 18:44:06 +0100 Subject: [PATCH 01/13] add v1alpha2 registry based conversion --- pkg/api/conversion.go | 14 + pkg/api/v1alpha1/conversion.go | 14 + pkg/api/v1alpha2/conversion.go | 140 ++++++++ pkg/api/v1alpha2/defaults.go | 20 ++ pkg/api/v1alpha2/doc.go | 21 ++ pkg/api/v1alpha2/register.go | 58 ++++ pkg/api/v1alpha2/sort.go | 23 ++ pkg/api/v1alpha2/types.go | 70 ++++ pkg/api/v1alpha2/zz_generated.conversion.go | 309 ++++++++++++++++++ pkg/api/v1alpha2/zz_generated.deepcopy.go | 189 +++++++++++ pkg/api/v1alpha2/zz_generated.defaults.go | 33 ++ pkg/descheduler/descheduler.go | 38 ++- pkg/descheduler/descheduler_test.go | 14 +- pkg/descheduler/policyconfig.go | 134 +++++++- pkg/descheduler/policyconfig_test.go | 213 +++++++++++- pkg/descheduler/scheme/scheme.go | 28 +- pkg/descheduler/setupplugins.go | 30 +- .../plugins/defaultevictor/defaults.go | 35 +- .../plugins/defaultevictor/validation.go | 30 ++ .../defaultevictor/zz_generated.defaults.go | 5 - .../plugins/nodeutilization/defaults.go | 30 +- .../plugins/nodeutilization/validation.go | 7 +- .../nodeutilization/zz_generated.defaults.go | 10 - .../plugins/pluginregistry/pluginregistry.go | 57 ++++ pkg/framework/plugins/podlifetime/defaults.go | 19 +- .../plugins/podlifetime/validation.go | 5 +- .../podlifetime/zz_generated.defaults.go | 5 - .../plugins/removeduplicates/defaults.go | 11 +- .../plugins/removeduplicates/validation.go | 5 +- .../removeduplicates/zz_generated.defaults.go | 5 - .../plugins/removefailedpods/defaults.go | 27 +- .../plugins/removefailedpods/validation.go | 4 +- .../removefailedpods/zz_generated.defaults.go | 5 - .../defaults.go | 19 +- .../validation.go | 4 +- .../zz_generated.defaults.go | 7 - .../defaults.go | 11 +- .../validation.go | 4 +- .../zz_generated.defaults.go | 7 - .../defaults.go | 11 +- .../validation.go | 4 +- .../zz_generated.defaults.go | 7 - .../removepodsviolatingnodetaints/defaults.go | 19 +- .../validation.go | 4 +- .../zz_generated.defaults.go | 7 - .../defaults.go | 15 +- .../validation.go | 4 +- .../zz_generated.defaults.go | 7 - 48 files changed, 1521 insertions(+), 217 deletions(-) create mode 100644 pkg/api/conversion.go create mode 100644 pkg/api/v1alpha1/conversion.go create mode 100644 pkg/api/v1alpha2/conversion.go create mode 100644 pkg/api/v1alpha2/defaults.go create mode 100644 pkg/api/v1alpha2/doc.go create mode 100644 pkg/api/v1alpha2/register.go create mode 100644 pkg/api/v1alpha2/sort.go create mode 100644 pkg/api/v1alpha2/types.go create mode 100644 pkg/api/v1alpha2/zz_generated.conversion.go create mode 100644 pkg/api/v1alpha2/zz_generated.deepcopy.go create mode 100644 pkg/api/v1alpha2/zz_generated.defaults.go create mode 100644 pkg/framework/plugins/defaultevictor/validation.go create mode 100644 pkg/framework/plugins/pluginregistry/pluginregistry.go diff --git a/pkg/api/conversion.go b/pkg/api/conversion.go new file mode 100644 index 0000000000..5b4c7f57c3 --- /dev/null +++ b/pkg/api/conversion.go @@ -0,0 +1,14 @@ +/* +Copyright 2017 The Kubernetes Authors. +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package api diff --git a/pkg/api/v1alpha1/conversion.go b/pkg/api/v1alpha1/conversion.go new file mode 100644 index 0000000000..518334410a --- /dev/null +++ b/pkg/api/v1alpha1/conversion.go @@ -0,0 +1,14 @@ +/* +Copyright 2017 The Kubernetes Authors. +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha1 diff --git a/pkg/api/v1alpha2/conversion.go b/pkg/api/v1alpha2/conversion.go new file mode 100644 index 0000000000..7079a09d9f --- /dev/null +++ b/pkg/api/v1alpha2/conversion.go @@ -0,0 +1,140 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha2 + +import ( + "fmt" + "sync" + + // unsafe "unsafe" + + "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/plugins/defaultevictor" + "sigs.k8s.io/descheduler/pkg/framework/plugins/pluginregistry" + // "sigs.k8s.io/descheduler/pkg/framework/plugins/removepodshavingtoomanyrestarts" +) + +var ( + // pluginArgConversionScheme is a scheme with internal and v1beta2 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..6a2c675b5f --- /dev/null +++ b/pkg/api/v1alpha2/defaults.go @@ -0,0 +1,20 @@ +/* +Copyright 2017 The Kubernetes Authors. +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package 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..74cb54b432 --- /dev/null +++ b/pkg/api/v1alpha2/doc.go @@ -0,0 +1,21 @@ +/* +Copyright 2017 The Kubernetes Authors. +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// +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..ae6de6c4ac --- /dev/null +++ b/pkg/api/v1alpha2/register.go @@ -0,0 +1,58 @@ +/* +Copyright 2017 The Kubernetes Authors. +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package 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..5c31cbcaaa --- /dev/null +++ b/pkg/api/v1alpha2/sort.go @@ -0,0 +1,23 @@ +/* +Copyright 2017 The Kubernetes Authors. +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package 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..103e661108 --- /dev/null +++ b/pkg/api/v1alpha2/types.go @@ -0,0 +1,70 @@ +/* +Copyright 2017 The Kubernetes Authors. +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package 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"` +} + +// Namespaces carries a list of included/excluded namespaces +// for which a given plugin is applicable. +type Namespaces struct { + Include []string `json:"include"` + Exclude []string `json:"exclude"` +} diff --git a/pkg/api/v1alpha2/zz_generated.conversion.go b/pkg/api/v1alpha2/zz_generated.conversion.go new file mode 100644 index 0000000000..265ee25c37 --- /dev/null +++ b/pkg/api/v1alpha2/zz_generated.conversion.go @@ -0,0 +1,309 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +/* +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. +*/ + +// 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((*Namespaces)(nil), (*api.Namespaces)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha2_Namespaces_To_api_Namespaces(a.(*Namespaces), b.(*api.Namespaces), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*api.Namespaces)(nil), (*Namespaces)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_api_Namespaces_To_v1alpha2_Namespaces(a.(*api.Namespaces), b.(*Namespaces), scope) + }); err != nil { + return err + } + 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_Namespaces_To_api_Namespaces(in *Namespaces, out *api.Namespaces, s conversion.Scope) error { + out.Include = *(*[]string)(unsafe.Pointer(&in.Include)) + out.Exclude = *(*[]string)(unsafe.Pointer(&in.Exclude)) + return nil +} + +// Convert_v1alpha2_Namespaces_To_api_Namespaces is an autogenerated conversion function. +func Convert_v1alpha2_Namespaces_To_api_Namespaces(in *Namespaces, out *api.Namespaces, s conversion.Scope) error { + return autoConvert_v1alpha2_Namespaces_To_api_Namespaces(in, out, s) +} + +func autoConvert_api_Namespaces_To_v1alpha2_Namespaces(in *api.Namespaces, out *Namespaces, s conversion.Scope) error { + out.Include = *(*[]string)(unsafe.Pointer(&in.Include)) + out.Exclude = *(*[]string)(unsafe.Pointer(&in.Exclude)) + return nil +} + +// Convert_api_Namespaces_To_v1alpha2_Namespaces is an autogenerated conversion function. +func Convert_api_Namespaces_To_v1alpha2_Namespaces(in *api.Namespaces, out *Namespaces, s conversion.Scope) error { + return autoConvert_api_Namespaces_To_v1alpha2_Namespaces(in, out, s) +} + +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..805177f593 --- /dev/null +++ b/pkg/api/v1alpha2/zz_generated.deepcopy.go @@ -0,0 +1,189 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +/* +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. +*/ + +// 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 *Namespaces) DeepCopyInto(out *Namespaces) { + *out = *in + if in.Include != nil { + in, out := &in.Include, &out.Include + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.Exclude != nil { + in, out := &in.Exclude, &out.Exclude + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Namespaces. +func (in *Namespaces) DeepCopy() *Namespaces { + if in == nil { + return nil + } + out := new(Namespaces) + in.DeepCopyInto(out) + return out +} + +// 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..c65a60181f --- /dev/null +++ b/pkg/api/v1alpha2/zz_generated.defaults.go @@ -0,0 +1,33 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +/* +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. +*/ + +// 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/descheduler/descheduler.go b/pkg/descheduler/descheduler.go index 8611e5491f..a5323ee16c 100644 --- a/pkg/descheduler/descheduler.go +++ b/pkg/descheduler/descheduler.go @@ -45,7 +45,7 @@ import ( podutil "sigs.k8s.io/descheduler/pkg/descheduler/pod" "sigs.k8s.io/descheduler/pkg/framework" "sigs.k8s.io/descheduler/pkg/framework/plugins/defaultevictor" - "sigs.k8s.io/descheduler/pkg/framework/plugins/pluginbuilder" + "sigs.k8s.io/descheduler/pkg/framework/plugins/pluginregistry" "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 { + switch p := pg.(type) { + case framework.DeschedulePlugin: + enabledDeschedulePlugins = append(enabledDeschedulePlugins, p) + } + return enabledDeschedulePlugins +} + +func includeBalance(enabledBalancePlugins []framework.BalancePlugin, pg framework.Plugin) []framework.BalancePlugin { + switch p := pg.(type) { + case framework.BalancePlugin: + enabledBalancePlugins = append(enabledBalancePlugins, p) + } + 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..052b6e3394 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/plugins/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 := 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 := 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..d89ef4c885 100644 --- a/pkg/descheduler/policyconfig.go +++ b/pkg/descheduler/policyconfig.go @@ -27,14 +27,15 @@ 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/plugins/defaultevictor" - "sigs.k8s.io/descheduler/pkg/framework/plugins/pluginbuilder" + "sigs.k8s.io/descheduler/pkg/framework/plugins/pluginregistry" "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,26 +46,125 @@ func LoadPolicyConfig(policyConfigFile string, client clientset.Interface, regis return nil, fmt.Errorf("failed to read policy config file %q: %+v", policyConfigFile, err) } + internalPolicy, err := decode(policyConfigFile, policy, client, registry) + if err != nil { + return nil, err + } + return internalPolicy, nil +} + +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) + 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) + } } - - // Build profiles - internalPolicy, err := V1alpha1ToInternal(client, versionedPolicy, registry) - if err != nil { - return nil, fmt.Errorf("failed converting versioned policy to internal policy version: %v", err) + if versionedPolicy.APIVersion == "descheduler/v1alpha1" { + // Build profiles + internalPolicy, err = V1alpha1ToInternal(client, versionedPolicy, registry) + if err != nil { + return nil, fmt.Errorf("failed converting versioned policy to internal policy version: %v", err) + } + err = validateDeschedulerConfiguration(*internalPolicy, registry) + if err != nil { + return nil, 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) + } + err = validateDeschedulerConfiguration(*internalPolicy, registry) + if err != nil { + return nil, err + } } + setDefaults(*internalPolicy, registry) + return internalPolicy, nil } +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 +} + +func setDefaultsPluginConfig(pluginConfig api.PluginConfig, registry pluginregistry.Registry) { + if _, ok := registry[pluginConfig.Name]; ok { + pluginUtilities := registry[pluginConfig.Name] + pluginUtilities.PluginArgDefaulter(pluginConfig.Args) + } +} + +func setDefaultEvictor(profile api.Profile) api.Profile { + if len(profile.Plugins.Evict.Enabled) == 0 { + profile.Plugins.Evict.Enabled = append(profile.Plugins.Evict.Enabled, defaultevictor.PluginName) + newPluginConfig := api.PluginConfig{ + Name: defaultevictor.PluginName, + Args: &defaultevictor.DefaultEvictorArgs{ + EvictLocalStoragePods: false, + EvictSystemCriticalPods: false, + IgnorePvcPods: false, + EvictFailedBarePods: false, + }, + } + if !hasPluginConfigsWithSameName(newPluginConfig, profile.PluginConfigs) { + profile.PluginConfigs = append(profile.PluginConfigs, newPluginConfig) + } + } + return profile +} + +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] + err := pluginUtilities.PluginArgValidator(pluginConfig.Args) + errorsInProfiles = setErrorsInProfiles(err, profile.Name, errorsInProfiles) + } + } + } + if errorsInProfiles != nil { + return errorsInProfiles + } + return nil +} + +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 errorsInProfiles +} + func V1alpha1ToInternal( client clientset.Interface, deschedulerPolicy *v1alpha1.DeschedulerPolicy, - registry pluginbuilder.Registry, + registry pluginregistry.Registry, ) (*api.DeschedulerPolicy, error) { var evictLocalStoragePods bool if deschedulerPolicy.EvictLocalStoragePods != nil { @@ -96,7 +196,7 @@ func V1alpha1ToInternal( // Build profiles for name, strategy := range deschedulerPolicy.Strategies { - if _, ok := pluginbuilder.PluginRegistry[string(name)]; ok { + if _, ok := pluginregistry.PluginRegistry[string(name)]; ok { if strategy.Enabled { params := strategy.Params if params == nil { @@ -108,12 +208,11 @@ func V1alpha1ToInternal( 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{ @@ -213,3 +312,12 @@ func checkDeschedule(profilePlugins api.Plugins, pluginInstance framework.Plugin } return profilePlugins } + +func hasPluginConfigsWithSameName(newPluginConfig api.PluginConfig, pluginConfigs []api.PluginConfig) bool { + for _, pluginConfig := range pluginConfigs { + if newPluginConfig.Name == pluginConfig.Name { + return true + } + } + return false +} diff --git a/pkg/descheduler/policyconfig_test.go b/pkg/descheduler/policyconfig_test.go index 26922fc05b..d142246fa1 100644 --- a/pkg/descheduler/policyconfig_test.go +++ b/pkg/descheduler/policyconfig_test.go @@ -27,7 +27,8 @@ import ( "sigs.k8s.io/descheduler/pkg/api/v1alpha1" "sigs.k8s.io/descheduler/pkg/framework/plugins/defaultevictor" "sigs.k8s.io/descheduler/pkg/framework/plugins/nodeutilization" - "sigs.k8s.io/descheduler/pkg/framework/plugins/pluginbuilder" + "sigs.k8s.io/descheduler/pkg/framework/plugins/pluginregistry" + "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 := 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,211 @@ 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) + } + }) + } +} 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..67b29770b5 100644 --- a/pkg/descheduler/setupplugins.go +++ b/pkg/descheduler/setupplugins.go @@ -19,7 +19,7 @@ package descheduler import ( "sigs.k8s.io/descheduler/pkg/framework/plugins/defaultevictor" "sigs.k8s.io/descheduler/pkg/framework/plugins/nodeutilization" - "sigs.k8s.io/descheduler/pkg/framework/plugins/pluginbuilder" + "sigs.k8s.io/descheduler/pkg/framework/plugins/pluginregistry" "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/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.defaults.go b/pkg/framework/plugins/defaultevictor/zz_generated.defaults.go index 6e662a5a97..feda310cb9 100644 --- a/pkg/framework/plugins/defaultevictor/zz_generated.defaults.go +++ b/pkg/framework/plugins/defaultevictor/zz_generated.defaults.go @@ -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.defaults.go b/pkg/framework/plugins/nodeutilization/zz_generated.defaults.go index ede106f47c..2cf088a7a2 100644 --- a/pkg/framework/plugins/nodeutilization/zz_generated.defaults.go +++ b/pkg/framework/plugins/nodeutilization/zz_generated.defaults.go @@ -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/pluginregistry/pluginregistry.go b/pkg/framework/plugins/pluginregistry/pluginregistry.go new file mode 100644 index 0000000000..a075f6f7fa --- /dev/null +++ b/pkg/framework/plugins/pluginregistry/pluginregistry.go @@ -0,0 +1,57 @@ +/* +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 pluginregistry + +import ( + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/klog/v2" + "sigs.k8s.io/descheduler/pkg/framework" +) + +var PluginRegistry Registry + +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 + PluginArgValidator PluginArgValidator + PluginArgDefaulter PluginArgDefaulter +} + +type PluginBuilder = func(args runtime.Object, handle framework.Handle) (framework.Plugin, error) + +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, pluginArgValidator PluginArgValidator, pluginArgDefaulter PluginArgDefaulter, registry Registry) { + if _, ok := registry[name]; ok { + klog.V(10).InfoS("Plugin already registered", "plugin", name) + } else { + registry[name] = PluginUtilities{ + PluginBuilder: builderFunc, + PluginArgInstance: exampleArg, + PluginArgValidator: pluginArgValidator, + PluginArgDefaulter: pluginArgDefaulter, + } + } +} 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.defaults.go b/pkg/framework/plugins/podlifetime/zz_generated.defaults.go index fc593d17d3..95493c61db 100644 --- a/pkg/framework/plugins/podlifetime/zz_generated.defaults.go +++ b/pkg/framework/plugins/podlifetime/zz_generated.defaults.go @@ -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.defaults.go b/pkg/framework/plugins/removeduplicates/zz_generated.defaults.go index 2ee3e64b74..bb16b3a7d4 100644 --- a/pkg/framework/plugins/removeduplicates/zz_generated.defaults.go +++ b/pkg/framework/plugins/removeduplicates/zz_generated.defaults.go @@ -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..9630ec34c0 100644 --- a/pkg/framework/plugins/removefailedpods/defaults.go +++ b/pkg/framework/plugins/removefailedpods/defaults.go @@ -23,23 +23,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 = nil } - 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.defaults.go b/pkg/framework/plugins/removefailedpods/zz_generated.defaults.go index 62c6d8052d..0aed1c8156 100644 --- a/pkg/framework/plugins/removefailedpods/zz_generated.defaults.go +++ b/pkg/framework/plugins/removefailedpods/zz_generated.defaults.go @@ -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.defaults.go b/pkg/framework/plugins/removepodshavingtoomanyrestarts/zz_generated.defaults.go index 7705a78a9d..64f2bacb3d 100644 --- a/pkg/framework/plugins/removepodshavingtoomanyrestarts/zz_generated.defaults.go +++ b/pkg/framework/plugins/removepodshavingtoomanyrestarts/zz_generated.defaults.go @@ -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.defaults.go b/pkg/framework/plugins/removepodsviolatinginterpodantiaffinity/zz_generated.defaults.go index 95c93e12df..4f791678b9 100644 --- a/pkg/framework/plugins/removepodsviolatinginterpodantiaffinity/zz_generated.defaults.go +++ b/pkg/framework/plugins/removepodsviolatinginterpodantiaffinity/zz_generated.defaults.go @@ -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.defaults.go b/pkg/framework/plugins/removepodsviolatingnodeaffinity/zz_generated.defaults.go index 610db082f9..80e8ad47a3 100644 --- a/pkg/framework/plugins/removepodsviolatingnodeaffinity/zz_generated.defaults.go +++ b/pkg/framework/plugins/removepodsviolatingnodeaffinity/zz_generated.defaults.go @@ -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.defaults.go b/pkg/framework/plugins/removepodsviolatingnodetaints/zz_generated.defaults.go index 0ea6f06be0..23982cd6af 100644 --- a/pkg/framework/plugins/removepodsviolatingnodetaints/zz_generated.defaults.go +++ b/pkg/framework/plugins/removepodsviolatingnodetaints/zz_generated.defaults.go @@ -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.defaults.go b/pkg/framework/plugins/removepodsviolatingtopologyspreadconstraint/zz_generated.defaults.go index 2659305b24..77b63425a0 100644 --- a/pkg/framework/plugins/removepodsviolatingtopologyspreadconstraint/zz_generated.defaults.go +++ b/pkg/framework/plugins/removepodsviolatingtopologyspreadconstraint/zz_generated.defaults.go @@ -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) -} From ef1c22366ab6bbcd7633e6069cd17ea09be4657a Mon Sep 17 00:00:00 2001 From: Lucas Severo Alves Date: Fri, 2 Dec 2022 17:23:12 +0100 Subject: [PATCH 02/13] test defaults, set our 1st explicit default --- pkg/descheduler/policyconfig.go | 4 +- pkg/descheduler/policyconfig_test.go | 91 +++++++++++++++++++ .../plugins/removefailedpods/defaults.go | 3 +- 3 files changed, 95 insertions(+), 3 deletions(-) diff --git a/pkg/descheduler/policyconfig.go b/pkg/descheduler/policyconfig.go index d89ef4c885..26c132d17d 100644 --- a/pkg/descheduler/policyconfig.go +++ b/pkg/descheduler/policyconfig.go @@ -96,13 +96,13 @@ func setDefaults(in api.DeschedulerPolicy, registry pluginregistry.Registry) *ap // 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) + setDefaultsPluginConfig(&pluginConfig, registry) } } return &in } -func setDefaultsPluginConfig(pluginConfig api.PluginConfig, registry pluginregistry.Registry) { +func setDefaultsPluginConfig(pluginConfig *api.PluginConfig, registry pluginregistry.Registry) { if _, ok := registry[pluginConfig.Name]; ok { pluginUtilities := registry[pluginConfig.Name] pluginUtilities.PluginArgDefaulter(pluginConfig.Args) diff --git a/pkg/descheduler/policyconfig_test.go b/pkg/descheduler/policyconfig_test.go index d142246fa1..eb5df87ba0 100644 --- a/pkg/descheduler/policyconfig_test.go +++ b/pkg/descheduler/policyconfig_test.go @@ -908,3 +908,94 @@ func TestValidateDeschedulerConfiguration(t *testing.T) { }) } } + +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/framework/plugins/removefailedpods/defaults.go b/pkg/framework/plugins/removefailedpods/defaults.go index 9630ec34c0..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 { @@ -35,7 +36,7 @@ func SetDefaults_RemoveFailedPodsArgs(obj runtime.Object) { args.ExcludeOwnerKinds = nil } if args.MinPodLifetimeSeconds == nil { - args.MinPodLifetimeSeconds = nil + args.MinPodLifetimeSeconds = utilpointer.Uint(3600) } if args.Reasons == nil { args.Reasons = nil From 5abb6b0953c5345ff219e4f2635bf8935ca86048 Mon Sep 17 00:00:00 2001 From: Lucas Severo Alves Date: Wed, 7 Dec 2022 17:30:25 +0100 Subject: [PATCH 03/13] fix typos and dates --- pkg/api/v1alpha1/conversion.go | 5 ++++- pkg/api/v1alpha2/conversion.go | 4 ++-- pkg/api/v1alpha2/defaults.go | 5 ++++- pkg/api/v1alpha2/doc.go | 5 ++++- pkg/api/v1alpha2/register.go | 5 ++++- pkg/api/v1alpha2/sort.go | 5 ++++- pkg/api/v1alpha2/types.go | 5 ++++- 7 files changed, 26 insertions(+), 8 deletions(-) diff --git a/pkg/api/v1alpha1/conversion.go b/pkg/api/v1alpha1/conversion.go index 518334410a..a3edeb12b7 100644 --- a/pkg/api/v1alpha1/conversion.go +++ b/pkg/api/v1alpha1/conversion.go @@ -1,9 +1,12 @@ /* -Copyright 2017 The Kubernetes Authors. +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. diff --git a/pkg/api/v1alpha2/conversion.go b/pkg/api/v1alpha2/conversion.go index 7079a09d9f..28280f2b33 100644 --- a/pkg/api/v1alpha2/conversion.go +++ b/pkg/api/v1alpha2/conversion.go @@ -1,5 +1,5 @@ /* -Copyright 2017 The Kubernetes Authors. +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. @@ -34,7 +34,7 @@ import ( ) var ( - // pluginArgConversionScheme is a scheme with internal and v1beta2 registered, + // pluginArgConversionScheme is a scheme with internal and v1alpha2 registered, // used for defaulting/converting typed PluginConfig Args. // Access via getPluginArgConversionScheme() pluginArgConversionScheme *runtime.Scheme diff --git a/pkg/api/v1alpha2/defaults.go b/pkg/api/v1alpha2/defaults.go index 6a2c675b5f..3532f2ae60 100644 --- a/pkg/api/v1alpha2/defaults.go +++ b/pkg/api/v1alpha2/defaults.go @@ -1,9 +1,12 @@ /* -Copyright 2017 The Kubernetes Authors. +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. diff --git a/pkg/api/v1alpha2/doc.go b/pkg/api/v1alpha2/doc.go index 74cb54b432..7583871739 100644 --- a/pkg/api/v1alpha2/doc.go +++ b/pkg/api/v1alpha2/doc.go @@ -1,9 +1,12 @@ /* -Copyright 2017 The Kubernetes Authors. +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. diff --git a/pkg/api/v1alpha2/register.go b/pkg/api/v1alpha2/register.go index ae6de6c4ac..2126bd816a 100644 --- a/pkg/api/v1alpha2/register.go +++ b/pkg/api/v1alpha2/register.go @@ -1,9 +1,12 @@ /* -Copyright 2017 The Kubernetes Authors. +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. diff --git a/pkg/api/v1alpha2/sort.go b/pkg/api/v1alpha2/sort.go index 5c31cbcaaa..c200d83a1a 100644 --- a/pkg/api/v1alpha2/sort.go +++ b/pkg/api/v1alpha2/sort.go @@ -1,9 +1,12 @@ /* -Copyright 2017 The Kubernetes Authors. +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. diff --git a/pkg/api/v1alpha2/types.go b/pkg/api/v1alpha2/types.go index 103e661108..c6ab07a417 100644 --- a/pkg/api/v1alpha2/types.go +++ b/pkg/api/v1alpha2/types.go @@ -1,9 +1,12 @@ /* -Copyright 2017 The Kubernetes Authors. +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. From 7802034e44ad910aafd1e00fca6fd195005b7468 Mon Sep 17 00:00:00 2001 From: Lucas Severo Alves Date: Wed, 7 Dec 2022 17:35:04 +0100 Subject: [PATCH 04/13] move pluginregistry to its own dir --- pkg/api/v1alpha2/conversion.go | 6 +----- pkg/descheduler/descheduler.go | 2 +- pkg/descheduler/descheduler_test.go | 2 +- pkg/descheduler/policyconfig.go | 2 +- pkg/descheduler/policyconfig_test.go | 2 +- pkg/descheduler/setupplugins.go | 2 +- .../{plugins => }/pluginregistry/pluginregistry.go | 0 7 files changed, 6 insertions(+), 10 deletions(-) rename pkg/framework/{plugins => }/pluginregistry/pluginregistry.go (100%) diff --git a/pkg/api/v1alpha2/conversion.go b/pkg/api/v1alpha2/conversion.go index 28280f2b33..3137a95d55 100644 --- a/pkg/api/v1alpha2/conversion.go +++ b/pkg/api/v1alpha2/conversion.go @@ -20,17 +20,13 @@ import ( "fmt" "sync" - // unsafe "unsafe" - "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/plugins/defaultevictor" - "sigs.k8s.io/descheduler/pkg/framework/plugins/pluginregistry" - // "sigs.k8s.io/descheduler/pkg/framework/plugins/removepodshavingtoomanyrestarts" + "sigs.k8s.io/descheduler/pkg/framework/pluginregistry" ) var ( diff --git a/pkg/descheduler/descheduler.go b/pkg/descheduler/descheduler.go index a5323ee16c..7c492b6386 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/pluginregistry" "sigs.k8s.io/descheduler/pkg/utils" ) diff --git a/pkg/descheduler/descheduler_test.go b/pkg/descheduler/descheduler_test.go index 052b6e3394..ee3a206f27 100644 --- a/pkg/descheduler/descheduler_test.go +++ b/pkg/descheduler/descheduler_test.go @@ -15,7 +15,7 @@ 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/pluginregistry" + "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" diff --git a/pkg/descheduler/policyconfig.go b/pkg/descheduler/policyconfig.go index 26c132d17d..8e25b79460 100644 --- a/pkg/descheduler/policyconfig.go +++ b/pkg/descheduler/policyconfig.go @@ -30,8 +30,8 @@ import ( "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/pluginregistry" "sigs.k8s.io/descheduler/pkg/utils" ) diff --git a/pkg/descheduler/policyconfig_test.go b/pkg/descheduler/policyconfig_test.go index eb5df87ba0..c4fb2672c4 100644 --- a/pkg/descheduler/policyconfig_test.go +++ b/pkg/descheduler/policyconfig_test.go @@ -25,9 +25,9 @@ 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/pluginregistry" "sigs.k8s.io/descheduler/pkg/framework/plugins/podlifetime" "sigs.k8s.io/descheduler/pkg/framework/plugins/removeduplicates" "sigs.k8s.io/descheduler/pkg/framework/plugins/removefailedpods" diff --git a/pkg/descheduler/setupplugins.go b/pkg/descheduler/setupplugins.go index 67b29770b5..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/pluginregistry" "sigs.k8s.io/descheduler/pkg/framework/plugins/podlifetime" "sigs.k8s.io/descheduler/pkg/framework/plugins/removeduplicates" "sigs.k8s.io/descheduler/pkg/framework/plugins/removefailedpods" diff --git a/pkg/framework/plugins/pluginregistry/pluginregistry.go b/pkg/framework/pluginregistry/pluginregistry.go similarity index 100% rename from pkg/framework/plugins/pluginregistry/pluginregistry.go rename to pkg/framework/pluginregistry/pluginregistry.go From e544e0aa87007b8285b4acafabd8a631cf18bbef Mon Sep 17 00:00:00 2001 From: Lucas Severo Alves Date: Wed, 7 Dec 2022 17:41:34 +0100 Subject: [PATCH 05/13] remove unused v1alpha2.Namespace type --- pkg/api/v1alpha2/types.go | 7 ----- pkg/api/v1alpha2/zz_generated.conversion.go | 32 --------------------- pkg/api/v1alpha2/zz_generated.deepcopy.go | 26 ----------------- 3 files changed, 65 deletions(-) diff --git a/pkg/api/v1alpha2/types.go b/pkg/api/v1alpha2/types.go index c6ab07a417..c19f8cca50 100644 --- a/pkg/api/v1alpha2/types.go +++ b/pkg/api/v1alpha2/types.go @@ -64,10 +64,3 @@ type PluginSet struct { Enabled []string `json:"enabled"` Disabled []string `json:"disabled"` } - -// Namespaces carries a list of included/excluded namespaces -// for which a given plugin is applicable. -type Namespaces struct { - Include []string `json:"include"` - Exclude []string `json:"exclude"` -} diff --git a/pkg/api/v1alpha2/zz_generated.conversion.go b/pkg/api/v1alpha2/zz_generated.conversion.go index 265ee25c37..e073c3ce61 100644 --- a/pkg/api/v1alpha2/zz_generated.conversion.go +++ b/pkg/api/v1alpha2/zz_generated.conversion.go @@ -36,16 +36,6 @@ func init() { // RegisterConversions adds conversion functions to the given scheme. // Public to allow building arbitrary schemes. func RegisterConversions(s *runtime.Scheme) error { - if err := s.AddGeneratedConversionFunc((*Namespaces)(nil), (*api.Namespaces)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha2_Namespaces_To_api_Namespaces(a.(*Namespaces), b.(*api.Namespaces), scope) - }); err != nil { - return err - } - if err := s.AddGeneratedConversionFunc((*api.Namespaces)(nil), (*Namespaces)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_api_Namespaces_To_v1alpha2_Namespaces(a.(*api.Namespaces), b.(*Namespaces), scope) - }); err != nil { - return err - } 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 { @@ -135,28 +125,6 @@ func autoConvert_api_DeschedulerPolicy_To_v1alpha2_DeschedulerPolicy(in *api.Des return nil } -func autoConvert_v1alpha2_Namespaces_To_api_Namespaces(in *Namespaces, out *api.Namespaces, s conversion.Scope) error { - out.Include = *(*[]string)(unsafe.Pointer(&in.Include)) - out.Exclude = *(*[]string)(unsafe.Pointer(&in.Exclude)) - return nil -} - -// Convert_v1alpha2_Namespaces_To_api_Namespaces is an autogenerated conversion function. -func Convert_v1alpha2_Namespaces_To_api_Namespaces(in *Namespaces, out *api.Namespaces, s conversion.Scope) error { - return autoConvert_v1alpha2_Namespaces_To_api_Namespaces(in, out, s) -} - -func autoConvert_api_Namespaces_To_v1alpha2_Namespaces(in *api.Namespaces, out *Namespaces, s conversion.Scope) error { - out.Include = *(*[]string)(unsafe.Pointer(&in.Include)) - out.Exclude = *(*[]string)(unsafe.Pointer(&in.Exclude)) - return nil -} - -// Convert_api_Namespaces_To_v1alpha2_Namespaces is an autogenerated conversion function. -func Convert_api_Namespaces_To_v1alpha2_Namespaces(in *api.Namespaces, out *Namespaces, s conversion.Scope) error { - return autoConvert_api_Namespaces_To_v1alpha2_Namespaces(in, out, s) -} - 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 { diff --git a/pkg/api/v1alpha2/zz_generated.deepcopy.go b/pkg/api/v1alpha2/zz_generated.deepcopy.go index 805177f593..78344b5579 100644 --- a/pkg/api/v1alpha2/zz_generated.deepcopy.go +++ b/pkg/api/v1alpha2/zz_generated.deepcopy.go @@ -72,32 +72,6 @@ func (in *DeschedulerPolicy) DeepCopyObject() runtime.Object { return nil } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Namespaces) DeepCopyInto(out *Namespaces) { - *out = *in - if in.Include != nil { - in, out := &in.Include, &out.Include - *out = make([]string, len(*in)) - copy(*out, *in) - } - if in.Exclude != nil { - in, out := &in.Exclude, &out.Exclude - *out = make([]string, len(*in)) - copy(*out, *in) - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Namespaces. -func (in *Namespaces) DeepCopy() *Namespaces { - if in == nil { - return nil - } - out := new(Namespaces) - in.DeepCopyInto(out) - return out -} - // 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 From 33f81b6136842345c4ceef16f12de8008bae9c1a Mon Sep 17 00:00:00 2001 From: Lucas Severo Alves Date: Wed, 7 Dec 2022 17:46:54 +0100 Subject: [PATCH 06/13] move migration code folders, remove switch --- pkg/api/conversion.go | 5 +- pkg/api/v1alpha1/conversion.go | 227 ++++++++++++++++++ .../v1alpha1/strategymigration.go} | 40 +-- .../v1alpha1/strategymigration_test.go} | 225 +++++++++-------- pkg/descheduler/descheduler.go | 12 +- pkg/descheduler/descheduler_test.go | 4 +- pkg/descheduler/policyconfig.go | 157 +----------- pkg/descheduler/policyconfig_test.go | 2 +- .../plugins/pluginbuilder/pluginbuilder.go | 48 ---- 9 files changed, 373 insertions(+), 347 deletions(-) rename pkg/{descheduler/strategy_migration.go => api/v1alpha1/strategymigration.go} (85%) rename pkg/{descheduler/strategy_migration_test.go => api/v1alpha1/strategymigration_test.go} (79%) delete mode 100644 pkg/framework/plugins/pluginbuilder/pluginbuilder.go diff --git a/pkg/api/conversion.go b/pkg/api/conversion.go index 5b4c7f57c3..cdaaf21686 100644 --- a/pkg/api/conversion.go +++ b/pkg/api/conversion.go @@ -1,9 +1,12 @@ /* -Copyright 2017 The Kubernetes Authors. +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. diff --git a/pkg/api/v1alpha1/conversion.go b/pkg/api/v1alpha1/conversion.go index a3edeb12b7..d426d8e177 100644 --- a/pkg/api/v1alpha1/conversion.go +++ b/pkg/api/v1alpha1/conversion.go @@ -15,3 +15,230 @@ 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).InfoS("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).InfoS("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..e9b8b19834 100644 --- a/pkg/descheduler/strategy_migration.go +++ b/pkg/api/v1alpha1/strategymigration.go @@ -14,14 +14,14 @@ See the License for the specific language governing permissions and limitations under the License. */ -package descheduler +// This is a temporary package that will only exist while we have both v1alpha1 and v1alpha2 +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 +37,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 +54,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 +76,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 +91,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 +105,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 +125,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 +154,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 +170,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 +185,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 +203,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 +226,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 +241,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/descheduler/descheduler.go b/pkg/descheduler/descheduler.go index 7c492b6386..c83ba1f302 100644 --- a/pkg/descheduler/descheduler.go +++ b/pkg/descheduler/descheduler.go @@ -417,17 +417,17 @@ func includeProfilePluginsByType(enabledDeschedulePlugins []framework.Deschedule } func includeDeschedule(enabledDeschedulePlugins []framework.DeschedulePlugin, pg framework.Plugin) []framework.DeschedulePlugin { - switch p := pg.(type) { - case framework.DeschedulePlugin: - enabledDeschedulePlugins = append(enabledDeschedulePlugins, p) + _, ok := pg.(framework.DeschedulePlugin) + if ok { + enabledDeschedulePlugins = append(enabledDeschedulePlugins, pg.(framework.DeschedulePlugin)) } return enabledDeschedulePlugins } func includeBalance(enabledBalancePlugins []framework.BalancePlugin, pg framework.Plugin) []framework.BalancePlugin { - switch p := pg.(type) { - case framework.BalancePlugin: - enabledBalancePlugins = append(enabledBalancePlugins, p) + _, ok := pg.(framework.BalancePlugin) + if ok { + enabledBalancePlugins = append(enabledBalancePlugins, pg.(framework.BalancePlugin)) } return enabledBalancePlugins } diff --git a/pkg/descheduler/descheduler_test.go b/pkg/descheduler/descheduler_test.go index ee3a206f27..fa74823082 100644 --- a/pkg/descheduler/descheduler_test.go +++ b/pkg/descheduler/descheduler_test.go @@ -74,7 +74,7 @@ func TestTaintsUpdated(t *testing.T) { var evictedPods []string client.PrependReactor("create", "pods", podEvictionReactionFuc(&evictedPods)) - internalDeschedulerPolicy, err := V1alpha1ToInternal(client, dp, pluginregistry.PluginRegistry) + internalDeschedulerPolicy, err := v1alpha1.V1alpha1ToInternal(client, dp, pluginregistry.PluginRegistry) if err != nil { t.Fatalf("Unable to convert v1alpha1 to v1alpha2: %v", err) } @@ -136,7 +136,7 @@ func TestDuplicate(t *testing.T) { var evictedPods []string client.PrependReactor("create", "pods", podEvictionReactionFuc(&evictedPods)) - internalDeschedulerPolicy, err := V1alpha1ToInternal(client, dp, pluginregistry.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 8e25b79460..3c6ed17ecf 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" @@ -29,10 +28,8 @@ import ( "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/utils" ) func LoadPolicyConfig(policyConfigFile string, client clientset.Interface, registry pluginregistry.Registry) (*api.DeschedulerPolicy, error) { @@ -68,7 +65,7 @@ func decode(policyConfigFile string, policy []byte, client clientset.Interface, } if versionedPolicy.APIVersion == "descheduler/v1alpha1" { // Build profiles - internalPolicy, err = V1alpha1ToInternal(client, versionedPolicy, registry) + internalPolicy, err = v1alpha1.V1alpha1ToInternal(client, versionedPolicy, registry) if err != nil { return nil, fmt.Errorf("failed converting versioned policy to internal policy version: %v", err) } @@ -161,158 +158,6 @@ func setErrorsInProfiles(err error, profileName string, errorsInProfiles error) return errorsInProfiles } -func V1alpha1ToInternal( - client clientset.Interface, - deschedulerPolicy *v1alpha1.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).InfoS("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).InfoS("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 = &v1alpha1.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 { - switch p := pluginInstance.(type) { - case framework.BalancePlugin: - klog.V(3).Info("converting Balance plugin: %s", p.Name()) - profilePlugins.Balance.Enabled = []string{pluginConfig.Name} - } - return profilePlugins -} - -func checkDeschedule(profilePlugins api.Plugins, pluginInstance framework.Plugin, pluginConfig *api.PluginConfig) api.Plugins { - switch p := pluginInstance.(type) { - case framework.DeschedulePlugin: - klog.V(3).Info("converting Deschedule plugin: %s", p.Name()) - profilePlugins.Deschedule.Enabled = []string{pluginConfig.Name} - } - return profilePlugins -} - func hasPluginConfigsWithSameName(newPluginConfig api.PluginConfig, pluginConfigs []api.PluginConfig) bool { for _, pluginConfig := range pluginConfigs { if newPluginConfig.Name == pluginConfig.Name { diff --git a/pkg/descheduler/policyconfig_test.go b/pkg/descheduler/policyconfig_test.go index c4fb2672c4..719541b317 100644 --- a/pkg/descheduler/policyconfig_test.go +++ b/pkg/descheduler/policyconfig_test.go @@ -683,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, pluginregistry.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()) diff --git a/pkg/framework/plugins/pluginbuilder/pluginbuilder.go b/pkg/framework/plugins/pluginbuilder/pluginbuilder.go deleted file mode 100644 index d7971f462b..0000000000 --- a/pkg/framework/plugins/pluginbuilder/pluginbuilder.go +++ /dev/null @@ -1,48 +0,0 @@ -/* -Copyright 2022 The Kubernetes Authors. -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package pluginbuilder - -import ( - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/klog/v2" - "sigs.k8s.io/descheduler/pkg/framework" -) - -var PluginRegistry Registry - -type PluginBuilderAndArgsInstance struct { - PluginBuilder PluginBuilder - // Just an example instance of this PluginArg so we can avoid having - // to deal with reflect Types - PluginArgInstance runtime.Object -} - -type PluginBuilder = func(args runtime.Object, handle framework.Handle) (framework.Plugin, error) - -type Registry = map[string]PluginBuilderAndArgsInstance - -func NewRegistry() Registry { - return Registry{} -} - -func Register(name string, builderFunc PluginBuilder, exampleArg runtime.Object, registry Registry) { - if _, ok := registry[name]; ok { - klog.V(10).InfoS("Plugin already registered", "plugin", name) - } else { - registry[name] = PluginBuilderAndArgsInstance{ - PluginBuilder: builderFunc, - PluginArgInstance: exampleArg, - } - } -} From 9e974114fff6ab4c6148a2d2d957fe9435270ec8 Mon Sep 17 00:00:00 2001 From: Lucas Severo Alves Date: Wed, 7 Dec 2022 17:51:25 +0100 Subject: [PATCH 07/13] validate internalPolicy a single time --- pkg/api/v1alpha1/strategymigration.go | 1 - pkg/descheduler/policyconfig.go | 13 +++++-------- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/pkg/api/v1alpha1/strategymigration.go b/pkg/api/v1alpha1/strategymigration.go index e9b8b19834..36865c2265 100644 --- a/pkg/api/v1alpha1/strategymigration.go +++ b/pkg/api/v1alpha1/strategymigration.go @@ -14,7 +14,6 @@ See the License for the specific language governing permissions and limitations under the License. */ -// This is a temporary package that will only exist while we have both v1alpha1 and v1alpha2 package v1alpha1 import ( diff --git a/pkg/descheduler/policyconfig.go b/pkg/descheduler/policyconfig.go index 3c6ed17ecf..2b202e9a77 100644 --- a/pkg/descheduler/policyconfig.go +++ b/pkg/descheduler/policyconfig.go @@ -69,18 +69,15 @@ func decode(policyConfigFile string, policy []byte, client clientset.Interface, if err != nil { return nil, fmt.Errorf("failed converting versioned policy to internal policy version: %v", err) } - err = validateDeschedulerConfiguration(*internalPolicy, registry) - if err != nil { - return nil, 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) } - err = validateDeschedulerConfiguration(*internalPolicy, registry) - if err != nil { - return nil, err - } + } + + err = validateDeschedulerConfiguration(*internalPolicy, registry) + if err != nil { + return nil, err } setDefaults(*internalPolicy, registry) From da590c0e37ff02393ac9af25f525a937ed5de7b2 Mon Sep 17 00:00:00 2001 From: Lucas Severo Alves Date: Thu, 5 Jan 2023 16:05:35 +0100 Subject: [PATCH 08/13] remove structured logs --- pkg/api/v1alpha1/conversion.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/api/v1alpha1/conversion.go b/pkg/api/v1alpha1/conversion.go index d426d8e177..298fddef6a 100644 --- a/pkg/api/v1alpha1/conversion.go +++ b/pkg/api/v1alpha1/conversion.go @@ -105,7 +105,7 @@ func V1alpha1ToInternal( 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.") + klog.V(1).Info("Warning: EvictFailedBarePods is set to True. This could cause eviction of pods without ownerReferences.") } } @@ -113,7 +113,7 @@ func V1alpha1ToInternal( 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.") + klog.V(1).Info("Warning: EvictSystemCriticalPods is set to True. This could cause eviction of Kubernetes system pods.") } } From a626085605b24191280177bff51b5c29952ce218 Mon Sep 17 00:00:00 2001 From: Lucas Severo Alves Date: Thu, 5 Jan 2023 16:20:51 +0100 Subject: [PATCH 09/13] simplify return --- pkg/descheduler/policyconfig.go | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/pkg/descheduler/policyconfig.go b/pkg/descheduler/policyconfig.go index 2b202e9a77..165ad6c4f6 100644 --- a/pkg/descheduler/policyconfig.go +++ b/pkg/descheduler/policyconfig.go @@ -43,11 +43,7 @@ func LoadPolicyConfig(policyConfigFile string, client clientset.Interface, regis return nil, fmt.Errorf("failed to read policy config file %q: %+v", policyConfigFile, err) } - internalPolicy, err := decode(policyConfigFile, policy, client, registry) - if err != nil { - return nil, err - } - return internalPolicy, nil + return decode(policyConfigFile, policy, client, registry) } func decode(policyConfigFile string, policy []byte, client clientset.Interface, registry pluginregistry.Registry) (*api.DeschedulerPolicy, error) { From e770f67bd2d16685ef6cf6ca9f47b8fe4bf8d494 Mon Sep 17 00:00:00 2001 From: Lucas Severo Alves Date: Thu, 5 Jan 2023 16:39:09 +0100 Subject: [PATCH 10/13] check for nil methods --- pkg/descheduler/policyconfig.go | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/pkg/descheduler/policyconfig.go b/pkg/descheduler/policyconfig.go index 165ad6c4f6..d8a1ab5de7 100644 --- a/pkg/descheduler/policyconfig.go +++ b/pkg/descheduler/policyconfig.go @@ -95,7 +95,9 @@ func setDefaults(in api.DeschedulerPolicy, registry pluginregistry.Registry) *ap func setDefaultsPluginConfig(pluginConfig *api.PluginConfig, registry pluginregistry.Registry) { if _, ok := registry[pluginConfig.Name]; ok { pluginUtilities := registry[pluginConfig.Name] - pluginUtilities.PluginArgDefaulter(pluginConfig.Args) + if pluginUtilities.PluginArgDefaulter != nil { + pluginUtilities.PluginArgDefaulter(pluginConfig.Args) + } } } @@ -129,8 +131,10 @@ func validateDeschedulerConfiguration(in api.DeschedulerPolicy, registry pluginr for _, pluginConfig := range profile.PluginConfigs { if _, ok := registry[pluginConfig.Name]; ok { pluginUtilities := registry[pluginConfig.Name] - err := pluginUtilities.PluginArgValidator(pluginConfig.Args) - errorsInProfiles = setErrorsInProfiles(err, profile.Name, errorsInProfiles) + if pluginUtilities.PluginArgValidator != nil { + err := pluginUtilities.PluginArgValidator(pluginConfig.Args) + errorsInProfiles = setErrorsInProfiles(err, profile.Name, errorsInProfiles) + } } } } From 0a45b0a284972a115d3e9b2b1b9feb5200219cc4 Mon Sep 17 00:00:00 2001 From: Lucas Severo Alves Date: Thu, 5 Jan 2023 16:41:49 +0100 Subject: [PATCH 11/13] properly check before adding default evictor --- pkg/api/v1alpha1/zz_generated.deepcopy.go | 2 +- pkg/api/v1alpha1/zz_generated.defaults.go | 2 +- pkg/api/v1alpha2/zz_generated.conversion.go | 2 +- pkg/api/v1alpha2/zz_generated.deepcopy.go | 2 +- pkg/api/v1alpha2/zz_generated.defaults.go | 2 +- pkg/api/zz_generated.deepcopy.go | 2 +- .../v1alpha1/zz_generated.conversion.go | 2 +- .../v1alpha1/zz_generated.deepcopy.go | 2 +- .../v1alpha1/zz_generated.defaults.go | 2 +- .../componentconfig/zz_generated.deepcopy.go | 2 +- pkg/descheduler/policyconfig.go | 24 +++++++++---------- .../defaultevictor/zz_generated.deepcopy.go | 2 +- .../defaultevictor/zz_generated.defaults.go | 2 +- .../nodeutilization/zz_generated.deepcopy.go | 2 +- .../nodeutilization/zz_generated.defaults.go | 2 +- .../podlifetime/zz_generated.deepcopy.go | 2 +- .../podlifetime/zz_generated.defaults.go | 2 +- .../removeduplicates/zz_generated.deepcopy.go | 2 +- .../removeduplicates/zz_generated.defaults.go | 2 +- .../removefailedpods/zz_generated.deepcopy.go | 2 +- .../removefailedpods/zz_generated.defaults.go | 2 +- .../zz_generated.deepcopy.go | 2 +- .../zz_generated.defaults.go | 2 +- .../zz_generated.deepcopy.go | 2 +- .../zz_generated.defaults.go | 2 +- .../zz_generated.deepcopy.go | 2 +- .../zz_generated.defaults.go | 2 +- .../zz_generated.deepcopy.go | 2 +- .../zz_generated.defaults.go | 2 +- .../zz_generated.deepcopy.go | 2 +- .../zz_generated.defaults.go | 2 +- 31 files changed, 41 insertions(+), 43 deletions(-) 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/zz_generated.conversion.go b/pkg/api/v1alpha2/zz_generated.conversion.go index e073c3ce61..0852ba0e37 100644 --- a/pkg/api/v1alpha2/zz_generated.conversion.go +++ b/pkg/api/v1alpha2/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/api/v1alpha2/zz_generated.deepcopy.go b/pkg/api/v1alpha2/zz_generated.deepcopy.go index 78344b5579..63f375381a 100644 --- a/pkg/api/v1alpha2/zz_generated.deepcopy.go +++ b/pkg/api/v1alpha2/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/v1alpha2/zz_generated.defaults.go b/pkg/api/v1alpha2/zz_generated.defaults.go index c65a60181f..eb8c39049c 100644 --- a/pkg/api/v1alpha2/zz_generated.defaults.go +++ b/pkg/api/v1alpha2/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/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/policyconfig.go b/pkg/descheduler/policyconfig.go index d8a1ab5de7..50be770648 100644 --- a/pkg/descheduler/policyconfig.go +++ b/pkg/descheduler/policyconfig.go @@ -102,20 +102,18 @@ func setDefaultsPluginConfig(pluginConfig *api.PluginConfig, registry pluginregi } func setDefaultEvictor(profile api.Profile) api.Profile { - if len(profile.Plugins.Evict.Enabled) == 0 { + 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) - newPluginConfig := api.PluginConfig{ - Name: defaultevictor.PluginName, - Args: &defaultevictor.DefaultEvictorArgs{ - EvictLocalStoragePods: false, - EvictSystemCriticalPods: false, - IgnorePvcPods: false, - EvictFailedBarePods: false, - }, - } - if !hasPluginConfigsWithSameName(newPluginConfig, profile.PluginConfigs) { - profile.PluginConfigs = append(profile.PluginConfigs, newPluginConfig) - } + profile.PluginConfigs = append(profile.PluginConfigs, newPluginConfig) } return profile } 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 feda310cb9..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. 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 2cf088a7a2..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. 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 95493c61db..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. 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 bb16b3a7d4..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. 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 0aed1c8156..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. 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 64f2bacb3d..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. 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 4f791678b9..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. 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 80e8ad47a3..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. 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 23982cd6af..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. 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 77b63425a0..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. From eec534af614b2dee0a1406e612770a85918c60eb Mon Sep 17 00:00:00 2001 From: Lucas Severo Alves Date: Tue, 17 Jan 2023 16:46:55 +0100 Subject: [PATCH 12/13] add TODO comment --- pkg/descheduler/policyconfig.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pkg/descheduler/policyconfig.go b/pkg/descheduler/policyconfig.go index 50be770648..a35909609d 100644 --- a/pkg/descheduler/policyconfig.go +++ b/pkg/descheduler/policyconfig.go @@ -53,6 +53,13 @@ func decode(policyConfigFile string, policy []byte, client clientset.Interface, decoder := scheme.Codecs.UniversalDecoder(v1alpha1.SchemeGroupVersion, v1alpha2.SchemeGroupVersion, api.SchemeGroupVersion) if err := runtime.DecodeInto(decoder, policy, versionedPolicy); err != nil { + // 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 { From e13f3fe2301ef8920966ca1d12dd21858a7d5279 Mon Sep 17 00:00:00 2001 From: Lucas Severo Alves Date: Tue, 17 Jan 2023 16:54:13 +0100 Subject: [PATCH 13/13] bump copyright year --- pkg/api/conversion.go | 2 +- pkg/api/v1alpha1/conversion.go | 2 +- pkg/api/v1alpha1/strategymigration.go | 2 +- pkg/api/v1alpha2/conversion.go | 2 +- pkg/api/v1alpha2/defaults.go | 2 +- pkg/api/v1alpha2/doc.go | 2 +- pkg/api/v1alpha2/register.go | 2 +- pkg/api/v1alpha2/sort.go | 2 +- pkg/api/v1alpha2/types.go | 2 +- pkg/framework/pluginregistry/pluginregistry.go | 5 ++++- 10 files changed, 13 insertions(+), 10 deletions(-) diff --git a/pkg/api/conversion.go b/pkg/api/conversion.go index cdaaf21686..0f4f59e71b 100644 --- a/pkg/api/conversion.go +++ b/pkg/api/conversion.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. diff --git a/pkg/api/v1alpha1/conversion.go b/pkg/api/v1alpha1/conversion.go index 298fddef6a..a805e3b9b6 100644 --- a/pkg/api/v1alpha1/conversion.go +++ b/pkg/api/v1alpha1/conversion.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. diff --git a/pkg/api/v1alpha1/strategymigration.go b/pkg/api/v1alpha1/strategymigration.go index 36865c2265..302b768ce9 100644 --- a/pkg/api/v1alpha1/strategymigration.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. diff --git a/pkg/api/v1alpha2/conversion.go b/pkg/api/v1alpha2/conversion.go index 3137a95d55..36c95e5ca1 100644 --- a/pkg/api/v1alpha2/conversion.go +++ b/pkg/api/v1alpha2/conversion.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. diff --git a/pkg/api/v1alpha2/defaults.go b/pkg/api/v1alpha2/defaults.go index 3532f2ae60..801d530cab 100644 --- a/pkg/api/v1alpha2/defaults.go +++ b/pkg/api/v1alpha2/defaults.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. diff --git a/pkg/api/v1alpha2/doc.go b/pkg/api/v1alpha2/doc.go index 7583871739..2d7dff1ed5 100644 --- a/pkg/api/v1alpha2/doc.go +++ b/pkg/api/v1alpha2/doc.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. diff --git a/pkg/api/v1alpha2/register.go b/pkg/api/v1alpha2/register.go index 2126bd816a..b975e416bc 100644 --- a/pkg/api/v1alpha2/register.go +++ b/pkg/api/v1alpha2/register.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. diff --git a/pkg/api/v1alpha2/sort.go b/pkg/api/v1alpha2/sort.go index c200d83a1a..a3f659df3f 100644 --- a/pkg/api/v1alpha2/sort.go +++ b/pkg/api/v1alpha2/sort.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. diff --git a/pkg/api/v1alpha2/types.go b/pkg/api/v1alpha2/types.go index c19f8cca50..b1b47467fb 100644 --- a/pkg/api/v1alpha2/types.go +++ b/pkg/api/v1alpha2/types.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. diff --git a/pkg/framework/pluginregistry/pluginregistry.go b/pkg/framework/pluginregistry/pluginregistry.go index a075f6f7fa..f5b2dd27a7 100644 --- a/pkg/framework/pluginregistry/pluginregistry.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.