From 330def2e56a0f44099a59b0578725f295ce7b985 Mon Sep 17 00:00:00 2001 From: Amir Alavi Date: Fri, 24 Jun 2022 16:28:28 -0400 Subject: [PATCH] Migrate RemoveFailedPods to plugin --- pkg/apis/componentconfig/types_pluginargs.go | 14 ++ .../validation/validation_pluginargs.go | 19 +- .../componentconfig/zz_generated.deepcopy.go | 50 +++++ pkg/descheduler/descheduler.go | 2 +- pkg/descheduler/strategies/failedpods.go | 174 ------------------ pkg/descheduler/strategy_migration.go | 28 +++ .../plugins/removefailedpods/failedpods.go | 168 +++++++++++++++++ .../removefailedpods}/failedpods_test.go | 147 +++++++-------- test/e2e/e2e_duplicatepods_test.go | 2 +- test/e2e/e2e_failedpods_test.go | 83 +++++---- test/e2e/e2e_leaderelection_test.go | 2 +- test/e2e/e2e_test.go | 20 +- test/e2e/e2e_toomanyrestarts_test.go | 2 +- test/e2e/e2e_topologyspreadconstraint_test.go | 2 +- 14 files changed, 411 insertions(+), 302 deletions(-) delete mode 100644 pkg/descheduler/strategies/failedpods.go create mode 100644 pkg/framework/plugins/removefailedpods/failedpods.go rename pkg/{descheduler/strategies => framework/plugins/removefailedpods}/failedpods_test.go (74%) diff --git a/pkg/apis/componentconfig/types_pluginargs.go b/pkg/apis/componentconfig/types_pluginargs.go index 7eca584c6..e38a96a10 100644 --- a/pkg/apis/componentconfig/types_pluginargs.go +++ b/pkg/apis/componentconfig/types_pluginargs.go @@ -32,3 +32,17 @@ type RemovePodsViolatingNodeTaintsArgs struct { IncludePreferNoSchedule bool ExcludedTaints []string } + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// RemoveFailedPodsArgs holds arguments used to configure RemoveFailedPodsArgs plugin. +type RemoveFailedPodsArgs struct { + metav1.TypeMeta + + Namespaces *api.Namespaces + LabelSelector *metav1.LabelSelector + ExcludeOwnerKinds []string + MinPodLifetimeSeconds *uint + Reasons []string + IncludingInitContainers bool +} diff --git a/pkg/apis/componentconfig/validation/validation_pluginargs.go b/pkg/apis/componentconfig/validation/validation_pluginargs.go index ebd67f073..fcf94ce42 100644 --- a/pkg/apis/componentconfig/validation/validation_pluginargs.go +++ b/pkg/apis/componentconfig/validation/validation_pluginargs.go @@ -19,15 +19,32 @@ package validation import ( "fmt" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "sigs.k8s.io/descheduler/pkg/api" "sigs.k8s.io/descheduler/pkg/apis/componentconfig" ) // ValidateRemovePodsViolatingNodeTaintsArgs validates RemovePodsViolatingNodeTaints arguments func ValidateRemovePodsViolatingNodeTaintsArgs(args *componentconfig.RemovePodsViolatingNodeTaintsArgs) error { + return validateCommonArgs(args.Namespaces, args.LabelSelector) +} + +// ValidateRemoveFailedPodsArgs validates RemoveFailedPods arguments +func ValidateRemoveFailedPodsArgs(args *componentconfig.RemoveFailedPodsArgs) error { + return validateCommonArgs(args.Namespaces, args.LabelSelector) +} + +func validateCommonArgs(namespaces *api.Namespaces, labelSelector *metav1.LabelSelector) error { // At most one of include/exclude can be set - if args.Namespaces != nil && len(args.Namespaces.Include) > 0 && len(args.Namespaces.Exclude) > 0 { + if namespaces != nil && len(namespaces.Include) > 0 && len(namespaces.Exclude) > 0 { return fmt.Errorf("only one of Include/Exclude namespaces can be set") } + if labelSelector != nil { + if _, err := metav1.LabelSelectorAsSelector(labelSelector); err != nil { + return fmt.Errorf("failed to get label selectors from strategy's params: %+v", err) + } + } + return nil } diff --git a/pkg/apis/componentconfig/zz_generated.deepcopy.go b/pkg/apis/componentconfig/zz_generated.deepcopy.go index 9d7267fc9..69279a4d9 100644 --- a/pkg/apis/componentconfig/zz_generated.deepcopy.go +++ b/pkg/apis/componentconfig/zz_generated.deepcopy.go @@ -54,6 +54,56 @@ func (in *DeschedulerConfiguration) 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 *RemovePodsViolatingNodeTaintsArgs) DeepCopyInto(out *RemovePodsViolatingNodeTaintsArgs) { *out = *in diff --git a/pkg/descheduler/descheduler.go b/pkg/descheduler/descheduler.go index de137a92f..4180ed882 100644 --- a/pkg/descheduler/descheduler.go +++ b/pkg/descheduler/descheduler.go @@ -254,7 +254,7 @@ func RunDeschedulerStrategies(ctx context.Context, rs *options.DeschedulerServer "RemovePodsHavingTooManyRestarts": strategies.RemovePodsHavingTooManyRestarts, "PodLifeTime": strategies.PodLifeTime, "RemovePodsViolatingTopologySpreadConstraint": strategies.RemovePodsViolatingTopologySpreadConstraint, - "RemoveFailedPods": strategies.RemoveFailedPods, + "RemoveFailedPods": nil, } var nodeSelector string diff --git a/pkg/descheduler/strategies/failedpods.go b/pkg/descheduler/strategies/failedpods.go deleted file mode 100644 index e12eb4c82..000000000 --- a/pkg/descheduler/strategies/failedpods.go +++ /dev/null @@ -1,174 +0,0 @@ -package strategies - -import ( - "context" - "fmt" - - v1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - utilerrors "k8s.io/apimachinery/pkg/util/errors" - "k8s.io/apimachinery/pkg/util/sets" - 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/descheduler/strategies/validation" -) - -// validatedFailedPodsStrategyParams contains validated strategy parameters -type validatedFailedPodsStrategyParams struct { - validation.ValidatedStrategyParams - includingInitContainers bool - reasons sets.String - excludeOwnerKinds sets.String - minPodLifetimeSeconds *uint -} - -// RemoveFailedPods removes Pods that are in failed status phase. -func RemoveFailedPods( - ctx context.Context, - client clientset.Interface, - strategy api.DeschedulerStrategy, - nodes []*v1.Node, - podEvictor *evictions.PodEvictor, - evictorFilter *evictions.EvictorFilter, - getPodsAssignedToNode podutil.GetPodsAssignedToNodeFunc, -) { - strategyParams, err := validateAndParseRemoveFailedPodsParams(ctx, client, strategy.Params) - if err != nil { - klog.ErrorS(err, "Invalid RemoveFailedPods parameters") - return - } - - var labelSelector *metav1.LabelSelector - if strategy.Params != nil { - labelSelector = strategy.Params.LabelSelector - } - - podFilter, err := podutil.NewOptions(). - WithFilter(evictorFilter.Filter). - WithNamespaces(strategyParams.IncludedNamespaces). - WithoutNamespaces(strategyParams.ExcludedNamespaces). - WithLabelSelector(labelSelector). - BuildFilterFunc() - if err != nil { - klog.ErrorS(err, "Error initializing pod filter function") - return - } - // Only list failed pods - phaseFilter := func(pod *v1.Pod) bool { return pod.Status.Phase == v1.PodFailed } - podFilter = podutil.WrapFilterFuncs(phaseFilter, podFilter) - - for _, node := range nodes { - klog.V(1).InfoS("Processing node", "node", klog.KObj(node)) - pods, err := podutil.ListAllPodsOnANode(node.Name, getPodsAssignedToNode, podFilter) - if err != nil { - klog.ErrorS(err, "Error listing a nodes failed pods", "node", klog.KObj(node)) - continue - } - - for i, pod := range pods { - if err = validateFailedPodShouldEvict(pod, *strategyParams); err != nil { - klog.V(4).InfoS(fmt.Sprintf("ignoring pod for eviction due to: %s", err.Error()), "pod", klog.KObj(pod)) - continue - } - - podEvictor.EvictPod(ctx, pods[i], evictions.EvictOptions{}) - if podEvictor.NodeLimitExceeded(node) { - continue - } - } - } -} - -func validateAndParseRemoveFailedPodsParams( - ctx context.Context, - client clientset.Interface, - params *api.StrategyParameters, -) (*validatedFailedPodsStrategyParams, error) { - if params == nil { - return &validatedFailedPodsStrategyParams{ - ValidatedStrategyParams: validation.DefaultValidatedStrategyParams(), - }, nil - } - - strategyParams, err := validation.ValidateAndParseStrategyParams(ctx, client, params) - if err != nil { - return nil, err - } - - var reasons, excludeOwnerKinds sets.String - var includingInitContainers bool - var minPodLifetimeSeconds *uint - if params.FailedPods != nil { - reasons = sets.NewString(params.FailedPods.Reasons...) - includingInitContainers = params.FailedPods.IncludingInitContainers - excludeOwnerKinds = sets.NewString(params.FailedPods.ExcludeOwnerKinds...) - minPodLifetimeSeconds = params.FailedPods.MinPodLifetimeSeconds - } - - return &validatedFailedPodsStrategyParams{ - ValidatedStrategyParams: *strategyParams, - includingInitContainers: includingInitContainers, - reasons: reasons, - excludeOwnerKinds: excludeOwnerKinds, - minPodLifetimeSeconds: minPodLifetimeSeconds, - }, nil -} - -// validateFailedPodShouldEvict looks at strategy params settings to see if the Pod -// should be evicted given the params in the PodFailed policy. -func validateFailedPodShouldEvict(pod *v1.Pod, strategyParams validatedFailedPodsStrategyParams) error { - var errs []error - - if strategyParams.minPodLifetimeSeconds != nil { - podAgeSeconds := uint(metav1.Now().Sub(pod.GetCreationTimestamp().Local()).Seconds()) - if podAgeSeconds < *strategyParams.minPodLifetimeSeconds { - errs = append(errs, fmt.Errorf("pod does not exceed the min age seconds of %d", *strategyParams.minPodLifetimeSeconds)) - } - } - - if len(strategyParams.excludeOwnerKinds) > 0 { - ownerRefList := podutil.OwnerRef(pod) - for _, owner := range ownerRefList { - if strategyParams.excludeOwnerKinds.Has(owner.Kind) { - errs = append(errs, fmt.Errorf("pod's owner kind of %s is excluded", owner.Kind)) - } - } - } - - if len(strategyParams.reasons) > 0 { - reasons := getFailedContainerStatusReasons(pod.Status.ContainerStatuses) - - if pod.Status.Phase == v1.PodFailed && pod.Status.Reason != "" { - reasons = append(reasons, pod.Status.Reason) - } - - if strategyParams.includingInitContainers { - reasons = append(reasons, getFailedContainerStatusReasons(pod.Status.InitContainerStatuses)...) - } - - if !strategyParams.reasons.HasAny(reasons...) { - errs = append(errs, fmt.Errorf("pod does not match any of the reasons")) - } - } - - return utilerrors.NewAggregate(errs) -} - -func getFailedContainerStatusReasons(containerStatuses []v1.ContainerStatus) []string { - reasons := make([]string, 0) - - for _, containerStatus := range containerStatuses { - if containerStatus.State.Waiting != nil && containerStatus.State.Waiting.Reason != "" { - reasons = append(reasons, containerStatus.State.Waiting.Reason) - } - if containerStatus.State.Terminated != nil && containerStatus.State.Terminated.Reason != "" { - reasons = append(reasons, containerStatus.State.Terminated.Reason) - } - } - - return reasons -} diff --git a/pkg/descheduler/strategy_migration.go b/pkg/descheduler/strategy_migration.go index 0bbcee012..e2a645795 100644 --- a/pkg/descheduler/strategy_migration.go +++ b/pkg/descheduler/strategy_migration.go @@ -25,6 +25,7 @@ import ( "sigs.k8s.io/descheduler/pkg/apis/componentconfig" "sigs.k8s.io/descheduler/pkg/apis/componentconfig/validation" "sigs.k8s.io/descheduler/pkg/framework" + "sigs.k8s.io/descheduler/pkg/framework/plugins/removefailedpods" "sigs.k8s.io/descheduler/pkg/framework/plugins/removepodsviolatingnodetaints" ) @@ -54,4 +55,31 @@ var pluginsMap = map[string]func(ctx context.Context, nodes []*v1.Node, params * klog.V(1).ErrorS(err, "plugin finished with error", "pluginName", removepodsviolatingnodetaints.PluginName) } }, + "RemoveFailedPods": func(ctx context.Context, nodes []*v1.Node, params *api.StrategyParameters, handle *handleImpl) { + failedPodsParams := params.FailedPods + if failedPodsParams == nil { + failedPodsParams = &api.FailedPods{} + } + args := &componentconfig.RemoveFailedPodsArgs{ + Namespaces: params.Namespaces, + LabelSelector: params.LabelSelector, + IncludingInitContainers: failedPodsParams.IncludingInitContainers, + MinPodLifetimeSeconds: failedPodsParams.MinPodLifetimeSeconds, + ExcludeOwnerKinds: failedPodsParams.ExcludeOwnerKinds, + Reasons: failedPodsParams.Reasons, + } + if err := validation.ValidateRemoveFailedPodsArgs(args); err != nil { + klog.V(1).ErrorS(err, "unable to validate plugin arguments", "pluginName", removefailedpods.PluginName) + return + } + pg, err := removefailedpods.New(args, handle) + if err != nil { + klog.V(1).ErrorS(err, "unable to initialize a plugin", "pluginName", removefailedpods.PluginName) + return + } + status := pg.(framework.DeschedulePlugin).Deschedule(ctx, nodes) + if status != nil && status.Err != nil { + klog.V(1).ErrorS(err, "plugin finished with error", "pluginName", removefailedpods.PluginName) + } + }, } diff --git a/pkg/framework/plugins/removefailedpods/failedpods.go b/pkg/framework/plugins/removefailedpods/failedpods.go new file mode 100644 index 000000000..ae7cdf648 --- /dev/null +++ b/pkg/framework/plugins/removefailedpods/failedpods.go @@ -0,0 +1,168 @@ +/* +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 ( + "context" + "fmt" + + v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + utilerrors "k8s.io/apimachinery/pkg/util/errors" + "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" +) + +const PluginName = "RemoveFailedPods" + +// RemoveFailedPods evicts pods on the node which violate NoSchedule Taints on nodes +type RemoveFailedPods struct { + handle framework.Handle + args *componentconfig.RemoveFailedPodsArgs + podFilter podutil.FilterFunc +} + +var _ framework.Plugin = &RemoveFailedPods{} +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) + if !ok { + return nil, fmt.Errorf("want args to be of type RemoveFailedPodsArgs, got %T", args) + } + + var includedNamespaces, excludedNamespaces sets.String + if failedPodsArgs.Namespaces != nil { + includedNamespaces = sets.NewString(failedPodsArgs.Namespaces.Include...) + excludedNamespaces = sets.NewString(failedPodsArgs.Namespaces.Exclude...) + } + + podFilter, err := podutil.NewOptions(). + WithFilter(handle.Evictor().Filter). + WithNamespaces(includedNamespaces). + WithoutNamespaces(excludedNamespaces). + WithLabelSelector(failedPodsArgs.LabelSelector). + BuildFilterFunc() + if err != nil { + return nil, fmt.Errorf("error initializing pod filter function: %v", err) + } + + podFilter = podutil.WrapFilterFuncs(func(pod *v1.Pod) bool { return pod.Status.Phase == v1.PodFailed }, podFilter) + + podFilter = podutil.WrapFilterFuncs(podFilter, func(pod *v1.Pod) bool { + if err := validateCanEvict(pod, failedPodsArgs); err != nil { + klog.V(4).InfoS(fmt.Sprintf("ignoring pod for eviction due to: %s", err.Error()), "pod", klog.KObj(pod)) + return false + } + + return true + }) + + return &RemoveFailedPods{ + handle: handle, + podFilter: podFilter, + args: failedPodsArgs, + }, nil +} + +// Name retrieves the plugin name +func (d *RemoveFailedPods) Name() string { + return PluginName +} + +// Deschedule extension point implementation for the plugin +func (d *RemoveFailedPods) Deschedule(ctx context.Context, nodes []*v1.Node) *framework.Status { + for _, node := range nodes { + klog.V(1).InfoS("Processing node", "node", klog.KObj(node)) + pods, err := podutil.ListAllPodsOnANode(node.Name, d.handle.GetPodsAssignedToNodeFunc(), d.podFilter) + if err != nil { + // no pods evicted as error encountered retrieving evictable Pods + return &framework.Status{ + Err: fmt.Errorf("error listing pods on a node: %v", err), + } + } + totalPods := len(pods) + for i := 0; i < totalPods; i++ { + d.handle.Evictor().Evict(ctx, pods[i], evictions.EvictOptions{}) + if d.handle.Evictor().NodeLimitExceeded(node) { + break + } + } + } + return nil +} + +// validateCanEvict looks at failedPodArgs to see if pod can be evicted given the args. +func validateCanEvict(pod *v1.Pod, failedPodArgs *componentconfig.RemoveFailedPodsArgs) error { + var errs []error + + if failedPodArgs.MinPodLifetimeSeconds != nil { + podAgeSeconds := uint(metav1.Now().Sub(pod.GetCreationTimestamp().Local()).Seconds()) + if podAgeSeconds < *failedPodArgs.MinPodLifetimeSeconds { + errs = append(errs, fmt.Errorf("pod does not exceed the min age seconds of %d", *failedPodArgs.MinPodLifetimeSeconds)) + } + } + + if len(failedPodArgs.ExcludeOwnerKinds) > 0 { + ownerRefList := podutil.OwnerRef(pod) + for _, owner := range ownerRefList { + if sets.NewString(failedPodArgs.ExcludeOwnerKinds...).Has(owner.Kind) { + errs = append(errs, fmt.Errorf("pod's owner kind of %s is excluded", owner.Kind)) + } + } + } + + if len(failedPodArgs.Reasons) > 0 { + reasons := getFailedContainerStatusReasons(pod.Status.ContainerStatuses) + + if pod.Status.Phase == v1.PodFailed && pod.Status.Reason != "" { + reasons = append(reasons, pod.Status.Reason) + } + + if failedPodArgs.IncludingInitContainers { + reasons = append(reasons, getFailedContainerStatusReasons(pod.Status.InitContainerStatuses)...) + } + + if !sets.NewString(failedPodArgs.Reasons...).HasAny(reasons...) { + errs = append(errs, fmt.Errorf("pod does not match any of the reasons")) + } + } + + return utilerrors.NewAggregate(errs) +} + +func getFailedContainerStatusReasons(containerStatuses []v1.ContainerStatus) []string { + reasons := make([]string, 0) + + for _, containerStatus := range containerStatuses { + if containerStatus.State.Waiting != nil && containerStatus.State.Waiting.Reason != "" { + reasons = append(reasons, containerStatus.State.Waiting.Reason) + } + if containerStatus.State.Terminated != nil && containerStatus.State.Terminated.Reason != "" { + reasons = append(reasons, containerStatus.State.Terminated.Reason) + } + } + + return reasons +} diff --git a/pkg/descheduler/strategies/failedpods_test.go b/pkg/framework/plugins/removefailedpods/failedpods_test.go similarity index 74% rename from pkg/descheduler/strategies/failedpods_test.go rename to pkg/framework/plugins/removefailedpods/failedpods_test.go index 83692add5..6e0b2b160 100644 --- a/pkg/descheduler/strategies/failedpods_test.go +++ b/pkg/framework/plugins/removefailedpods/failedpods_test.go @@ -1,4 +1,20 @@ -package strategies +/* +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 ( "context" @@ -11,10 +27,12 @@ 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/api" "sigs.k8s.io/descheduler/pkg/descheduler/evictions" podutil "sigs.k8s.io/descheduler/pkg/descheduler/pod" + frameworkfake "sigs.k8s.io/descheduler/pkg/framework/fake" "sigs.k8s.io/descheduler/test" ) @@ -23,45 +41,43 @@ var ( ) func TestRemoveFailedPods(t *testing.T) { - createStrategy := func(enabled, includingInitContainers bool, reasons, excludeKinds []string, minAgeSeconds *uint, nodeFit bool) api.DeschedulerStrategy { - return api.DeschedulerStrategy{ - Enabled: enabled, - Params: &api.StrategyParameters{ - FailedPods: &api.FailedPods{ - Reasons: reasons, - IncludingInitContainers: includingInitContainers, - ExcludeOwnerKinds: excludeKinds, - MinPodLifetimeSeconds: minAgeSeconds, - }, - NodeFit: nodeFit, - }, + createRemoveFailedPodsArgs := func( + includingInitContainers bool, + reasons, excludeKinds []string, + minAgeSeconds *uint) componentconfig.RemoveFailedPodsArgs { + return componentconfig.RemoveFailedPodsArgs{ + IncludingInitContainers: includingInitContainers, + Reasons: reasons, + MinPodLifetimeSeconds: minAgeSeconds, + ExcludeOwnerKinds: excludeKinds, } } tests := []struct { description string nodes []*v1.Node - strategy api.DeschedulerStrategy + args componentconfig.RemoveFailedPodsArgs expectedEvictedPodCount uint pods []*v1.Pod + nodeFit bool }{ { - description: "default empty strategy, 0 failures, 0 evictions", - strategy: api.DeschedulerStrategy{Params: &api.StrategyParameters{NodeFit: false}}, + description: "default empty args, 0 failures, 0 evictions", + args: componentconfig.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 }, { description: "0 failures, 0 evictions", - strategy: createStrategy(true, false, nil, nil, nil, false), + args: createRemoveFailedPodsArgs(false, nil, nil, nil), nodes: []*v1.Node{test.BuildTestNode("node1", 2000, 3000, 10, nil)}, expectedEvictedPodCount: 0, pods: []*v1.Pod{}, // no pods come back with field selector phase=Failed }, { description: "1 container terminated with reason NodeAffinity, 1 eviction", - strategy: createStrategy(true, false, nil, nil, nil, false), + args: createRemoveFailedPodsArgs(false, nil, nil, nil), nodes: []*v1.Node{test.BuildTestNode("node1", 2000, 3000, 10, nil)}, expectedEvictedPodCount: 1, pods: []*v1.Pod{ @@ -72,7 +88,7 @@ func TestRemoveFailedPods(t *testing.T) { }, { description: "1 init container terminated with reason NodeAffinity, 1 eviction", - strategy: createStrategy(true, true, nil, nil, nil, false), + args: createRemoveFailedPodsArgs(true, nil, nil, nil), nodes: []*v1.Node{test.BuildTestNode("node1", 2000, 3000, 10, nil)}, expectedEvictedPodCount: 1, pods: []*v1.Pod{ @@ -83,7 +99,7 @@ func TestRemoveFailedPods(t *testing.T) { }, { description: "1 init container waiting with reason CreateContainerConfigError, 1 eviction", - strategy: createStrategy(true, true, nil, nil, nil, false), + args: createRemoveFailedPodsArgs(true, nil, nil, nil), nodes: []*v1.Node{test.BuildTestNode("node1", 2000, 3000, 10, nil)}, expectedEvictedPodCount: 1, pods: []*v1.Pod{ @@ -94,7 +110,7 @@ func TestRemoveFailedPods(t *testing.T) { }, { description: "2 init container waiting with reason CreateContainerConfigError, 2 nodes, 2 evictions", - strategy: createStrategy(true, true, nil, nil, nil, false), + args: createRemoveFailedPodsArgs(true, nil, nil, nil), nodes: []*v1.Node{ test.BuildTestNode("node1", 2000, 3000, 10, nil), test.BuildTestNode("node2", 2000, 3000, 10, nil), @@ -111,7 +127,7 @@ func TestRemoveFailedPods(t *testing.T) { }, { description: "include reason=CreateContainerConfigError, 1 container terminated with reason CreateContainerConfigError, 1 eviction", - strategy: createStrategy(true, false, []string{"CreateContainerConfigError"}, nil, nil, false), + args: createRemoveFailedPodsArgs(false, []string{"CreateContainerConfigError"}, nil, nil), nodes: []*v1.Node{test.BuildTestNode("node1", 2000, 3000, 10, nil)}, expectedEvictedPodCount: 1, pods: []*v1.Pod{ @@ -122,7 +138,7 @@ func TestRemoveFailedPods(t *testing.T) { }, { description: "include reason=CreateContainerConfigError+NodeAffinity, 1 container terminated with reason CreateContainerConfigError, 1 eviction", - strategy: createStrategy(true, false, []string{"CreateContainerConfigError", "NodeAffinity"}, nil, nil, false), + args: createRemoveFailedPodsArgs(false, []string{"CreateContainerConfigError", "NodeAffinity"}, nil, nil), nodes: []*v1.Node{test.BuildTestNode("node1", 2000, 3000, 10, nil)}, expectedEvictedPodCount: 1, pods: []*v1.Pod{ @@ -133,7 +149,7 @@ func TestRemoveFailedPods(t *testing.T) { }, { description: "include reason=CreateContainerConfigError, 1 container terminated with reason NodeAffinity, 0 eviction", - strategy: createStrategy(true, false, []string{"CreateContainerConfigError"}, nil, nil, false), + args: createRemoveFailedPodsArgs(false, []string{"CreateContainerConfigError"}, nil, nil), nodes: []*v1.Node{test.BuildTestNode("node1", 2000, 3000, 10, nil)}, expectedEvictedPodCount: 0, pods: []*v1.Pod{ @@ -144,7 +160,7 @@ func TestRemoveFailedPods(t *testing.T) { }, { description: "include init container=false, 1 init container waiting with reason CreateContainerConfigError, 0 eviction", - strategy: createStrategy(true, false, []string{"CreateContainerConfigError"}, nil, nil, false), + args: createRemoveFailedPodsArgs(false, []string{"CreateContainerConfigError"}, nil, nil), nodes: []*v1.Node{test.BuildTestNode("node1", 2000, 3000, 10, nil)}, expectedEvictedPodCount: 0, pods: []*v1.Pod{ @@ -155,7 +171,7 @@ func TestRemoveFailedPods(t *testing.T) { }, { description: "lifetime 1 hour, 1 container terminated with reason NodeAffinity, 0 eviction", - strategy: createStrategy(true, false, nil, nil, &OneHourInSeconds, false), + args: createRemoveFailedPodsArgs(false, nil, nil, &OneHourInSeconds), nodes: []*v1.Node{test.BuildTestNode("node1", 2000, 3000, 10, nil)}, expectedEvictedPodCount: 0, pods: []*v1.Pod{ @@ -166,7 +182,7 @@ func TestRemoveFailedPods(t *testing.T) { }, { description: "nodeFit=true, 1 unschedulable node, 1 container terminated with reason NodeAffinity, 0 eviction", - strategy: createStrategy(true, false, nil, nil, nil, true), + args: createRemoveFailedPodsArgs(false, nil, nil, nil), nodes: []*v1.Node{ test.BuildTestNode("node1", 2000, 3000, 10, nil), test.BuildTestNode("node2", 2000, 2000, 10, func(node *v1.Node) { @@ -179,10 +195,11 @@ func TestRemoveFailedPods(t *testing.T) { Terminated: &v1.ContainerStateTerminated{Reason: "NodeAffinity"}, }), nil), }, + nodeFit: true, }, { description: "nodeFit=true, only available node does not have enough resources, 1 container terminated with reason CreateContainerConfigError, 0 eviction", - strategy: createStrategy(true, false, []string{"CreateContainerConfigError"}, nil, nil, true), + args: createRemoveFailedPodsArgs(false, []string{"CreateContainerConfigError"}, nil, nil), nodes: []*v1.Node{test.BuildTestNode("node1", 1, 1, 10, nil), test.BuildTestNode("node2", 0, 0, 10, nil)}, expectedEvictedPodCount: 0, pods: []*v1.Pod{ @@ -190,10 +207,11 @@ func TestRemoveFailedPods(t *testing.T) { Terminated: &v1.ContainerStateTerminated{Reason: "CreateContainerConfigError"}, }), nil), }, + nodeFit: true, }, { description: "excluded owner kind=ReplicaSet, 1 init container terminated with owner kind=ReplicaSet, 0 eviction", - strategy: createStrategy(true, true, nil, []string{"ReplicaSet"}, nil, false), + args: createRemoveFailedPodsArgs(true, nil, []string{"ReplicaSet"}, nil), nodes: []*v1.Node{test.BuildTestNode("node1", 2000, 3000, 10, nil)}, expectedEvictedPodCount: 0, pods: []*v1.Pod{ @@ -204,7 +222,7 @@ func TestRemoveFailedPods(t *testing.T) { }, { description: "excluded owner kind=DaemonSet, 1 init container terminated with owner kind=ReplicaSet, 1 eviction", - strategy: createStrategy(true, true, nil, []string{"DaemonSet"}, nil, false), + args: createRemoveFailedPodsArgs(true, nil, []string{"DaemonSet"}, nil), nodes: []*v1.Node{test.BuildTestNode("node1", 2000, 3000, 10, nil)}, expectedEvictedPodCount: 1, pods: []*v1.Pod{ @@ -215,7 +233,7 @@ func TestRemoveFailedPods(t *testing.T) { }, { description: "excluded owner kind=DaemonSet, 1 init container terminated with owner kind=ReplicaSet, 1 pod in termination; nothing should be moved", - strategy: createStrategy(true, true, nil, []string{"DaemonSet"}, nil, false), + args: createRemoveFailedPodsArgs(true, nil, []string{"DaemonSet"}, nil), nodes: []*v1.Node{test.BuildTestNode("node1", 2000, 3000, 10, nil)}, expectedEvictedPodCount: 0, pods: []*v1.Pod{ @@ -226,16 +244,17 @@ func TestRemoveFailedPods(t *testing.T) { }, { description: "1 container terminated with reason ShutDown, 0 evictions", - strategy: createStrategy(true, false, nil, nil, nil, true), + args: createRemoveFailedPodsArgs(false, nil, nil, nil), nodes: []*v1.Node{test.BuildTestNode("node1", 2000, 3000, 10, nil)}, expectedEvictedPodCount: 0, pods: []*v1.Pod{ buildTestPod("p1", "node1", newPodStatus("Shutdown", v1.PodFailed, nil, nil), nil), }, + nodeFit: true, }, { description: "include reason=Shutdown, 2 containers terminated with reason ShutDown, 2 evictions", - strategy: createStrategy(true, false, []string{"Shutdown"}, nil, nil, false), + args: createRemoveFailedPodsArgs(false, []string{"Shutdown"}, nil, nil), nodes: []*v1.Node{test.BuildTestNode("node1", 2000, 3000, 10, nil)}, expectedEvictedPodCount: 2, pods: []*v1.Pod{ @@ -289,10 +308,30 @@ func TestRemoveFailedPods(t *testing.T) { false, false, false, - evictions.WithNodeFit(tc.strategy.Params.NodeFit), + evictions.WithNodeFit(tc.nodeFit), ) - RemoveFailedPods(ctx, fakeClient, tc.strategy, tc.nodes, podEvictor, evictorFilter, getPodsAssignedToNode) + plugin, err := New(&componentconfig.RemoveFailedPodsArgs{ + Reasons: tc.args.Reasons, + MinPodLifetimeSeconds: tc.args.MinPodLifetimeSeconds, + IncludingInitContainers: tc.args.IncludingInitContainers, + ExcludeOwnerKinds: tc.args.ExcludeOwnerKinds, + LabelSelector: tc.args.LabelSelector, + Namespaces: tc.args.Namespaces, + }, + &frameworkfake.HandleImpl{ + ClientsetImpl: fakeClient, + PodEvictorImpl: podEvictor, + EvictorFilterImpl: evictorFilter, + SharedInformerFactoryImpl: sharedInformerFactory, + GetPodsAssignedToNodeFuncImpl: getPodsAssignedToNode, + }, + ) + if err != nil { + t.Fatalf("Unable to initialize the plugin: %v", err) + } + + plugin.(framework.DeschedulePlugin).Deschedule(ctx, tc.nodes) actualEvictedPodCount := podEvictor.TotalEvicted() if actualEvictedPodCount != tc.expectedEvictedPodCount { t.Errorf("Test %#v failed, expected %v pod evictions, but got %v pod evictions\n", tc.description, tc.expectedEvictedPodCount, actualEvictedPodCount) @@ -301,42 +340,6 @@ func TestRemoveFailedPods(t *testing.T) { } } -func TestValidRemoveFailedPodsParams(t *testing.T) { - ctx := context.Background() - fakeClient := &fake.Clientset{} - testCases := []struct { - name string - params *api.StrategyParameters - }{ - {name: "validate nil params", params: nil}, - {name: "validate empty params", params: &api.StrategyParameters{}}, - {name: "validate reasons params", params: &api.StrategyParameters{FailedPods: &api.FailedPods{ - Reasons: []string{"CreateContainerConfigError"}, - }}}, - {name: "validate includingInitContainers params", params: &api.StrategyParameters{FailedPods: &api.FailedPods{ - IncludingInitContainers: true, - }}}, - {name: "validate excludeOwnerKinds params", params: &api.StrategyParameters{FailedPods: &api.FailedPods{ - ExcludeOwnerKinds: []string{"Job"}, - }}}, - {name: "validate excludeOwnerKinds params", params: &api.StrategyParameters{FailedPods: &api.FailedPods{ - MinPodLifetimeSeconds: &OneHourInSeconds, - }}}, - } - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - t.Parallel() - params, err := validateAndParseRemoveFailedPodsParams(ctx, fakeClient, tc.params) - if err != nil { - t.Errorf("strategy params should be valid but got err: %v", err.Error()) - } - if params == nil { - t.Errorf("strategy params should return a ValidatedFailedPodsStrategyParams but got nil") - } - }) - } -} - func newPodStatus(reason string, phase v1.PodPhase, initContainerState, containerState *v1.ContainerState) v1.PodStatus { ps := v1.PodStatus{ Reason: reason, diff --git a/test/e2e/e2e_duplicatepods_test.go b/test/e2e/e2e_duplicatepods_test.go index 9bf5b5ad5..d8d4ad37f 100644 --- a/test/e2e/e2e_duplicatepods_test.go +++ b/test/e2e/e2e_duplicatepods_test.go @@ -37,7 +37,7 @@ import ( func TestRemoveDuplicates(t *testing.T) { ctx := context.Background() - clientSet, _, getPodsAssignedToNode, stopCh := initializeClient(t) + clientSet, _, _, getPodsAssignedToNode, stopCh := initializeClient(t) defer close(stopCh) nodeList, err := clientSet.CoreV1().Nodes().List(ctx, metav1.ListOptions{}) diff --git a/test/e2e/e2e_failedpods_test.go b/test/e2e/e2e_failedpods_test.go index 3873ee97d..6a1b86115 100644 --- a/test/e2e/e2e_failedpods_test.go +++ b/test/e2e/e2e_failedpods_test.go @@ -13,17 +13,18 @@ import ( "k8s.io/apimachinery/pkg/util/wait" clientset "k8s.io/client-go/kubernetes" "k8s.io/utils/pointer" - - deschedulerapi "sigs.k8s.io/descheduler/pkg/api" + "sigs.k8s.io/descheduler/pkg/apis/componentconfig" "sigs.k8s.io/descheduler/pkg/descheduler/evictions" - "sigs.k8s.io/descheduler/pkg/descheduler/strategies" + "sigs.k8s.io/descheduler/pkg/framework" + frameworkfake "sigs.k8s.io/descheduler/pkg/framework/fake" + "sigs.k8s.io/descheduler/pkg/framework/plugins/removefailedpods" ) var oneHourPodLifetimeSeconds uint = 3600 func TestFailedPods(t *testing.T) { ctx := context.Background() - clientSet, _, getPodsAssignedToNode, stopCh := initializeClient(t) + clientSet, sharedInformerFactory, _, getPodsAssignedToNode, stopCh := initializeClient(t) defer close(stopCh) nodeList, err := clientSet.CoreV1().Nodes().List(ctx, metav1.ListOptions{}) if err != nil { @@ -38,38 +39,28 @@ func TestFailedPods(t *testing.T) { defer clientSet.CoreV1().Namespaces().Delete(ctx, testNamespace.Name, metav1.DeleteOptions{}) testCases := map[string]struct { expectedEvictedCount uint - strategyParams *deschedulerapi.StrategyParameters + args *componentconfig.RemoveFailedPodsArgs }{ - "test-failed-pods-nil-strategy": { + "test-failed-pods-default-args": { expectedEvictedCount: 1, - strategyParams: nil, - }, - "test-failed-pods-default-strategy": { - expectedEvictedCount: 1, - strategyParams: &deschedulerapi.StrategyParameters{}, - }, - "test-failed-pods-default-failed-pods": { - expectedEvictedCount: 1, - strategyParams: &deschedulerapi.StrategyParameters{ - FailedPods: &deschedulerapi.FailedPods{}, - }, + args: &componentconfig.RemoveFailedPodsArgs{}, }, "test-failed-pods-reason-unmatched": { expectedEvictedCount: 0, - strategyParams: &deschedulerapi.StrategyParameters{ - FailedPods: &deschedulerapi.FailedPods{Reasons: []string{"ReasonDoesNotMatch"}}, + args: &componentconfig.RemoveFailedPodsArgs{ + Reasons: []string{"ReasonDoesNotMatch"}, }, }, "test-failed-pods-min-age-unmet": { expectedEvictedCount: 0, - strategyParams: &deschedulerapi.StrategyParameters{ - FailedPods: &deschedulerapi.FailedPods{MinPodLifetimeSeconds: &oneHourPodLifetimeSeconds}, + args: &componentconfig.RemoveFailedPodsArgs{ + MinPodLifetimeSeconds: &oneHourPodLifetimeSeconds, }, }, "test-failed-pods-exclude-job-kind": { expectedEvictedCount: 0, - strategyParams: &deschedulerapi.StrategyParameters{ - FailedPods: &deschedulerapi.FailedPods{ExcludeOwnerKinds: []string{"Job"}}, + args: &componentconfig.RemoveFailedPodsArgs{ + ExcludeOwnerKinds: []string{"Job"}, }, }, } @@ -87,26 +78,38 @@ func TestFailedPods(t *testing.T) { podEvictor := initPodEvictorOrFail(t, clientSet, getPodsAssignedToNode, nodes) - t.Logf("Running RemoveFailedPods strategy for %s", name) - strategies.RemoveFailedPods( - ctx, - clientSet, - deschedulerapi.DeschedulerStrategy{ - Enabled: true, - Params: tc.strategyParams, - }, + filter := evictions.NewEvictorFilter( nodes, - podEvictor, - evictions.NewEvictorFilter( - nodes, - getPodsAssignedToNode, - true, - false, - false, - false, - ), getPodsAssignedToNode, + true, + false, + false, + false, ) + + t.Logf("Running RemoveFailedPods strategy for %s", name) + + plugin, err := removefailedpods.New(&componentconfig.RemoveFailedPodsArgs{ + Reasons: tc.args.Reasons, + MinPodLifetimeSeconds: tc.args.MinPodLifetimeSeconds, + IncludingInitContainers: tc.args.IncludingInitContainers, + ExcludeOwnerKinds: tc.args.ExcludeOwnerKinds, + LabelSelector: tc.args.LabelSelector, + Namespaces: tc.args.Namespaces, + }, + &frameworkfake.HandleImpl{ + ClientsetImpl: clientSet, + PodEvictorImpl: podEvictor, + EvictorFilterImpl: filter, + SharedInformerFactoryImpl: sharedInformerFactory, + GetPodsAssignedToNodeFuncImpl: getPodsAssignedToNode, + }, + ) + if err != nil { + t.Fatalf("Unable to initialize the plugin: %v", err) + } + + plugin.(framework.DeschedulePlugin).Deschedule(ctx, nodes) t.Logf("Finished RemoveFailedPods strategy for %s", name) if actualEvictedCount := podEvictor.TotalEvicted(); actualEvictedCount == tc.expectedEvictedCount { diff --git a/test/e2e/e2e_leaderelection_test.go b/test/e2e/e2e_leaderelection_test.go index 18bfd977e..3fa708cf7 100644 --- a/test/e2e/e2e_leaderelection_test.go +++ b/test/e2e/e2e_leaderelection_test.go @@ -39,7 +39,7 @@ import ( func TestLeaderElection(t *testing.T) { ctx := context.Background() - clientSet, _, _, stopCh := initializeClient(t) + clientSet, _, _, _, stopCh := initializeClient(t) defer close(stopCh) ns1 := "e2e-" + strings.ToLower(t.Name()+"-a") diff --git a/test/e2e/e2e_test.go b/test/e2e/e2e_test.go index 8a26ae203..554eec6a9 100644 --- a/test/e2e/e2e_test.go +++ b/test/e2e/e2e_test.go @@ -107,7 +107,7 @@ func RcByNameContainer(name, namespace string, replicas int32, labels map[string } } -func initializeClient(t *testing.T) (clientset.Interface, coreinformers.NodeInformer, podutil.GetPodsAssignedToNodeFunc, chan struct{}) { +func initializeClient(t *testing.T) (clientset.Interface, informers.SharedInformerFactory, coreinformers.NodeInformer, podutil.GetPodsAssignedToNodeFunc, chan struct{}) { clientSet, err := client.CreateClient(os.Getenv("KUBECONFIG"), "") if err != nil { t.Errorf("Error during client creation with %v", err) @@ -128,7 +128,7 @@ func initializeClient(t *testing.T) (clientset.Interface, coreinformers.NodeInfo sharedInformerFactory.WaitForCacheSync(stopChannel) waitForNodesReady(context.Background(), t, clientSet, nodeInformer) - return clientSet, nodeInformer, getPodsAssignedToNode, stopChannel + return clientSet, sharedInformerFactory, nodeInformer, getPodsAssignedToNode, stopChannel } func waitForNodesReady(ctx context.Context, t *testing.T, clientSet clientset.Interface, nodeInformer coreinformers.NodeInformer) { @@ -250,7 +250,7 @@ func intersectStrings(lista, listb []string) []string { func TestLowNodeUtilization(t *testing.T) { ctx := context.Background() - clientSet, _, getPodsAssignedToNode, stopCh := initializeClient(t) + clientSet, _, _, getPodsAssignedToNode, stopCh := initializeClient(t) defer close(stopCh) nodeList, err := clientSet.CoreV1().Nodes().List(ctx, metav1.ListOptions{}) @@ -408,7 +408,7 @@ func TestLowNodeUtilization(t *testing.T) { func TestNamespaceConstraintsInclude(t *testing.T) { ctx := context.Background() - clientSet, nodeInformer, getPodsAssignedToNode, stopCh := initializeClient(t) + clientSet, _, nodeInformer, getPodsAssignedToNode, stopCh := initializeClient(t) defer close(stopCh) testNamespace := &v1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "e2e-" + strings.ToLower(t.Name())}} @@ -479,7 +479,7 @@ func TestNamespaceConstraintsInclude(t *testing.T) { func TestNamespaceConstraintsExclude(t *testing.T) { ctx := context.Background() - clientSet, nodeInformer, getPodsAssignedToNode, stopCh := initializeClient(t) + clientSet, _, nodeInformer, getPodsAssignedToNode, stopCh := initializeClient(t) defer close(stopCh) testNamespace := &v1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "e2e-" + strings.ToLower(t.Name())}} @@ -546,7 +546,7 @@ func testEvictSystemCritical(t *testing.T, isPriorityClass bool) { lowPriority := int32(500) ctx := context.Background() - clientSet, nodeInformer, getPodsAssignedToNode, stopCh := initializeClient(t) + clientSet, _, nodeInformer, getPodsAssignedToNode, stopCh := initializeClient(t) defer close(stopCh) testNamespace := &v1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "e2e-" + strings.ToLower(t.Name())}} @@ -676,7 +676,7 @@ func testPriority(t *testing.T, isPriorityClass bool) { lowPriority := int32(500) ctx := context.Background() - clientSet, nodeInformer, getPodsAssignedToNode, stopCh := initializeClient(t) + clientSet, _, nodeInformer, getPodsAssignedToNode, stopCh := initializeClient(t) defer close(stopCh) testNamespace := &v1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "e2e-" + strings.ToLower(t.Name())}} @@ -805,7 +805,7 @@ func testPriority(t *testing.T, isPriorityClass bool) { func TestPodLabelSelector(t *testing.T) { ctx := context.Background() - clientSet, nodeInformer, getPodsAssignedToNode, stopCh := initializeClient(t) + clientSet, _, nodeInformer, getPodsAssignedToNode, stopCh := initializeClient(t) defer close(stopCh) testNamespace := &v1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "e2e-" + strings.ToLower(t.Name())}} @@ -908,7 +908,7 @@ func TestPodLabelSelector(t *testing.T) { func TestEvictAnnotation(t *testing.T) { ctx := context.Background() - clientSet, nodeInformer, getPodsAssignedToNode, stopCh := initializeClient(t) + clientSet, _, nodeInformer, getPodsAssignedToNode, stopCh := initializeClient(t) defer close(stopCh) testNamespace := &v1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "e2e-" + strings.ToLower(t.Name())}} @@ -980,7 +980,7 @@ func TestEvictAnnotation(t *testing.T) { func TestPodLifeTimeOldestEvicted(t *testing.T) { ctx := context.Background() - clientSet, nodeInformer, getPodsAssignedToNode, stopCh := initializeClient(t) + clientSet, _, nodeInformer, getPodsAssignedToNode, stopCh := initializeClient(t) defer close(stopCh) testNamespace := &v1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "e2e-" + strings.ToLower(t.Name())}} diff --git a/test/e2e/e2e_toomanyrestarts_test.go b/test/e2e/e2e_toomanyrestarts_test.go index 00b0a2368..ab6faf78d 100644 --- a/test/e2e/e2e_toomanyrestarts_test.go +++ b/test/e2e/e2e_toomanyrestarts_test.go @@ -39,7 +39,7 @@ import ( func TestTooManyRestarts(t *testing.T) { ctx := context.Background() - clientSet, _, getPodsAssignedToNode, stopCh := initializeClient(t) + clientSet, _, _, getPodsAssignedToNode, stopCh := initializeClient(t) defer close(stopCh) nodeList, err := clientSet.CoreV1().Nodes().List(ctx, metav1.ListOptions{}) diff --git a/test/e2e/e2e_topologyspreadconstraint_test.go b/test/e2e/e2e_topologyspreadconstraint_test.go index dc2759868..91d787260 100644 --- a/test/e2e/e2e_topologyspreadconstraint_test.go +++ b/test/e2e/e2e_topologyspreadconstraint_test.go @@ -19,7 +19,7 @@ const zoneTopologyKey string = "topology.kubernetes.io/zone" func TestTopologySpreadConstraint(t *testing.T) { ctx := context.Background() - clientSet, _, getPodsAssignedToNode, stopCh := initializeClient(t) + clientSet, _, _, getPodsAssignedToNode, stopCh := initializeClient(t) defer close(stopCh) nodeList, err := clientSet.CoreV1().Nodes().List(ctx, metav1.ListOptions{}) if err != nil {