k8s.io/kubernetes@v1.29.3/test/e2e_node/log_path_test.go (about) 1 /* 2 Copyright 2016 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 e2enode 18 19 import ( 20 "context" 21 22 v1 "k8s.io/api/core/v1" 23 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 24 "k8s.io/apimachinery/pkg/util/uuid" 25 "k8s.io/kubernetes/pkg/kubelet" 26 kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" 27 "k8s.io/kubernetes/test/e2e/framework" 28 e2epod "k8s.io/kubernetes/test/e2e/framework/pod" 29 admissionapi "k8s.io/pod-security-admission/api" 30 31 "github.com/onsi/ginkgo/v2" 32 ) 33 34 const ( 35 logString = "This is the expected log content of this node e2e test" 36 logContainerName = "logger" 37 ) 38 39 var _ = SIGDescribe("ContainerLogPath", framework.WithNodeConformance(), func() { 40 f := framework.NewDefaultFramework("kubelet-container-log-path") 41 f.NamespacePodSecurityLevel = admissionapi.LevelPrivileged 42 var podClient *e2epod.PodClient 43 44 ginkgo.Describe("Pod with a container", func() { 45 ginkgo.Context("printed log to stdout", func() { 46 makeLogPod := func(podName, log string) *v1.Pod { 47 return &v1.Pod{ 48 ObjectMeta: metav1.ObjectMeta{ 49 Name: podName, 50 }, 51 Spec: v1.PodSpec{ 52 // this pod is expected to exit successfully 53 RestartPolicy: v1.RestartPolicyNever, 54 Containers: []v1.Container{ 55 { 56 Image: busyboxImage, 57 Name: logContainerName, 58 Command: []string{"sh", "-c", "echo " + log}, 59 }, 60 }, 61 }, 62 } 63 } 64 65 makeLogCheckPod := func(podName, log, expectedLogPath string) *v1.Pod { 66 hostPathType := new(v1.HostPathType) 67 *hostPathType = v1.HostPathType(string(v1.HostPathFileOrCreate)) 68 69 return &v1.Pod{ 70 ObjectMeta: metav1.ObjectMeta{ 71 Name: podName, 72 }, 73 Spec: v1.PodSpec{ 74 // this pod is expected to exit successfully 75 RestartPolicy: v1.RestartPolicyNever, 76 Containers: []v1.Container{ 77 { 78 Image: busyboxImage, 79 SecurityContext: &v1.SecurityContext{ 80 SELinuxOptions: &v1.SELinuxOptions{ 81 Type: "container_logreader_t", 82 }, 83 }, 84 Name: podName, 85 // If we find expected log file and contains right content, exit 0 86 // else, keep checking until test timeout 87 Command: []string{"sh", "-c", "while true; do if [ -e " + expectedLogPath + " ] && grep -q " + log + " " + expectedLogPath + "; then exit 0; fi; sleep 1; done"}, 88 VolumeMounts: []v1.VolumeMount{ 89 { 90 Name: "logdir", 91 // mount ContainerLogsDir to the same path in container 92 MountPath: expectedLogPath, 93 ReadOnly: true, 94 }, 95 }, 96 }, 97 }, 98 Volumes: []v1.Volume{ 99 { 100 Name: "logdir", 101 VolumeSource: v1.VolumeSource{ 102 HostPath: &v1.HostPathVolumeSource{ 103 Path: expectedLogPath, 104 Type: hostPathType, 105 }, 106 }, 107 }, 108 }, 109 }, 110 } 111 } 112 113 createAndWaitPod := func(ctx context.Context, pod *v1.Pod) error { 114 podClient.Create(ctx, pod) 115 return e2epod.WaitForPodSuccessInNamespace(ctx, f.ClientSet, pod.Name, f.Namespace.Name) 116 } 117 118 var logPodName string 119 ginkgo.BeforeEach(func(ctx context.Context) { 120 podClient = e2epod.NewPodClient(f) 121 logPodName = "log-pod-" + string(uuid.NewUUID()) 122 err := createAndWaitPod(ctx, makeLogPod(logPodName, logString)) 123 framework.ExpectNoError(err, "Failed waiting for pod: %s to enter success state", logPodName) 124 }) 125 ginkgo.It("should print log to correct log path", func(ctx context.Context) { 126 127 logDir := kubelet.ContainerLogsDir 128 129 // get containerID from created Pod 130 createdLogPod, err := podClient.Get(ctx, logPodName, metav1.GetOptions{}) 131 logContainerID := kubecontainer.ParseContainerID(createdLogPod.Status.ContainerStatuses[0].ContainerID) 132 framework.ExpectNoError(err, "Failed to get pod: %s", logPodName) 133 134 // build log file path 135 expectedlogFile := logDir + "/" + logPodName + "_" + f.Namespace.Name + "_" + logContainerName + "-" + logContainerID.ID + ".log" 136 137 logCheckPodName := "log-check-" + string(uuid.NewUUID()) 138 err = createAndWaitPod(ctx, makeLogCheckPod(logCheckPodName, logString, expectedlogFile)) 139 framework.ExpectNoError(err, "Failed waiting for pod: %s to enter success state", logCheckPodName) 140 }) 141 142 ginkgo.It("should print log to correct cri log path", func(ctx context.Context) { 143 144 logCRIDir := "/var/log/pods" 145 146 // get podID from created Pod 147 createdLogPod, err := podClient.Get(ctx, logPodName, metav1.GetOptions{}) 148 framework.ExpectNoError(err, "Failed to get pod: %s", logPodName) 149 podNs := createdLogPod.Namespace 150 podName := createdLogPod.Name 151 podID := string(createdLogPod.UID) 152 153 // build log cri file path 154 expectedCRILogFile := logCRIDir + "/" + podNs + "_" + podName + "_" + podID + "/" + logContainerName + "/0.log" 155 156 logCRICheckPodName := "log-cri-check-" + string(uuid.NewUUID()) 157 err = createAndWaitPod(ctx, makeLogCheckPod(logCRICheckPodName, logString, expectedCRILogFile)) 158 framework.ExpectNoError(err, "Failed waiting for pod: %s to enter success state", logCRICheckPodName) 159 }) 160 }) 161 }) 162 })