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  }