1
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
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
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
86
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
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
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
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
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
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 })
163
View as plain text