diff --git a/hack/update-generated-conversions.sh b/hack/update-generated-conversions.sh index ebf51280b..11a412b1f 100755 --- a/hack/update-generated-conversions.sh +++ b/hack/update-generated-conversions.sh @@ -5,5 +5,5 @@ go build -o "${OS_OUTPUT_BINPATH}/conversion-gen" "k8s.io/code-generator/cmd/con ${OS_OUTPUT_BINPATH}/conversion-gen \ --go-header-file "hack/boilerplate/boilerplate.go.txt" \ - --input-dirs "${PRJ_PREFIX}/pkg/apis/componentconfig/v1alpha1,${PRJ_PREFIX}/pkg/api/v1alpha1" \ + --input-dirs "${PRJ_PREFIX}/pkg/apis/componentconfig/v1alpha1,${PRJ_PREFIX}/pkg/api/v1alpha1,${PRJ_PREFIX}/pkg/framework/plugins/removefailedpods" \ --output-file-base zz_generated.conversion diff --git a/hack/update-generated-deep-copies.sh b/hack/update-generated-deep-copies.sh index 880961f70..cb7c0c113 100755 --- a/hack/update-generated-deep-copies.sh +++ b/hack/update-generated-deep-copies.sh @@ -5,6 +5,6 @@ go build -o "${OS_OUTPUT_BINPATH}/deepcopy-gen" "k8s.io/code-generator/cmd/deepc ${OS_OUTPUT_BINPATH}/deepcopy-gen \ --go-header-file "hack/boilerplate/boilerplate.go.txt" \ - --input-dirs "${PRJ_PREFIX}/pkg/apis/componentconfig,${PRJ_PREFIX}/pkg/apis/componentconfig/v1alpha1,${PRJ_PREFIX}/pkg/api,${PRJ_PREFIX}/pkg/api/v1alpha1,${PRJ_PREFIX}/pkg/framework/plugins/defaultevictor/" \ + --input-dirs "${PRJ_PREFIX}/pkg/apis/componentconfig,${PRJ_PREFIX}/pkg/apis/componentconfig/v1alpha1,${PRJ_PREFIX}/pkg/api,${PRJ_PREFIX}/pkg/api/v1alpha1,${PRJ_PREFIX}/pkg/framework/plugins/defaultevictor/,${PRJ_PREFIX}/pkg/framework/plugins/removefailedpods" \ --output-file-base zz_generated.deepcopy diff --git a/pkg/apis/componentconfig/types_pluginargs.go b/pkg/apis/componentconfig/types_pluginargs.go index d47a35eb9..b7a0829ba 100644 --- a/pkg/apis/componentconfig/types_pluginargs.go +++ b/pkg/apis/componentconfig/types_pluginargs.go @@ -35,20 +35,6 @@ type RemovePodsViolatingNodeTaintsArgs struct { // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object -// RemoveFailedPodsArgs holds arguments used to configure RemoveFailedPods plugin. -type RemoveFailedPodsArgs struct { - metav1.TypeMeta - - Namespaces *api.Namespaces - LabelSelector *metav1.LabelSelector - ExcludeOwnerKinds []string - MinPodLifetimeSeconds *uint - Reasons []string - IncludingInitContainers bool -} - -// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object - // RemovePodsViolatingNodeAffinityArgs holds arguments used to configure RemovePodsViolatingNodeAffinity plugin. type RemovePodsViolatingNodeAffinityArgs struct { metav1.TypeMeta diff --git a/pkg/apis/componentconfig/validation/validation_pluginargs.go b/pkg/apis/componentconfig/validation/validation_pluginargs.go index 8107e8f12..a4023abfa 100644 --- a/pkg/apis/componentconfig/validation/validation_pluginargs.go +++ b/pkg/apis/componentconfig/validation/validation_pluginargs.go @@ -43,14 +43,6 @@ func ValidateRemovePodsViolatingNodeTaintsArgs(args *componentconfig.RemovePodsV ) } -// ValidateRemoveFailedPodsArgs validates RemoveFailedPods arguments -func ValidateRemoveFailedPodsArgs(args *componentconfig.RemoveFailedPodsArgs) error { - return errorsAggregate( - validateNamespaceArgs(args.Namespaces), - validateLabelSelectorArgs(args.LabelSelector), - ) -} - // ValidateRemovePodsHavingTooManyRestartsArgs validates RemovePodsHavingTooManyRestarts arguments func ValidateRemovePodsHavingTooManyRestartsArgs(args *componentconfig.RemovePodsHavingTooManyRestartsArgs) error { return errorsAggregate( diff --git a/pkg/apis/componentconfig/zz_generated.deepcopy.go b/pkg/apis/componentconfig/zz_generated.deepcopy.go index 096c4f358..6838d2f6f 100644 --- a/pkg/apis/componentconfig/zz_generated.deepcopy.go +++ b/pkg/apis/componentconfig/zz_generated.deepcopy.go @@ -205,56 +205,6 @@ func (in *RemoveDuplicatesArgs) DeepCopyObject() runtime.Object { return nil } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *RemoveFailedPodsArgs) DeepCopyInto(out *RemoveFailedPodsArgs) { - *out = *in - out.TypeMeta = in.TypeMeta - if in.Namespaces != nil { - in, out := &in.Namespaces, &out.Namespaces - *out = new(api.Namespaces) - (*in).DeepCopyInto(*out) - } - if in.LabelSelector != nil { - in, out := &in.LabelSelector, &out.LabelSelector - *out = new(v1.LabelSelector) - (*in).DeepCopyInto(*out) - } - if in.ExcludeOwnerKinds != nil { - in, out := &in.ExcludeOwnerKinds, &out.ExcludeOwnerKinds - *out = make([]string, len(*in)) - copy(*out, *in) - } - if in.MinPodLifetimeSeconds != nil { - in, out := &in.MinPodLifetimeSeconds, &out.MinPodLifetimeSeconds - *out = new(uint) - **out = **in - } - if in.Reasons != nil { - in, out := &in.Reasons, &out.Reasons - *out = make([]string, len(*in)) - copy(*out, *in) - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RemoveFailedPodsArgs. -func (in *RemoveFailedPodsArgs) DeepCopy() *RemoveFailedPodsArgs { - if in == nil { - return nil - } - out := new(RemoveFailedPodsArgs) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *RemoveFailedPodsArgs) 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 *RemovePodsHavingTooManyRestartsArgs) DeepCopyInto(out *RemovePodsHavingTooManyRestartsArgs) { *out = *in diff --git a/pkg/descheduler/strategy_migration.go b/pkg/descheduler/strategy_migration.go index 410f1577f..d4255e4e8 100644 --- a/pkg/descheduler/strategy_migration.go +++ b/pkg/descheduler/strategy_migration.go @@ -67,7 +67,7 @@ var pluginsMap = map[string]func(ctx context.Context, nodes []*v1.Node, params * if failedPodsParams == nil { failedPodsParams = &api.FailedPods{} } - args := &componentconfig.RemoveFailedPodsArgs{ + args := &removefailedpods.RemoveFailedPodsArgs{ Namespaces: params.Namespaces, LabelSelector: params.LabelSelector, IncludingInitContainers: failedPodsParams.IncludingInitContainers, @@ -75,7 +75,7 @@ var pluginsMap = map[string]func(ctx context.Context, nodes []*v1.Node, params * ExcludeOwnerKinds: failedPodsParams.ExcludeOwnerKinds, Reasons: failedPodsParams.Reasons, } - if err := validation.ValidateRemoveFailedPodsArgs(args); err != nil { + if err := removefailedpods.ValidateRemoveFailedPodsArgs(args); err != nil { klog.V(1).ErrorS(err, "unable to validate plugin arguments", "pluginName", removefailedpods.PluginName) return } diff --git a/pkg/framework/plugins/removefailedpods/failedpods.go b/pkg/framework/plugins/removefailedpods/failedpods.go index 87435d455..9b7fb57ca 100644 --- a/pkg/framework/plugins/removefailedpods/failedpods.go +++ b/pkg/framework/plugins/removefailedpods/failedpods.go @@ -27,7 +27,6 @@ import ( "k8s.io/apimachinery/pkg/util/sets" "k8s.io/klog/v2" - "sigs.k8s.io/descheduler/pkg/apis/componentconfig" "sigs.k8s.io/descheduler/pkg/descheduler/evictions" podutil "sigs.k8s.io/descheduler/pkg/descheduler/pod" "sigs.k8s.io/descheduler/pkg/framework" @@ -38,7 +37,7 @@ const PluginName = "RemoveFailedPods" // RemoveFailedPods evicts pods in failed status phase that match the given args criteria type RemoveFailedPods struct { handle framework.Handle - args *componentconfig.RemoveFailedPodsArgs + args *RemoveFailedPodsArgs podFilter podutil.FilterFunc } @@ -46,7 +45,7 @@ var _ framework.DeschedulePlugin = &RemoveFailedPods{} // New builds plugin from its arguments while passing a handle func New(args runtime.Object, handle framework.Handle) (framework.Plugin, error) { - failedPodsArgs, ok := args.(*componentconfig.RemoveFailedPodsArgs) + failedPodsArgs, ok := args.(*RemoveFailedPodsArgs) if !ok { return nil, fmt.Errorf("want args to be of type RemoveFailedPodsArgs, got %T", args) } @@ -114,7 +113,7 @@ func (d *RemoveFailedPods) Deschedule(ctx context.Context, nodes []*v1.Node) *fr } // validateCanEvict looks at failedPodArgs to see if pod can be evicted given the args. -func validateCanEvict(pod *v1.Pod, failedPodArgs *componentconfig.RemoveFailedPodsArgs) error { +func validateCanEvict(pod *v1.Pod, failedPodArgs *RemoveFailedPodsArgs) error { var errs []error if failedPodArgs.MinPodLifetimeSeconds != nil { diff --git a/pkg/framework/plugins/removefailedpods/failedpods_test.go b/pkg/framework/plugins/removefailedpods/failedpods_test.go index 624e0c483..e354e94c8 100644 --- a/pkg/framework/plugins/removefailedpods/failedpods_test.go +++ b/pkg/framework/plugins/removefailedpods/failedpods_test.go @@ -27,7 +27,6 @@ import ( "k8s.io/client-go/informers" "k8s.io/client-go/kubernetes/fake" "k8s.io/client-go/tools/events" - "sigs.k8s.io/descheduler/pkg/apis/componentconfig" "sigs.k8s.io/descheduler/pkg/framework" "sigs.k8s.io/descheduler/pkg/descheduler/evictions" @@ -45,8 +44,8 @@ func TestRemoveFailedPods(t *testing.T) { createRemoveFailedPodsArgs := func( includingInitContainers bool, reasons, excludeKinds []string, - minAgeSeconds *uint) componentconfig.RemoveFailedPodsArgs { - return componentconfig.RemoveFailedPodsArgs{ + minAgeSeconds *uint) RemoveFailedPodsArgs { + return RemoveFailedPodsArgs{ IncludingInitContainers: includingInitContainers, Reasons: reasons, MinPodLifetimeSeconds: minAgeSeconds, @@ -57,14 +56,14 @@ func TestRemoveFailedPods(t *testing.T) { tests := []struct { description string nodes []*v1.Node - args componentconfig.RemoveFailedPodsArgs + args RemoveFailedPodsArgs expectedEvictedPodCount uint pods []*v1.Pod nodeFit bool }{ { description: "default empty args, 0 failures, 0 evictions", - args: componentconfig.RemoveFailedPodsArgs{}, + args: RemoveFailedPodsArgs{}, nodes: []*v1.Node{test.BuildTestNode("node1", 2000, 3000, 10, nil)}, expectedEvictedPodCount: 0, pods: []*v1.Pod{}, // no pods come back with field selector phase=Failed @@ -323,7 +322,7 @@ func TestRemoveFailedPods(t *testing.T) { t.Fatalf("Unable to initialize the plugin: %v", err) } - plugin, err := New(&componentconfig.RemoveFailedPodsArgs{ + plugin, err := New(&RemoveFailedPodsArgs{ Reasons: tc.args.Reasons, MinPodLifetimeSeconds: tc.args.MinPodLifetimeSeconds, IncludingInitContainers: tc.args.IncludingInitContainers, diff --git a/pkg/framework/plugins/removefailedpods/types.go b/pkg/framework/plugins/removefailedpods/types.go new file mode 100644 index 000000000..985f83398 --- /dev/null +++ b/pkg/framework/plugins/removefailedpods/types.go @@ -0,0 +1,34 @@ +/* +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 removefailedpods + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "sigs.k8s.io/descheduler/pkg/api" +) + +// +k8s:deepcopy-gen=true +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// RemoveFailedPodsArgs holds arguments used to configure RemoveFailedPods plugin. +type RemoveFailedPodsArgs struct { + metav1.TypeMeta + + Namespaces *api.Namespaces + LabelSelector *metav1.LabelSelector + ExcludeOwnerKinds []string + MinPodLifetimeSeconds *uint + Reasons []string + IncludingInitContainers bool +} diff --git a/pkg/framework/plugins/removefailedpods/validation.go b/pkg/framework/plugins/removefailedpods/validation.go new file mode 100644 index 000000000..11aa6c7d3 --- /dev/null +++ b/pkg/framework/plugins/removefailedpods/validation.go @@ -0,0 +1,36 @@ +/* +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 removefailedpods + +import ( + "fmt" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// ValidateRemoveFailedPodsArgs validates RemoveFailedPods arguments +func ValidateRemoveFailedPodsArgs(args *RemoveFailedPodsArgs) error { + // 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") + } + + if args.LabelSelector != nil { + if _, err := metav1.LabelSelectorAsSelector(args.LabelSelector); err != nil { + return fmt.Errorf("failed to get label selectors from strategy's params: %+v", err) + } + } + + return nil +} diff --git a/pkg/framework/plugins/removefailedpods/zz_generated.deepcopy.go b/pkg/framework/plugins/removefailedpods/zz_generated.deepcopy.go new file mode 100644 index 000000000..67fbf5f8f --- /dev/null +++ b/pkg/framework/plugins/removefailedpods/zz_generated.deepcopy.go @@ -0,0 +1,78 @@ +//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 removefailedpods + +import ( + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + api "sigs.k8s.io/descheduler/pkg/api" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RemoveFailedPodsArgs) DeepCopyInto(out *RemoveFailedPodsArgs) { + *out = *in + out.TypeMeta = in.TypeMeta + if in.Namespaces != nil { + in, out := &in.Namespaces, &out.Namespaces + *out = new(api.Namespaces) + (*in).DeepCopyInto(*out) + } + if in.LabelSelector != nil { + in, out := &in.LabelSelector, &out.LabelSelector + *out = new(v1.LabelSelector) + (*in).DeepCopyInto(*out) + } + if in.ExcludeOwnerKinds != nil { + in, out := &in.ExcludeOwnerKinds, &out.ExcludeOwnerKinds + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.MinPodLifetimeSeconds != nil { + in, out := &in.MinPodLifetimeSeconds, &out.MinPodLifetimeSeconds + *out = new(uint) + **out = **in + } + if in.Reasons != nil { + in, out := &in.Reasons, &out.Reasons + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RemoveFailedPodsArgs. +func (in *RemoveFailedPodsArgs) DeepCopy() *RemoveFailedPodsArgs { + if in == nil { + return nil + } + out := new(RemoveFailedPodsArgs) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *RemoveFailedPodsArgs) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} diff --git a/test/e2e/e2e_failedpods_test.go b/test/e2e/e2e_failedpods_test.go index e052601d3..4c26be053 100644 --- a/test/e2e/e2e_failedpods_test.go +++ b/test/e2e/e2e_failedpods_test.go @@ -13,7 +13,6 @@ import ( "k8s.io/apimachinery/pkg/util/wait" clientset "k8s.io/client-go/kubernetes" "k8s.io/utils/pointer" - "sigs.k8s.io/descheduler/pkg/apis/componentconfig" "sigs.k8s.io/descheduler/pkg/framework" frameworkfake "sigs.k8s.io/descheduler/pkg/framework/fake" "sigs.k8s.io/descheduler/pkg/framework/plugins/defaultevictor" @@ -39,27 +38,27 @@ func TestFailedPods(t *testing.T) { defer clientSet.CoreV1().Namespaces().Delete(ctx, testNamespace.Name, metav1.DeleteOptions{}) testCases := map[string]struct { expectedEvictedCount uint - args *componentconfig.RemoveFailedPodsArgs + args *removefailedpods.RemoveFailedPodsArgs }{ "test-failed-pods-default-args": { expectedEvictedCount: 1, - args: &componentconfig.RemoveFailedPodsArgs{}, + args: &removefailedpods.RemoveFailedPodsArgs{}, }, "test-failed-pods-reason-unmatched": { expectedEvictedCount: 0, - args: &componentconfig.RemoveFailedPodsArgs{ + args: &removefailedpods.RemoveFailedPodsArgs{ Reasons: []string{"ReasonDoesNotMatch"}, }, }, "test-failed-pods-min-age-unmet": { expectedEvictedCount: 0, - args: &componentconfig.RemoveFailedPodsArgs{ + args: &removefailedpods.RemoveFailedPodsArgs{ MinPodLifetimeSeconds: &oneHourPodLifetimeSeconds, }, }, "test-failed-pods-exclude-job-kind": { expectedEvictedCount: 0, - args: &componentconfig.RemoveFailedPodsArgs{ + args: &removefailedpods.RemoveFailedPodsArgs{ ExcludeOwnerKinds: []string{"Job"}, }, }, @@ -100,7 +99,7 @@ func TestFailedPods(t *testing.T) { t.Logf("Running RemoveFailedPods strategy for %s", name) - plugin, err := removefailedpods.New(&componentconfig.RemoveFailedPodsArgs{ + plugin, err := removefailedpods.New(&removefailedpods.RemoveFailedPodsArgs{ Reasons: tc.args.Reasons, MinPodLifetimeSeconds: tc.args.MinPodLifetimeSeconds, IncludingInitContainers: tc.args.IncludingInitContainers,