k8s.io/kubernetes@v1.31.0-alpha.0.0.20240520171757-56147500dadc/test/e2e/framework/pod/wait_test.go (about) 1 /* 2 Copyright 2022 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 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" // activate YAML object dumps 38 ) 39 40 // The line number of the following code is checked in TestFailureOutput below. 41 // Be careful when moving it around or changing the import statements above. 42 // Here are some intentionally blank lines that can be removed to compensate 43 // for future additional import statements. 44 // 45 // 46 // 47 // 48 // 49 // 50 // This must be line #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 }