From f9fe3534d4d2ce4c628f4fac3cf42ceea89c6f6e Mon Sep 17 00:00:00 2001 From: Matthew Wong Date: Wed, 17 May 2017 00:09:41 -0400 Subject: [PATCH] Add subPath e2e: test permissions and when subPath pre-exists --- test/e2e/common/empty_dir.go | 80 ++++++++++++++++++++----------- test/e2e/common/host_path.go | 91 ++++++++++++++++++++++++++++++++++-- test/e2e/framework/util.go | 6 +++ 3 files changed, 148 insertions(+), 29 deletions(-) diff --git a/test/e2e/common/empty_dir.go b/test/e2e/common/empty_dir.go index 7b358849bb7a..7f4415205a0d 100644 --- a/test/e2e/common/empty_dir.go +++ b/test/e2e/common/empty_dir.go @@ -32,6 +32,7 @@ import ( const ( testImageRootUid = "gcr.io/google_containers/mounttest:0.8" testImageNonRootUid = "gcr.io/google_containers/mounttest-user:0.5" + volumePath = "/test-volume" ) var _ = framework.KubeDescribe("EmptyDir volumes", func() { @@ -47,6 +48,10 @@ var _ = framework.KubeDescribe("EmptyDir volumes", func() { doTestSetgidFSGroup(f, testImageNonRootUid, v1.StorageMediumMemory) }) + It("nonexistent volume subPath should have the correct mode and owner using FSGroup [Volume]", func() { + doTestSubPathFSGroup(f, testImageNonRootUid, v1.StorageMediumMemory) + }) + It("files with FSGroup ownership should support (root,0644,tmpfs) [Volume]", func() { doTest0644FSGroup(f, testImageRootUid, v1.StorageMediumMemory) }) @@ -124,10 +129,9 @@ const ( func doTestSetgidFSGroup(f *framework.Framework, image string, medium v1.StorageMedium) { var ( - volumePath = "/test-volume" - filePath = path.Join(volumePath, "test-file") - source = &v1.EmptyDirVolumeSource{Medium: medium} - pod = testPodWithVolume(testImageRootUid, volumePath, source) + filePath = path.Join(volumePath, "test-file") + source = &v1.EmptyDirVolumeSource{Medium: medium} + pod = testPodWithVolume(testImageRootUid, volumePath, source) ) pod.Spec.Containers[0].Args = []string{ @@ -152,11 +156,40 @@ func doTestSetgidFSGroup(f *framework.Framework, image string, medium v1.Storage f.TestContainerOutput(msg, pod, 0, out) } +func doTestSubPathFSGroup(f *framework.Framework, image string, medium v1.StorageMedium) { + var ( + subPath = "test-sub" + source = &v1.EmptyDirVolumeSource{Medium: medium} + pod = testPodWithVolume(image, volumePath, source) + ) + + pod.Spec.Containers[0].Args = []string{ + fmt.Sprintf("--fs_type=%v", volumePath), + fmt.Sprintf("--file_perm=%v", volumePath), + fmt.Sprintf("--file_owner=%v", volumePath), + } + + pod.Spec.Containers[0].VolumeMounts[0].SubPath = subPath + + fsGroup := int64(123) + pod.Spec.SecurityContext.FSGroup = &fsGroup + + msg := fmt.Sprintf("emptydir subpath on %v", formatMedium(medium)) + out := []string{ + "perms of file \"/test-volume\": -rwxrwxrwx", + "owner UID of \"/test-volume\": 0", + "owner GID of \"/test-volume\": 123", + } + if medium == v1.StorageMediumMemory { + out = append(out, "mount type of \"/test-volume\": tmpfs") + } + f.TestContainerOutput(msg, pod, 0, out) +} + func doTestVolumeModeFSGroup(f *framework.Framework, image string, medium v1.StorageMedium) { var ( - volumePath = "/test-volume" - source = &v1.EmptyDirVolumeSource{Medium: medium} - pod = testPodWithVolume(testImageRootUid, volumePath, source) + source = &v1.EmptyDirVolumeSource{Medium: medium} + pod = testPodWithVolume(testImageRootUid, volumePath, source) ) pod.Spec.Containers[0].Args = []string{ @@ -179,10 +212,9 @@ func doTestVolumeModeFSGroup(f *framework.Framework, image string, medium v1.Sto func doTest0644FSGroup(f *framework.Framework, image string, medium v1.StorageMedium) { var ( - volumePath = "/test-volume" - filePath = path.Join(volumePath, "test-file") - source = &v1.EmptyDirVolumeSource{Medium: medium} - pod = testPodWithVolume(image, volumePath, source) + filePath = path.Join(volumePath, "test-file") + source = &v1.EmptyDirVolumeSource{Medium: medium} + pod = testPodWithVolume(image, volumePath, source) ) pod.Spec.Containers[0].Args = []string{ @@ -207,9 +239,8 @@ func doTest0644FSGroup(f *framework.Framework, image string, medium v1.StorageMe func doTestVolumeMode(f *framework.Framework, image string, medium v1.StorageMedium) { var ( - volumePath = "/test-volume" - source = &v1.EmptyDirVolumeSource{Medium: medium} - pod = testPodWithVolume(testImageRootUid, volumePath, source) + source = &v1.EmptyDirVolumeSource{Medium: medium} + pod = testPodWithVolume(testImageRootUid, volumePath, source) ) pod.Spec.Containers[0].Args = []string{ @@ -229,10 +260,9 @@ func doTestVolumeMode(f *framework.Framework, image string, medium v1.StorageMed func doTest0644(f *framework.Framework, image string, medium v1.StorageMedium) { var ( - volumePath = "/test-volume" - filePath = path.Join(volumePath, "test-file") - source = &v1.EmptyDirVolumeSource{Medium: medium} - pod = testPodWithVolume(image, volumePath, source) + filePath = path.Join(volumePath, "test-file") + source = &v1.EmptyDirVolumeSource{Medium: medium} + pod = testPodWithVolume(image, volumePath, source) ) pod.Spec.Containers[0].Args = []string{ @@ -254,10 +284,9 @@ func doTest0644(f *framework.Framework, image string, medium v1.StorageMedium) { func doTest0666(f *framework.Framework, image string, medium v1.StorageMedium) { var ( - volumePath = "/test-volume" - filePath = path.Join(volumePath, "test-file") - source = &v1.EmptyDirVolumeSource{Medium: medium} - pod = testPodWithVolume(image, volumePath, source) + filePath = path.Join(volumePath, "test-file") + source = &v1.EmptyDirVolumeSource{Medium: medium} + pod = testPodWithVolume(image, volumePath, source) ) pod.Spec.Containers[0].Args = []string{ @@ -279,10 +308,9 @@ func doTest0666(f *framework.Framework, image string, medium v1.StorageMedium) { func doTest0777(f *framework.Framework, image string, medium v1.StorageMedium) { var ( - volumePath = "/test-volume" - filePath = path.Join(volumePath, "test-file") - source = &v1.EmptyDirVolumeSource{Medium: medium} - pod = testPodWithVolume(image, volumePath, source) + filePath = path.Join(volumePath, "test-file") + source = &v1.EmptyDirVolumeSource{Medium: medium} + pod = testPodWithVolume(image, volumePath, source) ) pod.Spec.Containers[0].Args = []string{ diff --git a/test/e2e/common/host_path.go b/test/e2e/common/host_path.go index e57a6e9abb04..c2f8e4706354 100644 --- a/test/e2e/common/host_path.go +++ b/test/e2e/common/host_path.go @@ -35,12 +35,12 @@ var _ = framework.KubeDescribe("HostPath", func() { f := framework.NewDefaultFramework("hostpath") BeforeEach(func() { + // TODO permission denied cleanup failures //cleanup before running the test. _ = os.Remove("/tmp/test-file") }) It("should give a volume the correct mode [Conformance] [Volume]", func() { - volumePath := "/test-volume" source := &v1.HostPathVolumeSource{ Path: "/tmp", } @@ -57,7 +57,6 @@ var _ = framework.KubeDescribe("HostPath", func() { // This test requires mounting a folder into a container with write privileges. It("should support r/w [Volume]", func() { - volumePath := "/test-volume" filePath := path.Join(volumePath, "test-file") retryDuration := 180 source := &v1.HostPathVolumeSource{ @@ -82,7 +81,6 @@ var _ = framework.KubeDescribe("HostPath", func() { }) It("should support subPath [Volume]", func() { - volumePath := "/test-volume" subPath := "sub-path" fileName := "test-file" retryDuration := 180 @@ -94,6 +92,7 @@ var _ = framework.KubeDescribe("HostPath", func() { Path: "/tmp", } pod := testPodWithHostVol(volumePath, source) + // Write the file in the subPath from container 0 container := &pod.Spec.Containers[0] container.VolumeMounts[0].SubPath = subPath @@ -101,6 +100,92 @@ var _ = framework.KubeDescribe("HostPath", func() { fmt.Sprintf("--new_file_0644=%v", filePathInWriter), fmt.Sprintf("--file_mode=%v", filePathInWriter), } + + // Read it from outside the subPath from container 1 + pod.Spec.Containers[1].Args = []string{ + fmt.Sprintf("--file_content_in_loop=%v", filePathInReader), + fmt.Sprintf("--retry_time=%d", retryDuration), + } + + f.TestContainerOutput("hostPath subPath", pod, 1, []string{ + "content of file \"" + filePathInReader + "\": mount-tester new file", + }) + }) + + It("should support existing directory subPath [Volume]", func() { + framework.SkipUnlessSSHKeyPresent() + + subPath := "sub-path" + fileName := "test-file" + retryDuration := 180 + + filePathInWriter := path.Join(volumePath, fileName) + filePathInReader := path.Join(volumePath, subPath, fileName) + + source := &v1.HostPathVolumeSource{ + Path: "/tmp", + } + pod := testPodWithHostVol(volumePath, source) + nodeList := framework.GetReadySchedulableNodesOrDie(f.ClientSet) + pod.Spec.NodeName = nodeList.Items[0].Name + + // Create the subPath directory on the host + existing := path.Join(source.Path, subPath) + result, err := framework.SSH(fmt.Sprintf("mkdir -p %s", existing), framework.GetNodeExternalIP(&nodeList.Items[0]), framework.TestContext.Provider) + framework.LogSSHResult(result) + framework.ExpectNoError(err) + if result.Code != 0 { + framework.Failf("mkdir returned non-zero") + } + + // Write the file in the subPath from container 0 + container := &pod.Spec.Containers[0] + container.VolumeMounts[0].SubPath = subPath + container.Args = []string{ + fmt.Sprintf("--new_file_0644=%v", filePathInWriter), + fmt.Sprintf("--file_mode=%v", filePathInWriter), + } + + // Read it from outside the subPath from container 1 + pod.Spec.Containers[1].Args = []string{ + fmt.Sprintf("--file_content_in_loop=%v", filePathInReader), + fmt.Sprintf("--retry_time=%d", retryDuration), + } + + f.TestContainerOutput("hostPath subPath", pod, 1, []string{ + "content of file \"" + filePathInReader + "\": mount-tester new file", + }) + }) + + // TODO consolidate common code of this test and above + It("should support existing single file subPath [Volume]", func() { + framework.SkipUnlessSSHKeyPresent() + + subPath := "sub-path-test-file" + retryDuration := 180 + + filePathInReader := path.Join(volumePath, subPath) + + source := &v1.HostPathVolumeSource{ + Path: "/tmp", + } + pod := testPodWithHostVol(volumePath, source) + nodeList := framework.GetReadySchedulableNodesOrDie(f.ClientSet) + pod.Spec.NodeName = nodeList.Items[0].Name + + // Create the subPath file on the host + existing := path.Join(source.Path, subPath) + result, err := framework.SSH(fmt.Sprintf("echo \"mount-tester new file\" > %s", existing), framework.GetNodeExternalIP(&nodeList.Items[0]), framework.TestContext.Provider) + framework.LogSSHResult(result) + framework.ExpectNoError(err) + if result.Code != 0 { + framework.Failf("echo returned non-zero") + } + + // Mount the file to the subPath in container 0 + container := &pod.Spec.Containers[0] + container.VolumeMounts[0].SubPath = subPath + // Read it from outside the subPath from container 1 pod.Spec.Containers[1].Args = []string{ fmt.Sprintf("--file_content_in_loop=%v", filePathInReader), diff --git a/test/e2e/framework/util.go b/test/e2e/framework/util.go index ff12661724b0..16003406d49a 100644 --- a/test/e2e/framework/util.go +++ b/test/e2e/framework/util.go @@ -307,6 +307,12 @@ func SkipIfProviderIs(unsupportedProviders ...string) { } } +func SkipUnlessSSHKeyPresent() { + if _, err := GetSigner(TestContext.Provider); err != nil { + Skipf("No SSH Key for provider %s: '%v'", TestContext.Provider, err) + } +} + func SkipUnlessProviderIs(supportedProviders ...string) { if !ProviderIs(supportedProviders...) { Skipf("Only supported for providers %v (not %s)", supportedProviders, TestContext.Provider)