Skip to content

Commit a2b1fc0

Browse files
committed
Move PodRejectionStatus into e2e/node from e2e/common/node
1 parent 6da0175 commit a2b1fc0

File tree

3 files changed

+111
-80
lines changed

3 files changed

+111
-80
lines changed

test/e2e/common/node/pod_admission.go

Lines changed: 0 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,8 @@ import (
2020
"context"
2121

2222
"github.com/onsi/ginkgo/v2"
23-
"github.com/onsi/gomega"
2423

2524
v1 "k8s.io/api/core/v1"
26-
"k8s.io/apimachinery/pkg/api/resource"
2725
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2826
"k8s.io/apimachinery/pkg/labels"
2927
"k8s.io/kubernetes/test/e2e/framework"
@@ -67,83 +65,6 @@ var _ = SIGDescribe("PodOSRejection", framework.WithNodeConformance(), func() {
6765
})
6866
})
6967

70-
var _ = SIGDescribe("PodRejectionStatus", func() {
71-
f := framework.NewDefaultFramework("pod-rejection-status")
72-
f.NamespacePodSecurityLevel = admissionapi.LevelBaseline
73-
ginkgo.Context("Kubelet", func() {
74-
ginkgo.It("should reject pod when the node didn't have enough resource", func(ctx context.Context) {
75-
node, err := e2enode.GetRandomReadySchedulableNode(ctx, f.ClientSet)
76-
framework.ExpectNoError(err, "Failed to get a ready schedulable node")
77-
78-
// Create a pod that requests more CPU than the node has
79-
pod := &v1.Pod{
80-
ObjectMeta: metav1.ObjectMeta{
81-
Name: "pod-out-of-cpu",
82-
Namespace: f.Namespace.Name,
83-
},
84-
Spec: v1.PodSpec{
85-
Containers: []v1.Container{
86-
{
87-
Name: "pod-out-of-cpu",
88-
Image: imageutils.GetPauseImageName(),
89-
Resources: v1.ResourceRequirements{
90-
Requests: v1.ResourceList{
91-
v1.ResourceCPU: resource.MustParse("1000000000000"), // requests more CPU than any node has
92-
},
93-
},
94-
},
95-
},
96-
},
97-
}
98-
99-
pod = e2epod.NewPodClient(f).Create(ctx, pod)
100-
101-
// Wait for the scheduler to update the pod status
102-
err = e2epod.WaitForPodNameUnschedulableInNamespace(ctx, f.ClientSet, pod.Name, pod.Namespace)
103-
framework.ExpectNoError(err)
104-
105-
// Fetch the pod to get the latest status which should be last one observed by the scheduler
106-
// before it rejected the pod
107-
pod, err = f.ClientSet.CoreV1().Pods(pod.Namespace).Get(ctx, pod.Name, metav1.GetOptions{})
108-
framework.ExpectNoError(err)
109-
110-
// force assign the Pod to a node in order to get rejection status later
111-
binding := &v1.Binding{
112-
ObjectMeta: metav1.ObjectMeta{
113-
Name: pod.Name,
114-
Namespace: pod.Namespace,
115-
UID: pod.UID,
116-
},
117-
Target: v1.ObjectReference{
118-
Kind: "Node",
119-
Name: node.Name,
120-
},
121-
}
122-
err = f.ClientSet.CoreV1().Pods(pod.Namespace).Bind(ctx, binding, metav1.CreateOptions{})
123-
framework.ExpectNoError(err)
124-
125-
// kubelet has rejected the pod
126-
err = e2epod.WaitForPodFailedReason(ctx, f.ClientSet, pod, "OutOfcpu", f.Timeouts.PodStartShort)
127-
framework.ExpectNoError(err)
128-
129-
// fetch the reject Pod and compare the status
130-
gotPod, err := f.ClientSet.CoreV1().Pods(pod.Namespace).Get(ctx, pod.Name, metav1.GetOptions{})
131-
framework.ExpectNoError(err)
132-
133-
// This detects if there are any new fields in Status that were dropped by the pod rejection.
134-
// These new fields either should be kept by kubelet's admission or added explicitly in the list of fields that are having a different value or must be cleared.
135-
expectedStatus := pod.Status.DeepCopy()
136-
expectedStatus.Phase = gotPod.Status.Phase
137-
expectedStatus.Conditions = nil
138-
expectedStatus.Message = gotPod.Status.Message
139-
expectedStatus.Reason = gotPod.Status.Reason
140-
expectedStatus.StartTime = gotPod.Status.StartTime
141-
// expectedStatus.QOSClass keep it as is
142-
gomega.Expect(gotPod.Status).To(gomega.Equal(*expectedStatus))
143-
})
144-
})
145-
})
146-
14768
// findLinuxNode finds a Linux node that is Ready and Schedulable
14869
func findLinuxNode(ctx context.Context, f *framework.Framework) (v1.Node, error) {
14970
selector := labels.Set{"kubernetes.io/os": "linux"}.AsSelector()

test/e2e/framework/pod/wait.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -498,7 +498,7 @@ func WaitForPodNameUnschedulableInNamespace(ctx context.Context, c clientset.Int
498498
}
499499
}
500500
if pod.Status.Phase == v1.PodRunning || pod.Status.Phase == v1.PodSucceeded || pod.Status.Phase == v1.PodFailed {
501-
return true, fmt.Errorf("Expected pod %q in namespace %q to be in phase Pending, but got phase: %v, pod: \n%s", podName, namespace, pod.Status.Phase, format.Object(pod, 1))
501+
return true, fmt.Errorf("Expected pod %q in namespace %q to be in phase Pending, but got phase: %v", podName, namespace, pod.Status.Phase)
502502
}
503503
return false, nil
504504
})

