From aeafb4d149d3df48fccda523a151fc7e488f19d5 Mon Sep 17 00:00:00 2001 From: toshikish Date: Thu, 19 Sep 2024 14:54:32 +0900 Subject: [PATCH] Add integration test for NodeUnschedulable in requeueing scenarios --- test/integration/scheduler/queue_test.go | 54 +++++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/test/integration/scheduler/queue_test.go b/test/integration/scheduler/queue_test.go index 8b06c08476b..9a377533449 100644 --- a/test/integration/scheduler/queue_test.go +++ b/test/integration/scheduler/queue_test.go @@ -188,7 +188,7 @@ func TestSchedulingGates(t *testing.T) { func TestCoreResourceEnqueue(t *testing.T) { tests := []struct { name string - // initialNode is the Node to be created at first. + // initialNodes is the list of Nodes to be created at first. initialNodes []*v1.Node // initialPods is the list of Pods to be created at first if it's not empty. // Note that the scheduler won't schedule those Pods, @@ -486,6 +486,58 @@ func TestCoreResourceEnqueue(t *testing.T) { wantRequeuedPods: sets.New("pod2"), enableSchedulingQueueHint: []bool{true}, }, + { + name: "Pod rejected by the NodeUnschedulable plugin is requeued when the node is turned to ready", + initialNodes: []*v1.Node{st.MakeNode().Name("fake-node").Unschedulable(true).Obj()}, + pods: []*v1.Pod{ + st.MakePod().Name("pod1").Container("image").Obj(), + }, + triggerFn: func(testCtx *testutils.TestContext) error { + // Trigger a NodeUpdate event to change the Node to ready. + // It makes Pod1 schedulable. + if _, err := testCtx.ClientSet.CoreV1().Nodes().Update(testCtx.Ctx, st.MakeNode().Name("fake-node").Unschedulable(false).Obj(), metav1.UpdateOptions{}); err != nil { + return fmt.Errorf("failed to update the node: %w", err) + } + return nil + }, + wantRequeuedPods: sets.New("pod1"), + }, + { + name: "Pod rejected by the NodeUnschedulable plugin is requeued when a new node is created", + initialNodes: []*v1.Node{st.MakeNode().Name("fake-node1").Unschedulable(true).Obj()}, + pods: []*v1.Pod{ + st.MakePod().Name("pod1").Container("image").Obj(), + }, + triggerFn: func(testCtx *testutils.TestContext) error { + // Trigger a NodeCreated event. + // It makes Pod1 schedulable. + node := st.MakeNode().Name("fake-node2").Obj() + if _, err := testCtx.ClientSet.CoreV1().Nodes().Create(testCtx.Ctx, node, metav1.CreateOptions{}); err != nil { + return fmt.Errorf("failed to create a new node: %w", err) + } + return nil + }, + wantRequeuedPods: sets.New("pod1"), + }, + { + name: "Pod rejected by the NodeUnschedulable plugin isn't requeued when another unschedulable node is created", + initialNodes: []*v1.Node{st.MakeNode().Name("fake-node1").Unschedulable(true).Obj()}, + pods: []*v1.Pod{ + st.MakePod().Name("pod1").Container("image").Obj(), + }, + triggerFn: func(testCtx *testutils.TestContext) error { + // Trigger a NodeCreated event, but with unschedulable node, which wouldn't make Pod1 schedulable. + node := st.MakeNode().Name("fake-node2").Unschedulable(true).Obj() + if _, err := testCtx.ClientSet.CoreV1().Nodes().Create(testCtx.Ctx, node, metav1.CreateOptions{}); err != nil { + return fmt.Errorf("failed to create a new node: %w", err) + } + return nil + }, + wantRequeuedPods: sets.Set[string]{}, + // This test case is valid only when QHint is enabled + // because QHint filters out a node creation made in triggerFn. + enableSchedulingQueueHint: []bool{true}, + }, { name: "Pods with PodTopologySpread should be requeued when a Pod with matching label is scheduled", initialNodes: []*v1.Node{st.MakeNode().Name("fake-node").Label("node", "fake-node").Capacity(map[v1.ResourceName]string{v1.ResourceCPU: "2"}).Obj()},