1
16
17 package pod_test
18
19 import (
20 "context"
21 "fmt"
22 "regexp"
23 "testing"
24 "time"
25
26 "github.com/onsi/ginkgo/v2"
27 "github.com/onsi/ginkgo/v2/reporters"
28 "github.com/onsi/gomega"
29
30 v1 "k8s.io/api/core/v1"
31 apierrors "k8s.io/apimachinery/pkg/api/errors"
32 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
33 "k8s.io/client-go/kubernetes/fake"
34 "k8s.io/kubernetes/test/e2e/framework"
35 "k8s.io/kubernetes/test/e2e/framework/internal/output"
36 e2epod "k8s.io/kubernetes/test/e2e/framework/pod"
37 _ "k8s.io/kubernetes/test/utils/format"
38 )
39
40
41
42
43
44
45
46
47
48
49
50
51
52 var _ = ginkgo.Describe("pod", func() {
53 ginkgo.It("not found, must exist", func(ctx context.Context) {
54 gomega.Eventually(ctx, framework.HandleRetry(getNoSuchPod)).WithTimeout(timeout).Should(e2epod.BeInPhase(v1.PodRunning))
55 })
56
57 ginkgo.It("not found, retry", func(ctx context.Context) {
58 framework.ExpectNoError(e2epod.WaitTimeoutForPodRunningInNamespace(ctx, clientSet, "no-such-pod", "default", timeout))
59 })
60
61 ginkgo.It("not found, retry with wrappers", func(ctx context.Context) {
62 gomega.Eventually(ctx, framework.RetryNotFound(framework.HandleRetry(getNoSuchPod))).WithTimeout(timeout).Should(e2epod.BeInPhase(v1.PodRunning))
63 })
64
65 ginkgo.It("not found, retry with inverted wrappers", func(ctx context.Context) {
66 gomega.Eventually(ctx, framework.HandleRetry(framework.RetryNotFound(getNoSuchPod))).WithTimeout(timeout).Should(e2epod.BeInPhase(v1.PodRunning))
67 })
68
69 ginkgo.It("not running", func(ctx context.Context) {
70 ginkgo.By(fmt.Sprintf("waiting for pod %s to run", podName))
71 framework.ExpectNoError(e2epod.WaitTimeoutForPodRunningInNamespace(ctx, clientSet, podName, podNamespace, timeout))
72 })
73
74 ginkgo.It("failed", func(ctx context.Context) {
75 framework.ExpectNoError(e2epod.WaitTimeoutForPodRunningInNamespace(ctx, clientSet, failedPodName, podNamespace, timeout))
76 })
77
78 ginkgo.It("gets reported with API error", func(ctx context.Context) {
79 called := false
80 getPod := func(ctx context.Context) (*v1.Pod, error) {
81 if called {
82 ginkgo.By("returning fake API error")
83 return nil, apierrors.NewTooManyRequests("fake API error", 10)
84 }
85 called = true
86 pod, err := clientSet.CoreV1().Pods(podNamespace).Get(ctx, podName, metav1.GetOptions{})
87 if err != nil {
88 return nil, err
89 }
90 ginkgo.By("returning pod")
91 return pod, err
92 }
93 gomega.Eventually(ctx, framework.HandleRetry(getPod)).WithTimeout(5 * timeout).Should(e2epod.BeInPhase(v1.PodRunning))
94 })
95 })
96
97 func getNoSuchPod(ctx context.Context) (*v1.Pod, error) {
98 return clientSet.CoreV1().Pods("default").Get(ctx, "no-such-pod", metav1.GetOptions{})
99 }
100
101 const (
102 podName = "pending-pod"
103 podNamespace = "default"
104 failedPodName = "failed-pod"
105 timeout = time.Second
106 )
107
108 var (
109 clientSet = fake.NewSimpleClientset(
110 &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: podName, Namespace: podNamespace}, Status: v1.PodStatus{Phase: v1.PodPending}},
111 &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: failedPodName, Namespace: podNamespace}, Status: v1.PodStatus{Phase: v1.PodFailed}},
112 )
113 )
114
115 func TestFailureOutput(t *testing.T) {
116
117 expected := output.TestResult{
118 NormalizeOutput: func(in string) string {
119 return regexp.MustCompile(`wait.go:[[:digit:]]*`).ReplaceAllString(in, `wait.go`)
120 },
121 Suite: reporters.JUnitTestSuite{
122 Tests: 7,
123 Failures: 7,
124 Errors: 0,
125 Disabled: 0,
126 Skipped: 0,
127 TestCases: []reporters.JUnitTestCase{
128 {
129 Name: "[It] pod not found, must exist",
130 Status: "failed",
131 Failure: &reporters.JUnitFailure{
132 Type: "failed",
133 Description: `[FAILED] Told to stop trying after <after>.
134 Unexpected final error while getting *v1.Pod: pods "no-such-pod" not found
135 In [It] at: wait_test.go:54 <time>
136 `,
137 },
138 SystemErr: `> Enter [It] not found, must exist - wait_test.go:53 <time>
139 [FAILED] Told to stop trying after <after>.
140 Unexpected final error while getting *v1.Pod: pods "no-such-pod" not found
141 In [It] at: wait_test.go:54 <time>
142 < Exit [It] not found, must exist - wait_test.go:53 <time>
143 `,
144 },
145 {
146 Name: "[It] pod not found, retry",
147 Status: "failed",
148 Failure: &reporters.JUnitFailure{
149 Type: "failed",
150 Description: `[FAILED] Timed out after <after>.
151 The function passed to Eventually returned the following error:
152 <framework.transientError>:
153 pods "no-such-pod" not found
154 {
155 error: <*errors.StatusError>{
156 ErrStatus: {
157 TypeMeta: {Kind: "", APIVersion: ""},
158 ListMeta: {
159 SelfLink: "",
160 ResourceVersion: "",
161 Continue: "",
162 RemainingItemCount: nil,
163 },
164 Status: "Failure",
165 Message: "pods \"no-such-pod\" not found",
166 Reason: "NotFound",
167 Details: {Name: "no-such-pod", Group: "", Kind: "pods", UID: "", Causes: nil, RetryAfterSeconds: 0},
168 Code: 404,
169 },
170 },
171 }
172 In [It] at: wait_test.go:58 <time>
173 `,
174 },
175 SystemErr: `> Enter [It] not found, retry - wait_test.go:57 <time>
176 <klog> wait_test.go:58] Failed inside E2E framework:
177 k8s.io/kubernetes/test/e2e/framework/pod.WaitTimeoutForPodRunningInNamespace()
178 wait.go
179 k8s.io/kubernetes/test/e2e/framework/pod_test.glob..func1.2()
180 wait_test.go:58
181 [FAILED] Timed out after <after>.
182 The function passed to Eventually returned the following error:
183 <framework.transientError>:
184 pods "no-such-pod" not found
185 {
186 error: <*errors.StatusError>{
187 ErrStatus: {
188 TypeMeta: {Kind: "", APIVersion: ""},
189 ListMeta: {
190 SelfLink: "",
191 ResourceVersion: "",
192 Continue: "",
193 RemainingItemCount: nil,
194 },
195 Status: "Failure",
196 Message: "pods \"no-such-pod\" not found",
197 Reason: "NotFound",
198 Details: {Name: "no-such-pod", Group: "", Kind: "pods", UID: "", Causes: nil, RetryAfterSeconds: 0},
199 Code: 404,
200 },
201 },
202 }
203 In [It] at: wait_test.go:58 <time>
204 < Exit [It] not found, retry - wait_test.go:57 <time>
205 `,
206 },
207 {
208 Name: "[It] pod not found, retry with wrappers",
209 Status: "failed",
210 Failure: &reporters.JUnitFailure{
211 Type: "failed",
212 Description: `[FAILED] Timed out after <after>.
213 The function passed to Eventually returned the following error:
214 <framework.transientError>:
215 pods "no-such-pod" not found
216 {
217 error: <*errors.StatusError>{
218 ErrStatus: {
219 TypeMeta: {Kind: "", APIVersion: ""},
220 ListMeta: {
221 SelfLink: "",
222 ResourceVersion: "",
223 Continue: "",
224 RemainingItemCount: nil,
225 },
226 Status: "Failure",
227 Message: "pods \"no-such-pod\" not found",
228 Reason: "NotFound",
229 Details: {Name: "no-such-pod", Group: "", Kind: "pods", UID: "", Causes: nil, RetryAfterSeconds: 0},
230 Code: 404,
231 },
232 },
233 }
234 In [It] at: wait_test.go:62 <time>
235 `,
236 },
237 SystemErr: `> Enter [It] not found, retry with wrappers - wait_test.go:61 <time>
238 [FAILED] Timed out after <after>.
239 The function passed to Eventually returned the following error:
240 <framework.transientError>:
241 pods "no-such-pod" not found
242 {
243 error: <*errors.StatusError>{
244 ErrStatus: {
245 TypeMeta: {Kind: "", APIVersion: ""},
246 ListMeta: {
247 SelfLink: "",
248 ResourceVersion: "",
249 Continue: "",
250 RemainingItemCount: nil,
251 },
252 Status: "Failure",
253 Message: "pods \"no-such-pod\" not found",
254 Reason: "NotFound",
255 Details: {Name: "no-such-pod", Group: "", Kind: "pods", UID: "", Causes: nil, RetryAfterSeconds: 0},
256 Code: 404,
257 },
258 },
259 }
260 In [It] at: wait_test.go:62 <time>
261 < Exit [It] not found, retry with wrappers - wait_test.go:61 <time>
262 `,
263 },
264 {
265 Name: "[It] pod not found, retry with inverted wrappers",
266 Status: "failed",
267 Failure: &reporters.JUnitFailure{
268 Type: "failed",
269 Description: `[FAILED] Timed out after <after>.
270 The function passed to Eventually returned the following error:
271 <framework.transientError>:
272 pods "no-such-pod" not found
273 {
274 error: <*errors.StatusError>{
275 ErrStatus: {
276 TypeMeta: {Kind: "", APIVersion: ""},
277 ListMeta: {
278 SelfLink: "",
279 ResourceVersion: "",
280 Continue: "",
281 RemainingItemCount: nil,
282 },
283 Status: "Failure",
284 Message: "pods \"no-such-pod\" not found",
285 Reason: "NotFound",
286 Details: {Name: "no-such-pod", Group: "", Kind: "pods", UID: "", Causes: nil, RetryAfterSeconds: 0},
287 Code: 404,
288 },
289 },
290 }
291 In [It] at: wait_test.go:66 <time>
292 `,
293 },
294 SystemErr: `> Enter [It] not found, retry with inverted wrappers - wait_test.go:65 <time>
295 [FAILED] Timed out after <after>.
296 The function passed to Eventually returned the following error:
297 <framework.transientError>:
298 pods "no-such-pod" not found
299 {
300 error: <*errors.StatusError>{
301 ErrStatus: {
302 TypeMeta: {Kind: "", APIVersion: ""},
303 ListMeta: {
304 SelfLink: "",
305 ResourceVersion: "",
306 Continue: "",
307 RemainingItemCount: nil,
308 },
309 Status: "Failure",
310 Message: "pods \"no-such-pod\" not found",
311 Reason: "NotFound",
312 Details: {Name: "no-such-pod", Group: "", Kind: "pods", UID: "", Causes: nil, RetryAfterSeconds: 0},
313 Code: 404,
314 },
315 },
316 }
317 In [It] at: wait_test.go:66 <time>
318 < Exit [It] not found, retry with inverted wrappers - wait_test.go:65 <time>
319 `,
320 },
321 {
322 Name: "[It] pod not running",
323 Status: "failed",
324 Failure: &reporters.JUnitFailure{
325 Description: `[FAILED] Timed out after <after>.
326 Expected Pod to be in <v1.PodPhase>: "Running"
327 Got instead:
328 <*v1.Pod>:
329 metadata:
330 creationTimestamp: null
331 name: pending-pod
332 namespace: default
333 spec:
334 containers: null
335 status:
336 phase: Pending
337 In [It] at: wait_test.go:71 <time>
338 `,
339 Type: "failed",
340 },
341 SystemErr: `> Enter [It] not running - wait_test.go:69 <time>
342 STEP: waiting for pod pending-pod to run - wait_test.go:70 <time>
343 <klog> wait_test.go:71] Failed inside E2E framework:
344 k8s.io/kubernetes/test/e2e/framework/pod.WaitTimeoutForPodRunningInNamespace()
345 wait.go
346 k8s.io/kubernetes/test/e2e/framework/pod_test.glob..func1.5()
347 wait_test.go:71
348 [FAILED] Timed out after <after>.
349 Expected Pod to be in <v1.PodPhase>: "Running"
350 Got instead:
351 <*v1.Pod>:
352 metadata:
353 creationTimestamp: null
354 name: pending-pod
355 namespace: default
356 spec:
357 containers: null
358 status:
359 phase: Pending
360 In [It] at: wait_test.go:71 <time>
361 < Exit [It] not running - wait_test.go:69 <time>
362 `,
363 },
364 {
365 Name: "[It] pod failed",
366 Status: "failed",
367 Failure: &reporters.JUnitFailure{
368 Description: `[FAILED] Told to stop trying after <after>.
369 Expected pod to reach phase "Running", got final phase "Failed" instead:
370 <*v1.Pod>:
371 metadata:
372 creationTimestamp: null
373 name: failed-pod
374 namespace: default
375 spec:
376 containers: null
377 status:
378 phase: Failed
379 In [It] at: wait_test.go:75 <time>
380 `,
381 Type: "failed",
382 },
383 SystemErr: `> Enter [It] failed - wait_test.go:74 <time>
384 <klog> wait_test.go:75] Failed inside E2E framework:
385 k8s.io/kubernetes/test/e2e/framework/pod.WaitTimeoutForPodRunningInNamespace()
386 wait.go
387 k8s.io/kubernetes/test/e2e/framework/pod_test.glob..func1.6()
388 wait_test.go:75
389 [FAILED] Told to stop trying after <after>.
390 Expected pod to reach phase "Running", got final phase "Failed" instead:
391 <*v1.Pod>:
392 metadata:
393 creationTimestamp: null
394 name: failed-pod
395 namespace: default
396 spec:
397 containers: null
398 status:
399 phase: Failed
400 In [It] at: wait_test.go:75 <time>
401 < Exit [It] failed - wait_test.go:74 <time>
402 `,
403 },
404 {
405 Name: "[It] pod gets reported with API error",
406 Status: "failed",
407 Failure: &reporters.JUnitFailure{
408 Description: `[FAILED] Timed out after <after>.
409 The function passed to Eventually returned the following error:
410 <*errors.StatusError>:
411 fake API error
412 {
413 ErrStatus:
414 code: 429
415 details:
416 retryAfterSeconds: 10
417 message: fake API error
418 metadata: {}
419 reason: TooManyRequests
420 status: Failure,
421 }
422 At one point, however, the function did return successfully.
423 Yet, Eventually failed because the matcher was not satisfied:
424 Expected Pod to be in <v1.PodPhase>: "Running"
425 Got instead:
426 <*v1.Pod>:
427 metadata:
428 creationTimestamp: null
429 name: pending-pod
430 namespace: default
431 spec:
432 containers: null
433 status:
434 phase: Pending
435 In [It] at: wait_test.go:93 <time>
436 `,
437 Type: "failed",
438 },
439 SystemErr: `> Enter [It] gets reported with API error - wait_test.go:78 <time>
440 STEP: returning pod - wait_test.go:90 <time>
441 STEP: returning fake API error - wait_test.go:82 <time>
442 [FAILED] Timed out after <after>.
443 The function passed to Eventually returned the following error:
444 <*errors.StatusError>:
445 fake API error
446 {
447 ErrStatus:
448 code: 429
449 details:
450 retryAfterSeconds: 10
451 message: fake API error
452 metadata: {}
453 reason: TooManyRequests
454 status: Failure,
455 }
456 At one point, however, the function did return successfully.
457 Yet, Eventually failed because the matcher was not satisfied:
458 Expected Pod to be in <v1.PodPhase>: "Running"
459 Got instead:
460 <*v1.Pod>:
461 metadata:
462 creationTimestamp: null
463 name: pending-pod
464 namespace: default
465 spec:
466 containers: null
467 status:
468 phase: Pending
469 In [It] at: wait_test.go:93 <time>
470 < Exit [It] gets reported with API error - wait_test.go:78 <time>
471 `,
472 },
473 },
474 },
475 }
476 output.TestGinkgoOutput(t, expected)
477 }
478
View as plain text