k8s.io/kubernetes@v1.29.3/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 INFO: 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 INFO: 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 In [It] at: wait_test.go:75 <time> 371 `, 372 Type: "failed", 373 }, 374 SystemErr: `> Enter [It] failed - wait_test.go:74 <time> 375 INFO: Failed inside E2E framework: 376 k8s.io/kubernetes/test/e2e/framework/pod.WaitTimeoutForPodRunningInNamespace() 377 wait.go 378 k8s.io/kubernetes/test/e2e/framework/pod_test.glob..func1.6() 379 wait_test.go:75 380 [FAILED] Told to stop trying after <after>. 381 Expected pod to reach phase "Running", got final phase "Failed" instead. 382 In [It] at: wait_test.go:75 <time> 383 < Exit [It] failed - wait_test.go:74 <time> 384 `, 385 }, 386 { 387 Name: "[It] pod gets reported with API error", 388 Status: "failed", 389 Failure: &reporters.JUnitFailure{ 390 Description: `[FAILED] Timed out after <after>. 391 The function passed to Eventually returned the following error: 392 <*errors.StatusError>: 393 fake API error 394 { 395 ErrStatus: 396 code: 429 397 details: 398 retryAfterSeconds: 10 399 message: fake API error 400 metadata: {} 401 reason: TooManyRequests 402 status: Failure, 403 } 404 At one point, however, the function did return successfully. 405 Yet, Eventually failed because the matcher was not satisfied: 406 Expected Pod to be in <v1.PodPhase>: "Running" 407 Got instead: 408 <*v1.Pod>: 409 metadata: 410 creationTimestamp: null 411 name: pending-pod 412 namespace: default 413 spec: 414 containers: null 415 status: 416 phase: Pending 417 In [It] at: wait_test.go:93 <time> 418 `, 419 Type: "failed", 420 }, 421 SystemErr: `> Enter [It] gets reported with API error - wait_test.go:78 <time> 422 STEP: returning pod - wait_test.go:90 <time> 423 STEP: returning fake API error - wait_test.go:82 <time> 424 [FAILED] Timed out after <after>. 425 The function passed to Eventually returned the following error: 426 <*errors.StatusError>: 427 fake API error 428 { 429 ErrStatus: 430 code: 429 431 details: 432 retryAfterSeconds: 10 433 message: fake API error 434 metadata: {} 435 reason: TooManyRequests 436 status: Failure, 437 } 438 At one point, however, the function did return successfully. 439 Yet, Eventually failed because the matcher was not satisfied: 440 Expected Pod to be in <v1.PodPhase>: "Running" 441 Got instead: 442 <*v1.Pod>: 443 metadata: 444 creationTimestamp: null 445 name: pending-pod 446 namespace: default 447 spec: 448 containers: null 449 status: 450 phase: Pending 451 In [It] at: wait_test.go:93 <time> 452 < Exit [It] gets reported with API error - wait_test.go:78 <time> 453 `, 454 }, 455 }, 456 }, 457 } 458 output.TestGinkgoOutput(t, expected) 459 }