test/e2e/node/pod_admission.go

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
/*
2+
Copyright 2024 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package node
18+
19+
import (
20+
"context"
21+
22+
"github.com/onsi/ginkgo/v2"
23+
"github.com/onsi/gomega"
24+
v1 "k8s.io/api/core/v1"
25+
"k8s.io/apimachinery/pkg/api/resource"
26+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
27+
"k8s.io/kubernetes/test/e2e/framework"
28+
e2enode "k8s.io/kubernetes/test/e2e/framework/node"
29+
e2epod "k8s.io/kubernetes/test/e2e/framework/pod"
30+
imageutils "k8s.io/kubernetes/test/utils/image"
31+
admissionapi "k8s.io/pod-security-admission/api"
32+
)
33+
34+
var _ = SIGDescribe("PodRejectionStatus", func() {
35+
f := framework.NewDefaultFramework("pod-rejection-status")
36+
f.NamespacePodSecurityLevel = admissionapi.LevelBaseline
37+
ginkgo.Context("Kubelet", func() {
38+
ginkgo.It("should reject pod when the node didn't have enough resource", func(ctx context.Context) {
39+
node, err := e2enode.GetRandomReadySchedulableNode(ctx, f.ClientSet)
40+
framework.ExpectNoError(err, "Failed to get a ready schedulable node")
41+
42+
// Create a pod that requests more CPU than the node has
43+
pod := &v1.Pod{
44+
ObjectMeta: metav1.ObjectMeta{
45+
Name: "pod-out-of-cpu",
46+
Namespace: f.Namespace.Name,
47+
},
48+
Spec: v1.PodSpec{
49+
Containers: []v1.Container{
50+
{
51+
Name: "pod-out-of-cpu",
52+
Image: imageutils.GetPauseImageName(),
53+
Resources: v1.ResourceRequirements{
54+
Requests: v1.ResourceList{
55+
v1.ResourceCPU: resource.MustParse("1000000000000"), // requests more CPU than any node has
56+
},
57+
},
58+
},
59+
},
60+
},
61+
}
62+
63+
pod, err = f.ClientSet.CoreV1().Pods(f.Namespace.Name).Create(ctx, pod, metav1.CreateOptions{})
64+
framework.ExpectNoError(err)
65+
66+
// Wait for the scheduler to update the pod status
67+
err = e2epod.WaitForPodNameUnschedulableInNamespace(ctx, f.ClientSet, pod.Name, pod.Namespace)
68+
framework.ExpectNoError(err)
69+
70+
// Fetch the pod to get the latest status which should be last one observed by the scheduler
71+
// before it rejected the pod
72+
pod, err = f.ClientSet.CoreV1().Pods(pod.Namespace).Get(ctx, pod.Name, metav1.GetOptions{})
73+
framework.ExpectNoError(err)
74+
75+
// force assign the Pod to a node in order to get rejection status later
76+
binding := &v1.Binding{
77+
ObjectMeta: metav1.ObjectMeta{
78+
Name: pod.Name,
79+
Namespace: pod.Namespace,
80+
UID: pod.UID,
81+
},
82+
Target: v1.ObjectReference{
83+
Kind: "Node",
84+
Name: node.Name,
85+
},
86+
}
87+
err = f.ClientSet.CoreV1().Pods(pod.Namespace).Bind(ctx, binding, metav1.CreateOptions{})
88+
framework.ExpectNoError(err)
89+
90+
// kubelet has rejected the pod
91+
err = e2epod.WaitForPodFailedReason(ctx, f.ClientSet, pod, "OutOfcpu", f.Timeouts.PodStartShort)
92+
framework.ExpectNoError(err)
93+
94+
// fetch the reject Pod and compare the status
95+
gotPod, err := f.ClientSet.CoreV1().Pods(pod.Namespace).Get(ctx, pod.Name, metav1.GetOptions{})
96+
framework.ExpectNoError(err)
97+
98+
// This detects if there are any new fields in Status that were dropped by the pod rejection.
99+
// These new fields either should be kept by kubelet's admission or added explicitly in the list of fields that are having a different value or must be cleared.
100+
expectedStatus := pod.Status.DeepCopy()
101+
expectedStatus.Phase = gotPod.Status.Phase
102+
expectedStatus.Conditions = nil
103+
expectedStatus.Message = gotPod.Status.Message
104+
expectedStatus.Reason = gotPod.Status.Reason
105+
expectedStatus.StartTime = gotPod.Status.StartTime
106+
// expectedStatus.QOSClass keep it as is
107+
gomega.Expect(gotPod.Status).To(gomega.Equal(*expectedStatus))
108+
})
109+
})
110+
})

0 commit comments

Comments
 (0)