mirror of https://github.com/k3s-io/k3s
Merge pull request #73318 from wongma7/subpath-init-write
Do writes in init container before trying readspull/564/head
commit
641b2adcd3
|
@ -208,8 +208,8 @@ type subPathTestInput struct {
|
||||||
|
|
||||||
func testSubPath(input *subPathTestInput) {
|
func testSubPath(input *subPathTestInput) {
|
||||||
It("should support non-existent path", func() {
|
It("should support non-existent path", func() {
|
||||||
// Write the file in the subPath from container 0
|
// Write the file in the subPath from init container 1
|
||||||
setWriteCommand(input.filePathInSubpath, &input.pod.Spec.Containers[0])
|
setWriteCommand(input.filePathInSubpath, &input.pod.Spec.InitContainers[1])
|
||||||
|
|
||||||
// Read it from outside the subPath from container 1
|
// Read it from outside the subPath from container 1
|
||||||
testReadFile(input.f, input.filePathInVolume, input.pod, 1)
|
testReadFile(input.f, input.filePathInVolume, input.pod, 1)
|
||||||
|
@ -219,8 +219,8 @@ func testSubPath(input *subPathTestInput) {
|
||||||
// Create the directory
|
// Create the directory
|
||||||
setInitCommand(input.pod, fmt.Sprintf("mkdir -p %s", input.subPathDir))
|
setInitCommand(input.pod, fmt.Sprintf("mkdir -p %s", input.subPathDir))
|
||||||
|
|
||||||
// Write the file in the subPath from container 0
|
// Write the file in the subPath from init container 1
|
||||||
setWriteCommand(input.filePathInSubpath, &input.pod.Spec.Containers[0])
|
setWriteCommand(input.filePathInSubpath, &input.pod.Spec.InitContainers[1])
|
||||||
|
|
||||||
// Read it from outside the subPath from container 1
|
// Read it from outside the subPath from container 1
|
||||||
testReadFile(input.f, input.filePathInVolume, input.pod, 1)
|
testReadFile(input.f, input.filePathInVolume, input.pod, 1)
|
||||||
|
@ -291,7 +291,7 @@ func testSubPath(input *subPathTestInput) {
|
||||||
SubPath: "subpath2",
|
SubPath: "subpath2",
|
||||||
})
|
})
|
||||||
|
|
||||||
addMultipleWrites(&input.pod.Spec.Containers[0], filepath1, filepath2)
|
addMultipleWrites(&input.pod.Spec.InitContainers[1], filepath1, filepath2)
|
||||||
testMultipleReads(input.f, input.pod, 0, filepath1, filepath2)
|
testMultipleReads(input.f, input.pod, 0, filepath1, filepath2)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -325,8 +325,8 @@ func testSubPath(input *subPathTestInput) {
|
||||||
// Create the directory
|
// Create the directory
|
||||||
setInitCommand(input.pod, fmt.Sprintf("mkdir -p %s", input.subPathDir))
|
setInitCommand(input.pod, fmt.Sprintf("mkdir -p %s", input.subPathDir))
|
||||||
|
|
||||||
// Write the file in the volume from container 1
|
// Write the file in the volume from init container 2
|
||||||
setWriteCommand(input.filePathInVolume, &input.pod.Spec.Containers[1])
|
setWriteCommand(input.filePathInVolume, &input.pod.Spec.InitContainers[2])
|
||||||
|
|
||||||
// Read it from inside the subPath from container 0
|
// Read it from inside the subPath from container 0
|
||||||
input.pod.Spec.Containers[0].VolumeMounts[0].ReadOnly = true
|
input.pod.Spec.Containers[0].VolumeMounts[0].ReadOnly = true
|
||||||
|
@ -337,8 +337,8 @@ func testSubPath(input *subPathTestInput) {
|
||||||
// Create the file
|
// Create the file
|
||||||
setInitCommand(input.pod, fmt.Sprintf("touch %s", input.subPathDir))
|
setInitCommand(input.pod, fmt.Sprintf("touch %s", input.subPathDir))
|
||||||
|
|
||||||
// Write the file in the volume from container 1
|
// Write the file in the volume from init container 2
|
||||||
setWriteCommand(input.subPathDir, &input.pod.Spec.Containers[1])
|
setWriteCommand(input.subPathDir, &input.pod.Spec.InitContainers[2])
|
||||||
|
|
||||||
// Read it from inside the subPath from container 0
|
// Read it from inside the subPath from container 0
|
||||||
input.pod.Spec.Containers[0].VolumeMounts[0].ReadOnly = true
|
input.pod.Spec.Containers[0].VolumeMounts[0].ReadOnly = true
|
||||||
|
@ -350,8 +350,19 @@ func testSubPath(input *subPathTestInput) {
|
||||||
framework.Skipf("Volume type %v doesn't support readOnly source", input.volType)
|
framework.Skipf("Volume type %v doesn't support readOnly source", input.volType)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize content in the volume while it's writable
|
pod := input.pod.DeepCopy()
|
||||||
initVolumeContent(input.f, input.pod, input.filePathInVolume, input.filePathInSubpath)
|
|
||||||
|
// Create the directory
|
||||||
|
setInitCommand(input.pod, fmt.Sprintf("mkdir -p %s", input.subPathDir))
|
||||||
|
|
||||||
|
// Write the file in the subPath from init container 1
|
||||||
|
setWriteCommand(input.filePathInSubpath, &input.pod.Spec.InitContainers[1])
|
||||||
|
|
||||||
|
// Read it from inside the subPath from container 0
|
||||||
|
testReadFile(input.f, input.filePathInSubpath, input.pod, 0)
|
||||||
|
|
||||||
|
// Reset the pod
|
||||||
|
input.pod = pod
|
||||||
|
|
||||||
// Set volume source to read only
|
// Set volume source to read only
|
||||||
input.pod.Spec.Volumes[0].VolumeSource = *input.roVol
|
input.pod.Spec.Volumes[0].VolumeSource = *input.roVol
|
||||||
|
@ -384,6 +395,7 @@ func testSubPath(input *subPathTestInput) {
|
||||||
input.pod.Spec.Containers[1].Command = []string{"/bin/sh", "-ec", "sleep 100000"}
|
input.pod.Spec.Containers[1].Command = []string{"/bin/sh", "-ec", "sleep 100000"}
|
||||||
|
|
||||||
By(fmt.Sprintf("Creating pod %s", input.pod.Name))
|
By(fmt.Sprintf("Creating pod %s", input.pod.Name))
|
||||||
|
removeUnusedContainers(input.pod)
|
||||||
pod, err := input.f.ClientSet.CoreV1().Pods(input.f.Namespace.Name).Create(input.pod)
|
pod, err := input.f.ClientSet.CoreV1().Pods(input.f.Namespace.Name).Create(input.pod)
|
||||||
Expect(err).ToNot(HaveOccurred(), "while creating pod")
|
Expect(err).ToNot(HaveOccurred(), "while creating pod")
|
||||||
defer func() {
|
defer func() {
|
||||||
|
@ -416,6 +428,7 @@ func TestBasicSubpathFile(f *framework.Framework, contents string, pod *v1.Pod,
|
||||||
setReadCommand(filepath, &pod.Spec.Containers[0])
|
setReadCommand(filepath, &pod.Spec.Containers[0])
|
||||||
|
|
||||||
By(fmt.Sprintf("Creating pod %s", pod.Name))
|
By(fmt.Sprintf("Creating pod %s", pod.Name))
|
||||||
|
removeUnusedContainers(pod)
|
||||||
f.TestContainerOutput("atomic-volume-subpath", pod, 0, []string{contents})
|
f.TestContainerOutput("atomic-volume-subpath", pod, 0, []string{contents})
|
||||||
|
|
||||||
By(fmt.Sprintf("Deleting pod %s", pod.Name))
|
By(fmt.Sprintf("Deleting pod %s", pod.Name))
|
||||||
|
@ -467,6 +480,41 @@ func SubpathTestPod(f *framework.Framework, subpath, volumeType string, source *
|
||||||
Privileged: &privilegedSecurityContext,
|
Privileged: &privilegedSecurityContext,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Name: fmt.Sprintf("test-init-subpath-%s", suffix),
|
||||||
|
Image: mountImage,
|
||||||
|
VolumeMounts: []v1.VolumeMount{
|
||||||
|
{
|
||||||
|
Name: volumeName,
|
||||||
|
MountPath: volumePath,
|
||||||
|
SubPath: subpath,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: probeVolumeName,
|
||||||
|
MountPath: probeVolumePath,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
SecurityContext: &v1.SecurityContext{
|
||||||
|
Privileged: &privilegedSecurityContext,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: fmt.Sprintf("test-init-volume-%s", suffix),
|
||||||
|
Image: mountImage,
|
||||||
|
VolumeMounts: []v1.VolumeMount{
|
||||||
|
{
|
||||||
|
Name: volumeName,
|
||||||
|
MountPath: volumePath,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: probeVolumeName,
|
||||||
|
MountPath: probeVolumePath,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
SecurityContext: &v1.SecurityContext{
|
||||||
|
Privileged: &privilegedSecurityContext,
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Containers: []v1.Container{
|
Containers: []v1.Container{
|
||||||
{
|
{
|
||||||
|
@ -528,6 +576,33 @@ func SubpathTestPod(f *framework.Framework, subpath, volumeType string, source *
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func containerIsUnused(container *v1.Container) bool {
|
||||||
|
// mountImage with nil Args does nothing. Leave everything else
|
||||||
|
return container.Image == mountImage && container.Args == nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// removeUnusedContainers removes containers from a SubpathTestPod that aren't
|
||||||
|
// needed for a test. e.g. to test for subpath mount failure, only one
|
||||||
|
// container needs to run and get its status checked.
|
||||||
|
func removeUnusedContainers(pod *v1.Pod) {
|
||||||
|
initContainers := []v1.Container{}
|
||||||
|
containers := []v1.Container{}
|
||||||
|
if pod.Spec.InitContainers[0].Command != nil {
|
||||||
|
initContainers = append(initContainers, pod.Spec.InitContainers[0])
|
||||||
|
}
|
||||||
|
for _, ic := range pod.Spec.InitContainers[1:] {
|
||||||
|
if !containerIsUnused(&ic) {
|
||||||
|
initContainers = append(initContainers, ic)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
containers = append(containers, pod.Spec.Containers[0])
|
||||||
|
if !containerIsUnused(&pod.Spec.Containers[1]) {
|
||||||
|
containers = append(containers, pod.Spec.Containers[1])
|
||||||
|
}
|
||||||
|
pod.Spec.InitContainers = initContainers
|
||||||
|
pod.Spec.Containers = containers
|
||||||
|
}
|
||||||
|
|
||||||
// volumeFormatPod returns a Pod that does nothing but will cause the plugin to format a filesystem
|
// volumeFormatPod returns a Pod that does nothing but will cause the plugin to format a filesystem
|
||||||
// on first use
|
// on first use
|
||||||
func volumeFormatPod(f *framework.Framework, volumeSource *v1.VolumeSource) *v1.Pod {
|
func volumeFormatPod(f *framework.Framework, volumeSource *v1.VolumeSource) *v1.Pod {
|
||||||
|
@ -562,6 +637,8 @@ func volumeFormatPod(f *framework.Framework, volumeSource *v1.VolumeSource) *v1.
|
||||||
|
|
||||||
func clearSubpathPodCommands(pod *v1.Pod) {
|
func clearSubpathPodCommands(pod *v1.Pod) {
|
||||||
pod.Spec.InitContainers[0].Command = nil
|
pod.Spec.InitContainers[0].Command = nil
|
||||||
|
pod.Spec.InitContainers[1].Args = nil
|
||||||
|
pod.Spec.InitContainers[2].Args = nil
|
||||||
pod.Spec.Containers[0].Args = nil
|
pod.Spec.Containers[0].Args = nil
|
||||||
pod.Spec.Containers[1].Args = nil
|
pod.Spec.Containers[1].Args = nil
|
||||||
}
|
}
|
||||||
|
@ -591,6 +668,7 @@ func addMultipleWrites(container *v1.Container, file1 string, file2 string) {
|
||||||
|
|
||||||
func testMultipleReads(f *framework.Framework, pod *v1.Pod, containerIndex int, file1 string, file2 string) {
|
func testMultipleReads(f *framework.Framework, pod *v1.Pod, containerIndex int, file1 string, file2 string) {
|
||||||
By(fmt.Sprintf("Creating pod %s", pod.Name))
|
By(fmt.Sprintf("Creating pod %s", pod.Name))
|
||||||
|
removeUnusedContainers(pod)
|
||||||
f.TestContainerOutput("multi_subpath", pod, containerIndex, []string{
|
f.TestContainerOutput("multi_subpath", pod, containerIndex, []string{
|
||||||
"content of file \"" + file1 + "\": mount-tester new file",
|
"content of file \"" + file1 + "\": mount-tester new file",
|
||||||
"content of file \"" + file2 + "\": mount-tester new file",
|
"content of file \"" + file2 + "\": mount-tester new file",
|
||||||
|
@ -608,6 +686,7 @@ func testReadFile(f *framework.Framework, file string, pod *v1.Pod, containerInd
|
||||||
setReadCommand(file, &pod.Spec.Containers[containerIndex])
|
setReadCommand(file, &pod.Spec.Containers[containerIndex])
|
||||||
|
|
||||||
By(fmt.Sprintf("Creating pod %s", pod.Name))
|
By(fmt.Sprintf("Creating pod %s", pod.Name))
|
||||||
|
removeUnusedContainers(pod)
|
||||||
f.TestContainerOutput("subpath", pod, containerIndex, []string{
|
f.TestContainerOutput("subpath", pod, containerIndex, []string{
|
||||||
"content of file \"" + file + "\": mount-tester new file",
|
"content of file \"" + file + "\": mount-tester new file",
|
||||||
})
|
})
|
||||||
|
@ -623,6 +702,7 @@ func testPodFailSubpath(f *framework.Framework, pod *v1.Pod, allowContainerTermi
|
||||||
|
|
||||||
func testPodFailSubpathError(f *framework.Framework, pod *v1.Pod, errorMsg string, allowContainerTerminationError bool) {
|
func testPodFailSubpathError(f *framework.Framework, pod *v1.Pod, errorMsg string, allowContainerTerminationError bool) {
|
||||||
By(fmt.Sprintf("Creating pod %s", pod.Name))
|
By(fmt.Sprintf("Creating pod %s", pod.Name))
|
||||||
|
removeUnusedContainers(pod)
|
||||||
pod, err := f.ClientSet.CoreV1().Pods(f.Namespace.Name).Create(pod)
|
pod, err := f.ClientSet.CoreV1().Pods(f.Namespace.Name).Create(pod)
|
||||||
Expect(err).ToNot(HaveOccurred(), "while creating pod")
|
Expect(err).ToNot(HaveOccurred(), "while creating pod")
|
||||||
defer func() {
|
defer func() {
|
||||||
|
@ -704,6 +784,7 @@ func testPodContainerRestart(f *framework.Framework, pod *v1.Pod) {
|
||||||
|
|
||||||
// Start pod
|
// Start pod
|
||||||
By(fmt.Sprintf("Creating pod %s", pod.Name))
|
By(fmt.Sprintf("Creating pod %s", pod.Name))
|
||||||
|
removeUnusedContainers(pod)
|
||||||
pod, err := f.ClientSet.CoreV1().Pods(f.Namespace.Name).Create(pod)
|
pod, err := f.ClientSet.CoreV1().Pods(f.Namespace.Name).Create(pod)
|
||||||
Expect(err).ToNot(HaveOccurred(), "while creating pod")
|
Expect(err).ToNot(HaveOccurred(), "while creating pod")
|
||||||
defer func() {
|
defer func() {
|
||||||
|
@ -791,6 +872,7 @@ func testSubpathReconstruction(f *framework.Framework, pod *v1.Pod, forceDelete
|
||||||
pod.Spec.TerminationGracePeriodSeconds = &gracePeriod
|
pod.Spec.TerminationGracePeriodSeconds = &gracePeriod
|
||||||
|
|
||||||
By(fmt.Sprintf("Creating pod %s", pod.Name))
|
By(fmt.Sprintf("Creating pod %s", pod.Name))
|
||||||
|
removeUnusedContainers(pod)
|
||||||
pod, err := f.ClientSet.CoreV1().Pods(f.Namespace.Name).Create(pod)
|
pod, err := f.ClientSet.CoreV1().Pods(f.Namespace.Name).Create(pod)
|
||||||
Expect(err).ToNot(HaveOccurred(), "while creating pod")
|
Expect(err).ToNot(HaveOccurred(), "while creating pod")
|
||||||
|
|
||||||
|
@ -815,23 +897,6 @@ func formatVolume(f *framework.Framework, pod *v1.Pod) {
|
||||||
Expect(err).ToNot(HaveOccurred(), "while deleting volume init pod")
|
Expect(err).ToNot(HaveOccurred(), "while deleting volume init pod")
|
||||||
}
|
}
|
||||||
|
|
||||||
func initVolumeContent(f *framework.Framework, pod *v1.Pod, volumeFilepath, subpathFilepath string) {
|
|
||||||
setWriteCommand(volumeFilepath, &pod.Spec.Containers[1])
|
|
||||||
setReadCommand(subpathFilepath, &pod.Spec.Containers[0])
|
|
||||||
|
|
||||||
By(fmt.Sprintf("Creating pod to write volume content %s", pod.Name))
|
|
||||||
f.TestContainerOutput("subpath", pod, 0, []string{
|
|
||||||
"content of file \"" + subpathFilepath + "\": mount-tester new file",
|
|
||||||
})
|
|
||||||
|
|
||||||
By(fmt.Sprintf("Deleting pod %s", pod.Name))
|
|
||||||
err := framework.DeletePodWithWait(f, f.ClientSet, pod)
|
|
||||||
Expect(err).NotTo(HaveOccurred(), "while deleting pod")
|
|
||||||
|
|
||||||
// This pod spec is going to be reused; reset all the commands
|
|
||||||
clearSubpathPodCommands(pod)
|
|
||||||
}
|
|
||||||
|
|
||||||
func podContainerExec(pod *v1.Pod, containerIndex int, bashExec string) (string, error) {
|
func podContainerExec(pod *v1.Pod, containerIndex int, bashExec 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)
|
return framework.RunKubectl("exec", fmt.Sprintf("--namespace=%s", pod.Namespace), pod.Name, "--container", pod.Spec.Containers[containerIndex].Name, "--", "/bin/sh", "-c", bashExec)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue