Skip to content

Commit 1a2c557

Browse files
committed
test: add e2e test
Signed-off-by: Jian Zeng <[email protected]>
1 parent 4193824 commit 1a2c557

File tree

2 files changed

+86
-2
lines changed

2 files changed

+86
-2
lines changed

test/e2e/feature/feature.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,11 @@ var (
268268
// Marks a single test that tests Pod Lifecycle Sleep action with zero duration. Requires feature gate PodLifecycleSleepActionAllowZero to be enabled.
269269
PodLifecycleSleepActionAllowZero = framework.WithFeature(framework.ValidFeatures.Add("PodLifecycleSleepActionAllowZero"))
270270

271+
// Owner: sig-node
272+
// Marks tests that require a cluster with PodLogsQuerySplitStreams
273+
// (used for testing specific log stream <https://kep.k8s.io/3288>)
274+
PodLogsQuerySplitStreams = framework.WithFeature(framework.ValidFeatures.Add("PodLogsQuerySplitStreams"))
275+
271276
// TODO: document the feature (owning SIG, when to use this feature for a test)
272277
PodPriority = framework.WithFeature(framework.ValidFeatures.Add("PodPriority"))
273278

test/e2e/node/kubelet.go

Lines changed: 81 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,15 @@ import (
2828
"time"
2929

3030
"github.com/onsi/gomega"
31+
3132
v1 "k8s.io/api/core/v1"
3233
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3334
"k8s.io/apimachinery/pkg/util/sets"
3435
"k8s.io/apimachinery/pkg/util/uuid"
3536
"k8s.io/apimachinery/pkg/util/wait"
3637
clientset "k8s.io/client-go/kubernetes"
38+
admissionapi "k8s.io/pod-security-admission/api"
39+
3740
"k8s.io/kubernetes/test/e2e/feature"
3841
"k8s.io/kubernetes/test/e2e/framework"
3942
e2ekubectl "k8s.io/kubernetes/test/e2e/framework/kubectl"
@@ -46,7 +49,6 @@ import (
4649
e2evolume "k8s.io/kubernetes/test/e2e/framework/volume"
4750
testutils "k8s.io/kubernetes/test/utils"
4851
imageutils "k8s.io/kubernetes/test/utils/image"
49-
admissionapi "k8s.io/pod-security-admission/api"
5052

5153
"github.com/onsi/ginkgo/v2"
5254
)
@@ -144,7 +146,7 @@ func createPodUsingNfs(ctx context.Context, f *framework.Framework, c clientset.
144146
},
145147
},
146148
},
147-
RestartPolicy: v1.RestartPolicyNever, //don't restart pod
149+
RestartPolicy: v1.RestartPolicyNever, // don't restart pod
148150
Volumes: []v1.Volume{
149151
{
150152
Name: "nfs-vol",
@@ -640,6 +642,76 @@ var _ = SIGDescribe("kubelet", func() {
640642
})
641643
})
642644

645+
var _ = SIGDescribe("specific log stream", feature.PodLogsQuerySplitStreams, func() {
646+
var (
647+
c clientset.Interface
648+
ns string
649+
)
650+
f := framework.NewDefaultFramework("pod-log-stream")
651+
f.NamespacePodSecurityLevel = admissionapi.LevelPrivileged
652+
653+
ginkgo.BeforeEach(func() {
654+
c = f.ClientSet
655+
ns = f.Namespace.Name
656+
})
657+
658+
ginkgo.It("kubectl get --raw /api/v1/namespaces/default/pods/<pod-name>/log?stream", func(ctx context.Context) {
659+
ginkgo.By("create pod")
660+
661+
pod := &v1.Pod{
662+
TypeMeta: metav1.TypeMeta{
663+
Kind: "Pod",
664+
APIVersion: "v1",
665+
},
666+
ObjectMeta: metav1.ObjectMeta{
667+
GenerateName: "log-stream-",
668+
Namespace: ns,
669+
},
670+
Spec: v1.PodSpec{
671+
Containers: []v1.Container{
672+
{
673+
Name: "log-stream",
674+
Image: imageutils.GetE2EImage(imageutils.BusyBox),
675+
Command: []string{"/bin/sh"},
676+
Args: []string{"-c", "echo out1; echo err1 >&2; tail -f /dev/null"},
677+
},
678+
},
679+
RestartPolicy: v1.RestartPolicyNever, // don't restart pod
680+
},
681+
}
682+
rtnPod, err := c.CoreV1().Pods(ns).Create(ctx, pod, metav1.CreateOptions{})
683+
framework.ExpectNoError(err)
684+
685+
err = e2epod.WaitTimeoutForPodReadyInNamespace(ctx, f.ClientSet, rtnPod.Name, f.Namespace.Name, framework.PodStartTimeout) // running & ready
686+
framework.ExpectNoError(err)
687+
688+
rtnPod, err = c.CoreV1().Pods(ns).Get(ctx, rtnPod.Name, metav1.GetOptions{}) // return fresh pod
689+
framework.ExpectNoError(err)
690+
691+
ginkgo.By("Starting the command")
692+
tk := e2ekubectl.NewTestKubeconfig(framework.TestContext.CertDir, framework.TestContext.Host, framework.TestContext.KubeConfig, framework.TestContext.KubeContext, framework.TestContext.KubectlPath, ns)
693+
694+
queryCommand := fmt.Sprintf("/api/v1/namespaces/%s/pods/%s/log?stream=All", rtnPod.Namespace, rtnPod.Name)
695+
cmd := tk.KubectlCmd("get", "--raw", queryCommand)
696+
result := runKubectlCommand(cmd)
697+
// the order of the logs is indeterminate
698+
assertContains("out1", result)
699+
assertContains("err1", result)
700+
701+
queryCommand = fmt.Sprintf("/api/v1/namespaces/%s/pods/%s/log?stream=Stdout", rtnPod.Namespace, rtnPod.Name)
702+
cmd = tk.KubectlCmd("get", "--raw", queryCommand)
703+
result = runKubectlCommand(cmd)
704+
assertContains("out1", result)
705+
assertNotContains("err1", result)
706+
707+
queryCommand = fmt.Sprintf("/api/v1/namespaces/%s/pods/%s/log?stream=Stderr", rtnPod.Namespace, rtnPod.Name)
708+
cmd = tk.KubectlCmd("get", "--raw", queryCommand)
709+
result = runKubectlCommand(cmd)
710+
assertContains("err1", result)
711+
assertNotContains("out1", result)
712+
})
713+
})
714+
643715
func getLinuxNodes(nodes *v1.NodeList) *v1.NodeList {
644716
filteredNodes := nodes
645717
e2enode.Filter(filteredNodes, func(node v1.Node) bool {
@@ -696,6 +768,13 @@ func assertContains(expectedString string, result string) {
696768
framework.Failf("Failed to find \"%s\"", expectedString)
697769
}
698770

771+
func assertNotContains(expectedString string, result string) {
772+
if !strings.Contains(result, expectedString) {
773+
return
774+
}
775+
framework.Failf("Found unexpected \"%s\"", expectedString)
776+
}
777+
699778
func commandOnNode(nodeName string, cmd string) string {
700779
result, err := e2essh.NodeExec(context.Background(), nodeName, cmd, framework.TestContext.Provider)
701780
framework.ExpectNoError(err)

0 commit comments

Comments
 (0)