Update subpath e2e test for windows

Modify the current subpath e2e file to allow it run in windows clusters.

Change-Id: I921dfbbae9480c718853a97a76cc0a95b1af9790
This commit is contained in:
Jing Xu 2019-04-29 11:23:48 -07:00
parent d881c0d77b
commit e570d27b40

View File

@ -28,6 +28,7 @@ import (
"k8s.io/apimachinery/pkg/util/wait" "k8s.io/apimachinery/pkg/util/wait"
"k8s.io/kubernetes/test/e2e/framework" "k8s.io/kubernetes/test/e2e/framework"
e2elog "k8s.io/kubernetes/test/e2e/framework/log" e2elog "k8s.io/kubernetes/test/e2e/framework/log"
"k8s.io/kubernetes/test/e2e/framework/volume"
"k8s.io/kubernetes/test/e2e/storage/testpatterns" "k8s.io/kubernetes/test/e2e/storage/testpatterns"
"k8s.io/kubernetes/test/e2e/storage/utils" "k8s.io/kubernetes/test/e2e/storage/utils"
imageutils "k8s.io/kubernetes/test/utils/image" imageutils "k8s.io/kubernetes/test/utils/image"
@ -63,6 +64,7 @@ func InitSubPathTestSuite() TestSuite {
testpatterns.DefaultFsInlineVolume, testpatterns.DefaultFsInlineVolume,
testpatterns.DefaultFsPreprovisionedPV, testpatterns.DefaultFsPreprovisionedPV,
testpatterns.DefaultFsDynamicPV, testpatterns.DefaultFsDynamicPV,
testpatterns.NtfsDynamicPV,
}, },
}, },
} }
@ -191,7 +193,7 @@ func (s *subPathTestSuite) defineTests(driver TestDriver, pattern testpatterns.T
testReadFile(f, l.filePathInVolume, l.pod, 1) testReadFile(f, l.filePathInVolume, l.pod, 1)
}) })
ginkgo.It("should support existing single file", func() { ginkgo.It("should support existing single file [LinuxOnly]", func() {
init() init()
defer cleanup() defer cleanup()
@ -202,7 +204,7 @@ func (s *subPathTestSuite) defineTests(driver TestDriver, pattern testpatterns.T
testReadFile(f, l.filePathInSubpath, l.pod, 0) testReadFile(f, l.filePathInSubpath, l.pod, 0)
}) })
ginkgo.It("should support file as subpath", func() { ginkgo.It("should support file as subpath [LinuxOnly]", func() {
init() init()
defer cleanup() defer cleanup()
@ -217,13 +219,18 @@ func (s *subPathTestSuite) defineTests(driver TestDriver, pattern testpatterns.T
defer cleanup() defer cleanup()
// Create the subpath outside the volume // Create the subpath outside the volume
setInitCommand(l.pod, fmt.Sprintf("ln -s /bin %s", l.subPathDir)) var command string
if framework.NodeOSDistroIs("windows") {
command = fmt.Sprintf("New-Item -ItemType SymbolicLink -Path %s -value \\Windows", l.subPathDir)
} else {
command = fmt.Sprintf("ln -s /bin %s", l.subPathDir)
}
setInitCommand(l.pod, command)
// Pod should fail // Pod should fail
testPodFailSubpath(f, l.pod, false) testPodFailSubpath(f, l.pod, false)
}) })
ginkgo.It("should fail if subpath file is outside the volume [Slow]", func() { ginkgo.It("should fail if subpath file is outside the volume [Slow][LinuxOnly]", func() {
init() init()
defer cleanup() defer cleanup()
@ -234,7 +241,7 @@ func (s *subPathTestSuite) defineTests(driver TestDriver, pattern testpatterns.T
testPodFailSubpath(f, l.pod, false) testPodFailSubpath(f, l.pod, false)
}) })
ginkgo.It("should fail if non-existent subpath is outside the volume [Slow]", func() { ginkgo.It("should fail if non-existent subpath is outside the volume [Slow][LinuxOnly]", func() {
init() init()
defer cleanup() defer cleanup()
@ -250,8 +257,13 @@ func (s *subPathTestSuite) defineTests(driver TestDriver, pattern testpatterns.T
defer cleanup() defer cleanup()
// Create the subpath outside the volume // Create the subpath outside the volume
setInitCommand(l.pod, fmt.Sprintf("ln -s ../ %s", l.subPathDir)) var command string
if framework.NodeOSDistroIs("windows") {
command = fmt.Sprintf("New-Item -ItemType SymbolicLink -Path %s -value ..\\", l.subPathDir)
} else {
command = fmt.Sprintf("ln -s ../ %s", l.subPathDir)
}
setInitCommand(l.pod, command)
// Pod should fail // Pod should fail
testPodFailSubpath(f, l.pod, false) testPodFailSubpath(f, l.pod, false)
}) })
@ -287,12 +299,17 @@ func (s *subPathTestSuite) defineTests(driver TestDriver, pattern testpatterns.T
defer cleanup() defer cleanup()
// Create the directory // Create the directory
setInitCommand(l.pod, fmt.Sprintf("mkdir -p %v; touch %v", l.subPathDir, probeFilePath)) var command string
if framework.NodeOSDistroIs("windows") {
command = fmt.Sprintf("mkdir -p %v; New-Item -itemtype File -path %v", l.subPathDir, probeFilePath)
} else {
command = fmt.Sprintf("mkdir -p %v; touch %v", l.subPathDir, probeFilePath)
}
setInitCommand(l.pod, command)
testPodContainerRestart(f, l.pod) testPodContainerRestart(f, l.pod)
}) })
ginkgo.It("should support restarting containers using file as subpath [Slow]", func() { ginkgo.It("should support restarting containers using file as subpath [Slow][LinuxOnly]", func() {
init() init()
defer cleanup() defer cleanup()
@ -302,14 +319,14 @@ func (s *subPathTestSuite) defineTests(driver TestDriver, pattern testpatterns.T
testPodContainerRestart(f, l.pod) testPodContainerRestart(f, l.pod)
}) })
ginkgo.It("should unmount if pod is gracefully deleted while kubelet is down [Disruptive][Slow]", func() { ginkgo.It("should unmount if pod is gracefully deleted while kubelet is down [Disruptive][Slow][LinuxOnly]", func() {
init() init()
defer cleanup() defer cleanup()
testSubpathReconstruction(f, l.pod, false) testSubpathReconstruction(f, l.pod, false)
}) })
ginkgo.It("should unmount if pod is force deleted while kubelet is down [Disruptive][Slow]", func() { ginkgo.It("should unmount if pod is force deleted while kubelet is down [Disruptive][Slow][LinuxOnly]", func() {
init() init()
defer cleanup() defer cleanup()
@ -336,7 +353,7 @@ func (s *subPathTestSuite) defineTests(driver TestDriver, pattern testpatterns.T
testReadFile(f, l.filePathInSubpath, l.pod, 0) testReadFile(f, l.filePathInSubpath, l.pod, 0)
}) })
ginkgo.It("should support readOnly file specified in the volumeMount", func() { ginkgo.It("should support readOnly file specified in the volumeMount [LinuxOnly]", func() {
init() init()
defer cleanup() defer cleanup()
@ -404,8 +421,8 @@ func (s *subPathTestSuite) defineTests(driver TestDriver, pattern testpatterns.T
defer cleanup() defer cleanup()
// Change volume container to busybox so we can exec later // Change volume container to busybox so we can exec later
l.pod.Spec.Containers[1].Image = imageutils.GetE2EImage(imageutils.BusyBox) l.pod.Spec.Containers[1].Image = volume.GetTestImage(imageutils.GetE2EImage(imageutils.BusyBox))
l.pod.Spec.Containers[1].Command = []string{"/bin/sh", "-ec", "sleep 100000"} l.pod.Spec.Containers[1].Command = volume.GenerateScriptCmd("sleep 100000")
ginkgo.By(fmt.Sprintf("Creating pod %s", l.pod.Name)) ginkgo.By(fmt.Sprintf("Creating pod %s", l.pod.Name))
removeUnusedContainers(l.pod) removeUnusedContainers(l.pod)
@ -421,7 +438,7 @@ func (s *subPathTestSuite) defineTests(driver TestDriver, pattern testpatterns.T
gomega.Expect(err).ToNot(gomega.HaveOccurred(), "while waiting for pod to be running") gomega.Expect(err).ToNot(gomega.HaveOccurred(), "while waiting for pod to be running")
// Exec into container that mounted the volume, delete subpath directory // Exec into container that mounted the volume, delete subpath directory
rmCmd := fmt.Sprintf("rm -rf %s", l.subPathDir) rmCmd := fmt.Sprintf("rm -r %s", l.subPathDir)
_, err = podContainerExec(l.pod, 1, rmCmd) _, err = podContainerExec(l.pod, 1, rmCmd)
gomega.Expect(err).ToNot(gomega.HaveOccurred(), "while removing subpath directory") gomega.Expect(err).ToNot(gomega.HaveOccurred(), "while removing subpath directory")
@ -468,6 +485,7 @@ func SubpathTestPod(f *framework.Framework, subpath, volumeType string, source *
suffix = generateSuffixForPodName(volumeType) suffix = generateSuffixForPodName(volumeType)
gracePeriod = int64(1) gracePeriod = int64(1)
probeVolumeName = "liveness-probe-volume" probeVolumeName = "liveness-probe-volume"
seLinuxOptions = &v1.SELinuxOptions{Level: "s0:c0,c1"}
) )
return &v1.Pod{ return &v1.Pod{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
@ -478,7 +496,7 @@ func SubpathTestPod(f *framework.Framework, subpath, volumeType string, source *
InitContainers: []v1.Container{ InitContainers: []v1.Container{
{ {
Name: fmt.Sprintf("init-volume-%s", suffix), Name: fmt.Sprintf("init-volume-%s", suffix),
Image: imageutils.GetE2EImage(imageutils.BusyBox), Image: volume.GetTestImage(imageutils.GetE2EImage(imageutils.BusyBox)),
VolumeMounts: []v1.VolumeMount{ VolumeMounts: []v1.VolumeMount{
{ {
Name: volumeName, Name: volumeName,
@ -489,9 +507,7 @@ func SubpathTestPod(f *framework.Framework, subpath, volumeType string, source *
MountPath: probeVolumePath, MountPath: probeVolumePath,
}, },
}, },
SecurityContext: &v1.SecurityContext{ SecurityContext: volume.GenerateSecurityContext(privilegedSecurityContext),
Privileged: &privilegedSecurityContext,
},
}, },
{ {
Name: fmt.Sprintf("test-init-subpath-%s", suffix), Name: fmt.Sprintf("test-init-subpath-%s", suffix),
@ -507,9 +523,7 @@ func SubpathTestPod(f *framework.Framework, subpath, volumeType string, source *
MountPath: probeVolumePath, MountPath: probeVolumePath,
}, },
}, },
SecurityContext: &v1.SecurityContext{ SecurityContext: volume.GenerateSecurityContext(privilegedSecurityContext),
Privileged: &privilegedSecurityContext,
},
}, },
{ {
Name: fmt.Sprintf("test-init-volume-%s", suffix), Name: fmt.Sprintf("test-init-volume-%s", suffix),
@ -524,9 +538,7 @@ func SubpathTestPod(f *framework.Framework, subpath, volumeType string, source *
MountPath: probeVolumePath, MountPath: probeVolumePath,
}, },
}, },
SecurityContext: &v1.SecurityContext{ SecurityContext: volume.GenerateSecurityContext(privilegedSecurityContext),
Privileged: &privilegedSecurityContext,
},
}, },
}, },
Containers: []v1.Container{ Containers: []v1.Container{
@ -544,9 +556,7 @@ func SubpathTestPod(f *framework.Framework, subpath, volumeType string, source *
MountPath: probeVolumePath, MountPath: probeVolumePath,
}, },
}, },
SecurityContext: &v1.SecurityContext{ SecurityContext: volume.GenerateSecurityContext(privilegedSecurityContext),
Privileged: &privilegedSecurityContext,
},
}, },
{ {
Name: fmt.Sprintf("test-container-volume-%s", suffix), Name: fmt.Sprintf("test-container-volume-%s", suffix),
@ -561,9 +571,7 @@ func SubpathTestPod(f *framework.Framework, subpath, volumeType string, source *
MountPath: probeVolumePath, MountPath: probeVolumePath,
}, },
}, },
SecurityContext: &v1.SecurityContext{ SecurityContext: volume.GenerateSecurityContext(privilegedSecurityContext),
Privileged: &privilegedSecurityContext,
},
}, },
}, },
RestartPolicy: v1.RestartPolicyNever, RestartPolicy: v1.RestartPolicyNever,
@ -580,11 +588,7 @@ func SubpathTestPod(f *framework.Framework, subpath, volumeType string, source *
}, },
}, },
}, },
SecurityContext: &v1.PodSecurityContext{ SecurityContext: volume.GeneratePodSecurityContext(nil, seLinuxOptions),
SELinuxOptions: &v1.SELinuxOptions{
Level: "s0:c0,c1",
},
},
}, },
} }
} }
@ -627,8 +631,8 @@ func volumeFormatPod(f *framework.Framework, volumeSource *v1.VolumeSource) *v1.
Containers: []v1.Container{ Containers: []v1.Container{
{ {
Name: fmt.Sprintf("init-volume-%s", f.Namespace.Name), Name: fmt.Sprintf("init-volume-%s", f.Namespace.Name),
Image: imageutils.GetE2EImage(imageutils.BusyBox), Image: volume.GetTestImage(imageutils.GetE2EImage(imageutils.BusyBox)),
Command: []string{"/bin/sh", "-ec", "echo nothing"}, Command: volume.GenerateScriptCmd("echo nothing"),
VolumeMounts: []v1.VolumeMount{ VolumeMounts: []v1.VolumeMount{
{ {
Name: volumeName, Name: volumeName,
@ -649,7 +653,7 @@ func volumeFormatPod(f *framework.Framework, volumeSource *v1.VolumeSource) *v1.
} }
func setInitCommand(pod *v1.Pod, command string) { func setInitCommand(pod *v1.Pod, command string) {
pod.Spec.InitContainers[0].Command = []string{"/bin/sh", "-ec", command} pod.Spec.InitContainers[0].Command = volume.GenerateScriptCmd(command)
} }
func setWriteCommand(file string, container *v1.Container) { func setWriteCommand(file string, container *v1.Container) {
@ -768,11 +772,10 @@ func waitForPodSubpathError(f *framework.Framework, pod *v1.Pod, allowContainerT
func testPodContainerRestart(f *framework.Framework, pod *v1.Pod) { func testPodContainerRestart(f *framework.Framework, pod *v1.Pod) {
pod.Spec.RestartPolicy = v1.RestartPolicyOnFailure pod.Spec.RestartPolicy = v1.RestartPolicyOnFailure
pod.Spec.Containers[0].Image = imageutils.GetE2EImage(imageutils.BusyBox) pod.Spec.Containers[0].Image = volume.GetTestImage(imageutils.GetE2EImage(imageutils.BusyBox))
pod.Spec.Containers[0].Command = []string{"/bin/sh", "-ec", "sleep 100000"} pod.Spec.Containers[0].Command = volume.GenerateScriptCmd("sleep 100000")
pod.Spec.Containers[1].Image = imageutils.GetE2EImage(imageutils.BusyBox) pod.Spec.Containers[1].Image = volume.GetTestImage(imageutils.GetE2EImage(imageutils.BusyBox))
pod.Spec.Containers[1].Command = []string{"/bin/sh", "-ec", "sleep 100000"} pod.Spec.Containers[1].Command = volume.GenerateScriptCmd("sleep 100000")
// Add liveness probe to subpath container // Add liveness probe to subpath container
pod.Spec.Containers[0].LivenessProbe = &v1.Probe{ pod.Spec.Containers[0].LivenessProbe = &v1.Probe{
Handler: v1.Handler{ Handler: v1.Handler{
@ -825,7 +828,12 @@ func testPodContainerRestart(f *framework.Framework, pod *v1.Pod) {
// Fix liveness probe // Fix liveness probe
ginkgo.By("Rewriting the file") ginkgo.By("Rewriting the file")
writeCmd := fmt.Sprintf("echo test-after > %v", probeFilePath) var writeCmd string
if framework.NodeOSDistroIs("windows") {
writeCmd = fmt.Sprintf("echo test-after | Out-File -FilePath %v", probeFilePath)
} else {
writeCmd = fmt.Sprintf("echo test-after > %v", probeFilePath)
}
out, err = podContainerExec(pod, 1, writeCmd) out, err = podContainerExec(pod, 1, writeCmd)
e2elog.Logf("Pod exec output: %v", out) e2elog.Logf("Pod exec output: %v", out)
gomega.Expect(err).ToNot(gomega.HaveOccurred(), "while rewriting the probe file") gomega.Expect(err).ToNot(gomega.HaveOccurred(), "while rewriting the probe file")
@ -864,10 +872,10 @@ func testSubpathReconstruction(f *framework.Framework, pod *v1.Pod, forceDelete
// This is mostly copied from TestVolumeUnmountsFromDeletedPodWithForceOption() // This is mostly copied from TestVolumeUnmountsFromDeletedPodWithForceOption()
// Change to busybox // Change to busybox
pod.Spec.Containers[0].Image = imageutils.GetE2EImage(imageutils.BusyBox) pod.Spec.Containers[0].Image = volume.GetTestImage(imageutils.GetE2EImage(imageutils.BusyBox))
pod.Spec.Containers[0].Command = []string{"/bin/sh", "-ec", "sleep 100000"} pod.Spec.Containers[0].Command = volume.GenerateScriptCmd("sleep 100000")
pod.Spec.Containers[1].Image = imageutils.GetE2EImage(imageutils.BusyBox) pod.Spec.Containers[1].Image = volume.GetTestImage(imageutils.GetE2EImage(imageutils.BusyBox))
pod.Spec.Containers[1].Command = []string{"/bin/sh", "-ec", "sleep 100000"} pod.Spec.Containers[1].Command = volume.GenerateScriptCmd("sleep 100000")
// If grace period is too short, then there is not enough time for the volume // If grace period is too short, then there is not enough time for the volume
// manager to cleanup the volumes // manager to cleanup the volumes
@ -900,6 +908,15 @@ func formatVolume(f *framework.Framework, pod *v1.Pod) {
gomega.Expect(err).ToNot(gomega.HaveOccurred(), "while deleting volume init pod") gomega.Expect(err).ToNot(gomega.HaveOccurred(), "while deleting volume init pod")
} }
func podContainerExec(pod *v1.Pod, containerIndex int, bashExec string) (string, error) { func podContainerExec(pod *v1.Pod, containerIndex int, command string) (string, error) {
return framework.RunKubectl("exec", fmt.Sprintf("--namespace=%s", pod.Namespace), pod.Name, "--container", pod.Spec.Containers[containerIndex].Name, "--", "/bin/sh", "-c", bashExec) var shell string
var option string
if framework.NodeOSDistroIs("windows") {
shell = "powershell"
option = "/c"
} else {
shell = "/bin/sh"
option = "-c"
}
return framework.RunKubectl("exec", fmt.Sprintf("--namespace=%s", pod.Namespace), pod.Name, "--container", pod.Spec.Containers[containerIndex].Name, "--", shell, option, command)
} }