mirror of
https://github.com/kubernetes-sigs/descheduler.git
synced 2026-01-26 05:14:13 +01:00
Merge pull request #1790 from ingvagabund/podlifetime-unit-tests
refactor(TestPodLifeTime): split the unit tests into smaller semantically close groups
This commit is contained in:
@@ -35,44 +35,45 @@ import (
|
||||
"sigs.k8s.io/descheduler/test"
|
||||
)
|
||||
|
||||
func TestPodLifeTime(t *testing.T) {
|
||||
const nodeName1 = "n1"
|
||||
buildTestNode1 := func() *v1.Node {
|
||||
const nodeName1 = "n1"
|
||||
|
||||
var (
|
||||
olderPodCreationTime = metav1.NewTime(time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC))
|
||||
newerPodCreationTime = metav1.NewTime(time.Now())
|
||||
)
|
||||
|
||||
func buildTestNode1() *v1.Node {
|
||||
return test.BuildTestNode(nodeName1, 2000, 3000, 10, nil)
|
||||
}
|
||||
}
|
||||
|
||||
olderPodCreationTime := metav1.NewTime(time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC))
|
||||
newerPodCreationTime := metav1.NewTime(time.Now())
|
||||
|
||||
buildTestPodForNode1 := func(name string, creationTime metav1.Time, apply func(*v1.Pod)) *v1.Pod {
|
||||
func buildTestPodForNode1(name string, creationTime metav1.Time, apply func(*v1.Pod)) *v1.Pod {
|
||||
return test.BuildTestPod(name, 100, 0, nodeName1, func(pod *v1.Pod) {
|
||||
pod.ObjectMeta.CreationTimestamp = creationTime
|
||||
if apply != nil {
|
||||
apply(pod)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
buildTestPodWithRSOwnerRefForNode1 := func(name string, creationTime metav1.Time, apply func(*v1.Pod)) *v1.Pod {
|
||||
func buildTestPodWithRSOwnerRefForNode1(name string, creationTime metav1.Time, apply func(*v1.Pod)) *v1.Pod {
|
||||
return buildTestPodForNode1(name, creationTime, func(pod *v1.Pod) {
|
||||
test.SetRSOwnerRef(pod)
|
||||
if apply != nil {
|
||||
apply(pod)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
buildTestPodWithRSOwnerRefWithPendingPhaseForNode1 := func(name string, creationTime metav1.Time, apply func(*v1.Pod)) *v1.Pod {
|
||||
func buildTestPodWithRSOwnerRefWithPendingPhaseForNode1(name string, creationTime metav1.Time, apply func(*v1.Pod)) *v1.Pod {
|
||||
return buildTestPodWithRSOwnerRefForNode1(name, creationTime, func(pod *v1.Pod) {
|
||||
pod.Status.Phase = "Pending"
|
||||
if apply != nil {
|
||||
apply(pod)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
var maxLifeTime uint = 600
|
||||
testCases := []struct {
|
||||
type podLifeTimeTestCase struct {
|
||||
description string
|
||||
args *PodLifeTimeArgs
|
||||
pods []*v1.Pod
|
||||
@@ -83,119 +84,96 @@ func TestPodLifeTime(t *testing.T) {
|
||||
maxPodsToEvictPerNode *uint
|
||||
maxPodsToEvictPerNamespace *uint
|
||||
maxPodsToEvictTotal *uint
|
||||
}{
|
||||
}
|
||||
|
||||
func runPodLifeTimeTest(t *testing.T, tc podLifeTimeTestCase) {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
var objs []runtime.Object
|
||||
for _, node := range tc.nodes {
|
||||
objs = append(objs, node)
|
||||
}
|
||||
for _, pod := range tc.pods {
|
||||
objs = append(objs, pod)
|
||||
}
|
||||
fakeClient := fake.NewSimpleClientset(objs...)
|
||||
|
||||
handle, podEvictor, err := frameworktesting.InitFrameworkHandle(
|
||||
ctx,
|
||||
fakeClient,
|
||||
evictions.NewOptions().
|
||||
WithMaxPodsToEvictPerNode(tc.maxPodsToEvictPerNode).
|
||||
WithMaxPodsToEvictPerNamespace(tc.maxPodsToEvictPerNamespace).
|
||||
WithMaxPodsToEvictTotal(tc.maxPodsToEvictTotal),
|
||||
defaultevictor.DefaultEvictorArgs{IgnorePvcPods: tc.ignorePvcPods},
|
||||
nil,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to initialize a framework handle: %v", err)
|
||||
}
|
||||
|
||||
var evictedPods []string
|
||||
test.RegisterEvictedPodsCollector(fakeClient, &evictedPods)
|
||||
|
||||
plugin, err := New(ctx, tc.args, handle)
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to initialize the plugin: %v", err)
|
||||
}
|
||||
|
||||
plugin.(frameworktypes.DeschedulePlugin).Deschedule(ctx, tc.nodes)
|
||||
podsEvicted := podEvictor.TotalEvicted()
|
||||
if podsEvicted != tc.expectedEvictedPodCount {
|
||||
t.Errorf("Test error for description: %s. Expected evicted pods count %v, got %v", tc.description, tc.expectedEvictedPodCount, podsEvicted)
|
||||
}
|
||||
|
||||
if tc.expectedEvictedPods != nil {
|
||||
diff := sets.New(tc.expectedEvictedPods...).Difference(sets.New(evictedPods...))
|
||||
if diff.Len() > 0 {
|
||||
t.Errorf(
|
||||
"Expected pods %v to be evicted but %v were not evicted. Actual pods evicted: %v",
|
||||
tc.expectedEvictedPods,
|
||||
diff.UnsortedList(),
|
||||
evictedPods,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestPodLifeTime(t *testing.T) {
|
||||
var maxLifeTime uint = 600
|
||||
testCases := []podLifeTimeTestCase{
|
||||
{
|
||||
description: "Two pods in the default namespace, 1 is new and 1 very is old. 1 should be evicted.",
|
||||
description: "No pod should be evicted since pod terminating",
|
||||
args: &PodLifeTimeArgs{
|
||||
MaxPodLifeTimeSeconds: &maxLifeTime,
|
||||
LabelSelector: &metav1.LabelSelector{
|
||||
MatchLabels: map[string]string{"foo": "bar"},
|
||||
},
|
||||
},
|
||||
pods: []*v1.Pod{
|
||||
buildTestPodWithRSOwnerRefForNode1("p1", newerPodCreationTime, nil),
|
||||
buildTestPodWithRSOwnerRefForNode1("p2", olderPodCreationTime, nil),
|
||||
},
|
||||
nodes: []*v1.Node{buildTestNode1()},
|
||||
expectedEvictedPodCount: 1,
|
||||
expectedEvictedPods: []string{"p2"},
|
||||
},
|
||||
{
|
||||
description: "Two pods in the default namespace, 2 are new and 0 are old. 0 should be evicted.",
|
||||
args: &PodLifeTimeArgs{
|
||||
MaxPodLifeTimeSeconds: &maxLifeTime,
|
||||
},
|
||||
pods: []*v1.Pod{
|
||||
buildTestPodWithRSOwnerRefForNode1("p3", newerPodCreationTime, nil),
|
||||
buildTestPodWithRSOwnerRefForNode1("p4", newerPodCreationTime, nil),
|
||||
buildTestPodWithRSOwnerRefForNode1("p14", olderPodCreationTime, func(pod *v1.Pod) {
|
||||
pod.DeletionTimestamp = &metav1.Time{}
|
||||
}),
|
||||
buildTestPodWithRSOwnerRefForNode1("p15", olderPodCreationTime, func(pod *v1.Pod) {
|
||||
pod.DeletionTimestamp = &metav1.Time{}
|
||||
}),
|
||||
},
|
||||
nodes: []*v1.Node{buildTestNode1()},
|
||||
expectedEvictedPodCount: 0,
|
||||
},
|
||||
{
|
||||
description: "Two pods in the default namespace, 1 created 605 seconds ago. 1 should be evicted.",
|
||||
args: &PodLifeTimeArgs{
|
||||
MaxPodLifeTimeSeconds: &maxLifeTime,
|
||||
},
|
||||
pods: []*v1.Pod{
|
||||
buildTestPodWithRSOwnerRefForNode1("p5", newerPodCreationTime, nil),
|
||||
buildTestPodWithRSOwnerRefForNode1("p6", metav1.NewTime(time.Now().Add(-time.Second*605)), nil),
|
||||
},
|
||||
nodes: []*v1.Node{buildTestNode1()},
|
||||
expectedEvictedPodCount: 1,
|
||||
expectedEvictedPods: []string{"p6"},
|
||||
},
|
||||
{
|
||||
description: "Two pods in the default namespace, 1 created 595 seconds ago. 0 should be evicted.",
|
||||
args: &PodLifeTimeArgs{
|
||||
MaxPodLifeTimeSeconds: &maxLifeTime,
|
||||
},
|
||||
pods: []*v1.Pod{
|
||||
buildTestPodForNode1("p7", newerPodCreationTime, nil),
|
||||
buildTestPodForNode1("p8", metav1.NewTime(time.Now().Add(-time.Second*595)), nil),
|
||||
},
|
||||
nodes: []*v1.Node{buildTestNode1()},
|
||||
expectedEvictedPodCount: 0,
|
||||
},
|
||||
{
|
||||
description: "Two pods, one with ContainerCreating state. 1 should be evicted.",
|
||||
args: &PodLifeTimeArgs{
|
||||
MaxPodLifeTimeSeconds: &maxLifeTime,
|
||||
States: []string{"ContainerCreating"},
|
||||
},
|
||||
pods: []*v1.Pod{
|
||||
buildTestPodWithRSOwnerRefWithPendingPhaseForNode1("p9", olderPodCreationTime, nil),
|
||||
test.BuildTestPod("container-creating-stuck", 0, 0, nodeName1, func(pod *v1.Pod) {
|
||||
pod.Status.ContainerStatuses = []v1.ContainerStatus{
|
||||
{
|
||||
State: v1.ContainerState{
|
||||
Waiting: &v1.ContainerStateWaiting{Reason: "ContainerCreating"},
|
||||
},
|
||||
},
|
||||
}
|
||||
test.SetRSOwnerRef(pod)
|
||||
pod.ObjectMeta.CreationTimestamp = olderPodCreationTime
|
||||
}),
|
||||
},
|
||||
nodes: []*v1.Node{buildTestNode1()},
|
||||
expectedEvictedPodCount: 1,
|
||||
},
|
||||
{
|
||||
description: "Two pods, one with PodInitializing state. 1 should be evicted.",
|
||||
args: &PodLifeTimeArgs{
|
||||
MaxPodLifeTimeSeconds: &maxLifeTime,
|
||||
States: []string{"PodInitializing"},
|
||||
},
|
||||
pods: []*v1.Pod{
|
||||
buildTestPodWithRSOwnerRefWithPendingPhaseForNode1("p9", olderPodCreationTime, nil),
|
||||
test.BuildTestPod("pod-initializing-stuck", 0, 0, nodeName1, func(pod *v1.Pod) {
|
||||
pod.Status.ContainerStatuses = []v1.ContainerStatus{
|
||||
{
|
||||
State: v1.ContainerState{
|
||||
Waiting: &v1.ContainerStateWaiting{Reason: "PodInitializing"},
|
||||
},
|
||||
},
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.description, func(t *testing.T) {
|
||||
runPodLifeTimeTest(t, tc)
|
||||
})
|
||||
}
|
||||
test.SetRSOwnerRef(pod)
|
||||
pod.ObjectMeta.CreationTimestamp = olderPodCreationTime
|
||||
}),
|
||||
},
|
||||
nodes: []*v1.Node{buildTestNode1()},
|
||||
expectedEvictedPodCount: 1,
|
||||
},
|
||||
{
|
||||
description: "Two old pods with different states. 1 should be evicted.",
|
||||
args: &PodLifeTimeArgs{
|
||||
MaxPodLifeTimeSeconds: &maxLifeTime,
|
||||
States: []string{"Pending"},
|
||||
},
|
||||
pods: []*v1.Pod{
|
||||
buildTestPodWithRSOwnerRefWithPendingPhaseForNode1("p9", olderPodCreationTime, nil),
|
||||
buildTestPodWithRSOwnerRefForNode1("p10", olderPodCreationTime, func(pod *v1.Pod) {
|
||||
pod.Status.Phase = "Running"
|
||||
}),
|
||||
},
|
||||
nodes: []*v1.Node{buildTestNode1()},
|
||||
expectedEvictedPodCount: 1,
|
||||
expectedEvictedPods: []string{"p9"},
|
||||
},
|
||||
}
|
||||
|
||||
func TestPodLifeTime_EvictorConfiguration(t *testing.T) {
|
||||
var maxLifeTime uint = 600
|
||||
testCases := []podLifeTimeTestCase{
|
||||
{
|
||||
description: "Does not evict pvc pods with ignorePvcPods set to true",
|
||||
args: &PodLifeTimeArgs{
|
||||
@@ -235,6 +213,18 @@ func TestPodLifeTime(t *testing.T) {
|
||||
nodes: []*v1.Node{buildTestNode1()},
|
||||
expectedEvictedPodCount: 1,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.description, func(t *testing.T) {
|
||||
runPodLifeTimeTest(t, tc)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestPodLifeTime_GenericFiltering(t *testing.T) {
|
||||
var maxLifeTime uint = 600
|
||||
testCases := []podLifeTimeTestCase{
|
||||
{
|
||||
description: "1 pod matching label selector should be evicted",
|
||||
args: &PodLifeTimeArgs{
|
||||
@@ -255,25 +245,18 @@ func TestPodLifeTime(t *testing.T) {
|
||||
expectedEvictedPodCount: 1,
|
||||
expectedEvictedPods: []string{"p12"},
|
||||
},
|
||||
{
|
||||
description: "No pod should be evicted since pod terminating",
|
||||
args: &PodLifeTimeArgs{
|
||||
MaxPodLifeTimeSeconds: &maxLifeTime,
|
||||
LabelSelector: &metav1.LabelSelector{
|
||||
MatchLabels: map[string]string{"foo": "bar"},
|
||||
},
|
||||
},
|
||||
pods: []*v1.Pod{
|
||||
buildTestPodWithRSOwnerRefForNode1("p14", olderPodCreationTime, func(pod *v1.Pod) {
|
||||
pod.DeletionTimestamp = &metav1.Time{}
|
||||
}),
|
||||
buildTestPodWithRSOwnerRefForNode1("p15", olderPodCreationTime, func(pod *v1.Pod) {
|
||||
pod.DeletionTimestamp = &metav1.Time{}
|
||||
}),
|
||||
},
|
||||
nodes: []*v1.Node{buildTestNode1()},
|
||||
expectedEvictedPodCount: 0,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.description, func(t *testing.T) {
|
||||
runPodLifeTimeTest(t, tc)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestPodLifeTime_EvictionLimits(t *testing.T) {
|
||||
var maxLifeTime uint = 600
|
||||
testCases := []podLifeTimeTestCase{
|
||||
{
|
||||
description: "2 Oldest pods should be evicted when maxPodsToEvictPerNode and maxPodsToEvictPerNamespace are not set",
|
||||
args: &PodLifeTimeArgs{
|
||||
@@ -333,6 +316,64 @@ func TestPodLifeTime(t *testing.T) {
|
||||
expectedEvictedPodCount: 1,
|
||||
expectedEvictedPods: []string{"p2"},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.description, func(t *testing.T) {
|
||||
runPodLifeTimeTest(t, tc)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestPodLifeTime_ContainerWaitingReasons(t *testing.T) {
|
||||
var maxLifeTime uint = 600
|
||||
testCases := []podLifeTimeTestCase{
|
||||
{
|
||||
description: "Two pods, one with ContainerCreating state. 1 should be evicted.",
|
||||
args: &PodLifeTimeArgs{
|
||||
MaxPodLifeTimeSeconds: &maxLifeTime,
|
||||
States: []string{"ContainerCreating"},
|
||||
},
|
||||
pods: []*v1.Pod{
|
||||
buildTestPodWithRSOwnerRefWithPendingPhaseForNode1("p9", olderPodCreationTime, nil),
|
||||
test.BuildTestPod("container-creating-stuck", 0, 0, nodeName1, func(pod *v1.Pod) {
|
||||
pod.Status.ContainerStatuses = []v1.ContainerStatus{
|
||||
{
|
||||
State: v1.ContainerState{
|
||||
Waiting: &v1.ContainerStateWaiting{Reason: "ContainerCreating"},
|
||||
},
|
||||
},
|
||||
}
|
||||
test.SetRSOwnerRef(pod)
|
||||
pod.ObjectMeta.CreationTimestamp = olderPodCreationTime
|
||||
}),
|
||||
},
|
||||
nodes: []*v1.Node{buildTestNode1()},
|
||||
expectedEvictedPodCount: 1,
|
||||
},
|
||||
{
|
||||
description: "Two pods, one with PodInitializing state. 1 should be evicted.",
|
||||
args: &PodLifeTimeArgs{
|
||||
MaxPodLifeTimeSeconds: &maxLifeTime,
|
||||
States: []string{"PodInitializing"},
|
||||
},
|
||||
pods: []*v1.Pod{
|
||||
buildTestPodWithRSOwnerRefWithPendingPhaseForNode1("p9", olderPodCreationTime, nil),
|
||||
test.BuildTestPod("pod-initializing-stuck", 0, 0, nodeName1, func(pod *v1.Pod) {
|
||||
pod.Status.ContainerStatuses = []v1.ContainerStatus{
|
||||
{
|
||||
State: v1.ContainerState{
|
||||
Waiting: &v1.ContainerStateWaiting{Reason: "PodInitializing"},
|
||||
},
|
||||
},
|
||||
}
|
||||
test.SetRSOwnerRef(pod)
|
||||
pod.ObjectMeta.CreationTimestamp = olderPodCreationTime
|
||||
}),
|
||||
},
|
||||
nodes: []*v1.Node{buildTestNode1()},
|
||||
expectedEvictedPodCount: 1,
|
||||
},
|
||||
{
|
||||
description: "1 pod with container status ImagePullBackOff should be evicted",
|
||||
args: &PodLifeTimeArgs{
|
||||
@@ -535,6 +576,38 @@ func TestPodLifeTime(t *testing.T) {
|
||||
nodes: []*v1.Node{buildTestNode1()},
|
||||
expectedEvictedPodCount: 1,
|
||||
},
|
||||
{
|
||||
description: "1 pod with ImagePullBackOff status should be ignored when States filter is ContainerCreating",
|
||||
args: &PodLifeTimeArgs{
|
||||
MaxPodLifeTimeSeconds: &maxLifeTime,
|
||||
States: []string{"ContainerCreating"},
|
||||
},
|
||||
pods: []*v1.Pod{
|
||||
buildTestPodWithRSOwnerRefWithPendingPhaseForNode1("p9", olderPodCreationTime, func(pod *v1.Pod) {
|
||||
pod.Status.ContainerStatuses = []v1.ContainerStatus{
|
||||
{
|
||||
State: v1.ContainerState{
|
||||
Waiting: &v1.ContainerStateWaiting{Reason: "ImagePullBackOff"},
|
||||
},
|
||||
},
|
||||
}
|
||||
}),
|
||||
},
|
||||
nodes: []*v1.Node{buildTestNode1()},
|
||||
expectedEvictedPodCount: 0,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.description, func(t *testing.T) {
|
||||
runPodLifeTimeTest(t, tc)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestPodLifeTime_PodStatusReasons(t *testing.T) {
|
||||
var maxLifeTime uint = 600
|
||||
testCases := []podLifeTimeTestCase{
|
||||
{
|
||||
description: "1 pod with pod status reason NodeLost should be evicted",
|
||||
args: &PodLifeTimeArgs{
|
||||
@@ -591,6 +664,96 @@ func TestPodLifeTime(t *testing.T) {
|
||||
nodes: []*v1.Node{buildTestNode1()},
|
||||
expectedEvictedPodCount: 1,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.description, func(t *testing.T) {
|
||||
runPodLifeTimeTest(t, tc)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestPodLifeTime_AgeThreshold(t *testing.T) {
|
||||
var maxLifeTime uint = 600
|
||||
testCases := []podLifeTimeTestCase{
|
||||
{
|
||||
description: "Two pods in the default namespace, 1 is new and 1 very is old. 1 should be evicted.",
|
||||
args: &PodLifeTimeArgs{
|
||||
MaxPodLifeTimeSeconds: &maxLifeTime,
|
||||
},
|
||||
pods: []*v1.Pod{
|
||||
buildTestPodWithRSOwnerRefForNode1("p1", newerPodCreationTime, nil),
|
||||
buildTestPodWithRSOwnerRefForNode1("p2", olderPodCreationTime, nil),
|
||||
},
|
||||
nodes: []*v1.Node{buildTestNode1()},
|
||||
expectedEvictedPodCount: 1,
|
||||
expectedEvictedPods: []string{"p2"},
|
||||
},
|
||||
{
|
||||
description: "Two pods in the default namespace, 2 are new and 0 are old. 0 should be evicted.",
|
||||
args: &PodLifeTimeArgs{
|
||||
MaxPodLifeTimeSeconds: &maxLifeTime,
|
||||
},
|
||||
pods: []*v1.Pod{
|
||||
buildTestPodWithRSOwnerRefForNode1("p3", newerPodCreationTime, nil),
|
||||
buildTestPodWithRSOwnerRefForNode1("p4", newerPodCreationTime, nil),
|
||||
},
|
||||
nodes: []*v1.Node{buildTestNode1()},
|
||||
expectedEvictedPodCount: 0,
|
||||
},
|
||||
{
|
||||
description: "Two pods in the default namespace, 1 created 605 seconds ago. 1 should be evicted.",
|
||||
args: &PodLifeTimeArgs{
|
||||
MaxPodLifeTimeSeconds: &maxLifeTime,
|
||||
},
|
||||
pods: []*v1.Pod{
|
||||
buildTestPodWithRSOwnerRefForNode1("p5", newerPodCreationTime, nil),
|
||||
buildTestPodWithRSOwnerRefForNode1("p6", metav1.NewTime(time.Now().Add(-time.Second*605)), nil),
|
||||
},
|
||||
nodes: []*v1.Node{buildTestNode1()},
|
||||
expectedEvictedPodCount: 1,
|
||||
expectedEvictedPods: []string{"p6"},
|
||||
},
|
||||
{
|
||||
description: "Two pods in the default namespace, 1 created 595 seconds ago. 0 should be evicted.",
|
||||
args: &PodLifeTimeArgs{
|
||||
MaxPodLifeTimeSeconds: &maxLifeTime,
|
||||
},
|
||||
pods: []*v1.Pod{
|
||||
buildTestPodForNode1("p7", newerPodCreationTime, nil),
|
||||
buildTestPodForNode1("p8", metav1.NewTime(time.Now().Add(-time.Second*595)), nil),
|
||||
},
|
||||
nodes: []*v1.Node{buildTestNode1()},
|
||||
expectedEvictedPodCount: 0,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.description, func(t *testing.T) {
|
||||
runPodLifeTimeTest(t, tc)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestPodLifeTime_PodPhaseStates(t *testing.T) {
|
||||
var maxLifeTime uint = 600
|
||||
testCases := []podLifeTimeTestCase{
|
||||
{
|
||||
description: "Two old pods with different states. 1 should be evicted.",
|
||||
args: &PodLifeTimeArgs{
|
||||
MaxPodLifeTimeSeconds: &maxLifeTime,
|
||||
States: []string{"Pending"},
|
||||
},
|
||||
pods: []*v1.Pod{
|
||||
buildTestPodWithRSOwnerRefWithPendingPhaseForNode1("p9", olderPodCreationTime, nil),
|
||||
buildTestPodWithRSOwnerRefForNode1("p10", olderPodCreationTime, func(pod *v1.Pod) {
|
||||
pod.Status.Phase = "Running"
|
||||
}),
|
||||
},
|
||||
nodes: []*v1.Node{buildTestNode1()},
|
||||
expectedEvictedPodCount: 1,
|
||||
expectedEvictedPods: []string{"p9"},
|
||||
},
|
||||
{
|
||||
description: "1 pod with pod status phase v1.PodSucceeded should be evicted",
|
||||
args: &PodLifeTimeArgs{
|
||||
@@ -633,81 +796,11 @@ func TestPodLifeTime(t *testing.T) {
|
||||
nodes: []*v1.Node{buildTestNode1()},
|
||||
expectedEvictedPodCount: 1,
|
||||
},
|
||||
{
|
||||
description: "1 pod with ImagePullBackOff status should be ignored when States filter is ContainerCreating",
|
||||
args: &PodLifeTimeArgs{
|
||||
MaxPodLifeTimeSeconds: &maxLifeTime,
|
||||
States: []string{"ContainerCreating"},
|
||||
},
|
||||
pods: []*v1.Pod{
|
||||
buildTestPodWithRSOwnerRefWithPendingPhaseForNode1("p9", olderPodCreationTime, func(pod *v1.Pod) {
|
||||
pod.Status.ContainerStatuses = []v1.ContainerStatus{
|
||||
{
|
||||
State: v1.ContainerState{
|
||||
Waiting: &v1.ContainerStateWaiting{Reason: "ImagePullBackOff"},
|
||||
},
|
||||
},
|
||||
}
|
||||
}),
|
||||
},
|
||||
nodes: []*v1.Node{buildTestNode1()},
|
||||
expectedEvictedPodCount: 0,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.description, func(t *testing.T) {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
var objs []runtime.Object
|
||||
for _, node := range tc.nodes {
|
||||
objs = append(objs, node)
|
||||
}
|
||||
for _, pod := range tc.pods {
|
||||
objs = append(objs, pod)
|
||||
}
|
||||
fakeClient := fake.NewSimpleClientset(objs...)
|
||||
|
||||
handle, podEvictor, err := frameworktesting.InitFrameworkHandle(
|
||||
ctx,
|
||||
fakeClient,
|
||||
evictions.NewOptions().
|
||||
WithMaxPodsToEvictPerNode(tc.maxPodsToEvictPerNode).
|
||||
WithMaxPodsToEvictPerNamespace(tc.maxPodsToEvictPerNamespace).
|
||||
WithMaxPodsToEvictTotal(tc.maxPodsToEvictTotal),
|
||||
defaultevictor.DefaultEvictorArgs{IgnorePvcPods: tc.ignorePvcPods},
|
||||
nil,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to initialize a framework handle: %v", err)
|
||||
}
|
||||
|
||||
var evictedPods []string
|
||||
test.RegisterEvictedPodsCollector(fakeClient, &evictedPods)
|
||||
|
||||
plugin, err := New(ctx, tc.args, handle)
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to initialize the plugin: %v", err)
|
||||
}
|
||||
|
||||
plugin.(frameworktypes.DeschedulePlugin).Deschedule(ctx, tc.nodes)
|
||||
podsEvicted := podEvictor.TotalEvicted()
|
||||
if podsEvicted != tc.expectedEvictedPodCount {
|
||||
t.Errorf("Test error for description: %s. Expected evicted pods count %v, got %v", tc.description, tc.expectedEvictedPodCount, podsEvicted)
|
||||
}
|
||||
|
||||
if tc.expectedEvictedPods != nil {
|
||||
diff := sets.New(tc.expectedEvictedPods...).Difference(sets.New(evictedPods...))
|
||||
if diff.Len() > 0 {
|
||||
t.Errorf(
|
||||
"Expected pods %v to be evicted but %v were not evicted. Actual pods evicted: %v",
|
||||
tc.expectedEvictedPods,
|
||||
diff.UnsortedList(),
|
||||
evictedPods,
|
||||
)
|
||||
}
|
||||
}
|
||||
runPodLifeTimeTest(t, tc)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user