k8s.io/kubernetes@v1.29.3/test/e2e/node/examples.go (about)

     1  /*
     2  Copyright 2015 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  	"fmt"
    22  	"path/filepath"
    23  	"sync"
    24  	"time"
    25  
    26  	rbacv1 "k8s.io/api/rbac/v1"
    27  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    28  	"k8s.io/apimachinery/pkg/runtime/schema"
    29  	"k8s.io/apiserver/pkg/authentication/serviceaccount"
    30  	clientset "k8s.io/client-go/kubernetes"
    31  	podutil "k8s.io/kubernetes/pkg/api/v1/pod"
    32  	commonutils "k8s.io/kubernetes/test/e2e/common"
    33  	"k8s.io/kubernetes/test/e2e/feature"
    34  	"k8s.io/kubernetes/test/e2e/framework"
    35  	e2eauth "k8s.io/kubernetes/test/e2e/framework/auth"
    36  	e2ekubectl "k8s.io/kubernetes/test/e2e/framework/kubectl"
    37  	e2epod "k8s.io/kubernetes/test/e2e/framework/pod"
    38  	e2eoutput "k8s.io/kubernetes/test/e2e/framework/pod/output"
    39  	e2etestfiles "k8s.io/kubernetes/test/e2e/framework/testfiles"
    40  	admissionapi "k8s.io/pod-security-admission/api"
    41  
    42  	"github.com/onsi/ginkgo/v2"
    43  )
    44  
    45  const (
    46  	serverStartTimeout = framework.PodStartTimeout + 3*time.Minute
    47  )
    48  
    49  var _ = SIGDescribe(feature.Example, func() {
    50  	f := framework.NewDefaultFramework("examples")
    51  	f.NamespacePodSecurityLevel = admissionapi.LevelBaseline
    52  
    53  	var c clientset.Interface
    54  	var ns string
    55  	ginkgo.BeforeEach(func(ctx context.Context) {
    56  		c = f.ClientSet
    57  		ns = f.Namespace.Name
    58  
    59  		// this test wants powerful permissions.  Since the namespace names are unique, we can leave this
    60  		// lying around so we don't have to race any caches
    61  		err := e2eauth.BindClusterRoleInNamespace(ctx, c.RbacV1(), "edit", f.Namespace.Name,
    62  			rbacv1.Subject{Kind: rbacv1.ServiceAccountKind, Namespace: f.Namespace.Name, Name: "default"})
    63  		framework.ExpectNoError(err)
    64  
    65  		err = e2eauth.WaitForAuthorizationUpdate(ctx, c.AuthorizationV1(),
    66  			serviceaccount.MakeUsername(f.Namespace.Name, "default"),
    67  			f.Namespace.Name, "create", schema.GroupResource{Resource: "pods"}, true)
    68  		framework.ExpectNoError(err)
    69  	})
    70  
    71  	ginkgo.Describe("Liveness", func() {
    72  		ginkgo.It("liveness pods should be automatically restarted", func(ctx context.Context) {
    73  			test := "test/fixtures/doc-yaml/user-guide/liveness"
    74  			execYaml := readFile(test, "exec-liveness.yaml.in")
    75  			httpYaml := readFile(test, "http-liveness.yaml.in")
    76  
    77  			e2ekubectl.RunKubectlOrDieInput(ns, execYaml, "create", "-f", "-")
    78  			e2ekubectl.RunKubectlOrDieInput(ns, httpYaml, "create", "-f", "-")
    79  
    80  			// Since both containers start rapidly, we can easily run this test in parallel.
    81  			var wg sync.WaitGroup
    82  			passed := true
    83  			checkRestart := func(podName string, timeout time.Duration) {
    84  				err := e2epod.WaitForPodNameRunningInNamespace(ctx, c, podName, ns)
    85  				framework.ExpectNoError(err)
    86  				for t := time.Now(); time.Since(t) < timeout; time.Sleep(framework.Poll) {
    87  					pod, err := c.CoreV1().Pods(ns).Get(ctx, podName, metav1.GetOptions{})
    88  					framework.ExpectNoError(err, fmt.Sprintf("getting pod %s", podName))
    89  					stat := podutil.GetExistingContainerStatus(pod.Status.ContainerStatuses, podName)
    90  					framework.Logf("Pod: %s, restart count:%d", stat.Name, stat.RestartCount)
    91  					if stat.RestartCount > 0 {
    92  						framework.Logf("Saw %v restart, succeeded...", podName)
    93  						wg.Done()
    94  						return
    95  					}
    96  				}
    97  				framework.Logf("Failed waiting for %v restart! ", podName)
    98  				passed = false
    99  				wg.Done()
   100  			}
   101  
   102  			ginkgo.By("Check restarts")
   103  
   104  			// Start the "actual test", and wait for both pods to complete.
   105  			// If 2 fail: Something is broken with the test (or maybe even with liveness).
   106  			// If 1 fails: Its probably just an error in the examples/ files themselves.
   107  			wg.Add(2)
   108  			for _, c := range []string{"liveness-http", "liveness-exec"} {
   109  				go checkRestart(c, 2*time.Minute)
   110  			}
   111  			wg.Wait()
   112  			if !passed {
   113  				framework.Failf("At least one liveness example failed.  See the logs above.")
   114  			}
   115  		})
   116  	})
   117  
   118  	ginkgo.Describe("Secret", func() {
   119  		ginkgo.It("should create a pod that reads a secret", func(ctx context.Context) {
   120  			test := "test/fixtures/doc-yaml/user-guide/secrets"
   121  			secretYaml := readFile(test, "secret.yaml")
   122  			podYaml := readFile(test, "secret-pod.yaml.in")
   123  
   124  			podName := "secret-test-pod"
   125  
   126  			ginkgo.By("creating secret and pod")
   127  			e2ekubectl.RunKubectlOrDieInput(ns, secretYaml, "create", "-f", "-")
   128  			e2ekubectl.RunKubectlOrDieInput(ns, podYaml, "create", "-f", "-")
   129  			err := e2epod.WaitForPodNoLongerRunningInNamespace(ctx, c, podName, ns)
   130  			framework.ExpectNoError(err)
   131  
   132  			ginkgo.By("checking if secret was read correctly")
   133  			_, err = e2eoutput.LookForStringInLog(ns, "secret-test-pod", "test-container", "value-1", serverStartTimeout)
   134  			framework.ExpectNoError(err)
   135  		})
   136  	})
   137  
   138  	ginkgo.Describe("Downward API", func() {
   139  		ginkgo.It("should create a pod that prints his name and namespace", func(ctx context.Context) {
   140  			test := "test/fixtures/doc-yaml/user-guide/downward-api"
   141  			podYaml := readFile(test, "dapi-pod.yaml.in")
   142  			podName := "dapi-test-pod"
   143  
   144  			ginkgo.By("creating the pod")
   145  			e2ekubectl.RunKubectlOrDieInput(ns, podYaml, "create", "-f", "-")
   146  			err := e2epod.WaitForPodNoLongerRunningInNamespace(ctx, c, podName, ns)
   147  			framework.ExpectNoError(err)
   148  
   149  			ginkgo.By("checking if name and namespace were passed correctly")
   150  			_, err = e2eoutput.LookForStringInLog(ns, podName, "test-container", fmt.Sprintf("MY_POD_NAMESPACE=%v", ns), serverStartTimeout)
   151  			framework.ExpectNoError(err)
   152  			_, err = e2eoutput.LookForStringInLog(ns, podName, "test-container", fmt.Sprintf("MY_POD_NAME=%v", podName), serverStartTimeout)
   153  			framework.ExpectNoError(err)
   154  		})
   155  	})
   156  })
   157  
   158  func readFile(test, file string) string {
   159  	from := filepath.Join(test, file)
   160  	data, err := e2etestfiles.Read(from)
   161  	if err != nil {
   162  		framework.Fail(err.Error())
   163  	}
   164  	return commonutils.SubstituteImageName(string(data))
   165  }