Code change:
<ins> /* Copyright 2020 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package storage import ( "context" "fmt" "path" "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/fields" "k8s.io/kubernetes/pkg/kubelet/events" "k8s.io/kubernetes/test/e2e/framework" e2eevents "k8s.io/kubernetes/test/e2e/framework/events" e2epod "k8s.io/kubernetes/test/e2e/framework/pod" "k8s.io/kubernetes/test/e2e/storage/utils" imageutils "k8s.io/kubernetes/test/utils/image" "github.com/onsi/ginkgo" ) var _ = utils.SIGDescribe("HostPathType Directory [Slow]", func() { f := framework.NewDefaultFramework("host-path-type-directory") var ( ns           string hostBaseDir  string mountBaseDir string basePod      *v1.Pod targetDir    string hostPathUnset             = v1.HostPathUnset hostPathDirectoryOrCreate = v1.HostPathDirectoryOrCreate hostPathDirectory         = v1.HostPathDirectory hostPathFile              = v1.HostPathFile hostPathSocket            = v1.HostPathSocket hostPathCharDev           = v1.HostPathCharDev hostPathBlockDev          = v1.HostPathBlockDev ) ginkgo.BeforeEach(func() { ns = f.Namespace.Name ginkgo.By("Create a pod for further testing") hostBaseDir = path.Join("/tmp", ns) mountBaseDir = "/mnt/test" basePod = f.PodClient().CreateSync(newHostPathTypeTestPod(map[string]string{}, hostBaseDir, mountBaseDir, &hostPathDirectoryOrCreate)) ginkgo.By(fmt.Sprintf("running on node %s", basePod.Spec.NodeName)) targetDir = path.Join(hostBaseDir, "adir") ginkgo.By("Should automatically create a new directory 'adir' when HostPathType is HostPathDirectoryOrCreate") verifyPodHostPathType(f, map[string]string{"kubernetes.io/hostname": basePod.Spec.NodeName}, targetDir, &hostPathDirectoryOrCreate) }) ginkgo.It("Should fail on mounting non-existent directory 'does-not-exist-dir' when HostPathType is HostPathDirectory", func() { dirPath := path.Join(hostBaseDir, "does-not-exist-dir") verifyPodHostPathTypeFailure(f, map[string]string{"kubernetes.io/hostname": basePod.Spec.NodeName}, dirPath, fmt.Sprintf("%s is not a directory", dirPath), &hostPathDirectory) }) ginkgo.It("Should be able to mount directory 'adir' successfully when HostPathType is HostPathDirectory", func() { verifyPodHostPathType(f, map[string]string{"kubernetes.io/hostname": basePod.Spec.NodeName}, targetDir, &hostPathDirectory) }) ginkgo.It("Should be able to mount directory 'adir' successfully when HostPathType is HostPathUnset", func() { verifyPodHostPathType(f, map[string]string{"kubernetes.io/hostname": basePod.Spec.NodeName}, targetDir, &hostPathUnset) }) ginkgo.It("Should fail on mounting directory 'adir' when HostPathType is HostPathFile", func() { verifyPodHostPathTypeFailure(f, map[string]string{"kubernetes.io/hostname": basePod.Spec.NodeName}, targetDir, fmt.Sprintf("%s is not a file", targetDir), &hostPathFile) }) ginkgo.It("Should fail on mounting directory 'adir' when HostPathType is HostPathSocket", func() { verifyPodHostPathTypeFailure(f, map[string]string{"kubernetes.io/hostname": basePod.Spec.NodeName}, targetDir, fmt.Sprintf("%s is not a socket", targetDir), &hostPathSocket) }) ginkgo.It("Should fail on mounting directory 'adir' when HostPathType is HostPathCharDev", func() { verifyPodHostPathTypeFailure(f, map[string]string{"kubernetes.io/hostname": basePod.Spec.NodeName}, targetDir, fmt.Sprintf("%s is not a character device", targetDir), &hostPathCharDev) }) ginkgo.It("Should fail on mounting directory 'adir' when HostPathType is HostPathBlockDev", func() { verifyPodHostPathTypeFailure(f, map[string]string{"kubernetes.io/hostname": basePod.Spec.NodeName}, targetDir, fmt.Sprintf("%s is not a block device", targetDir), &hostPathBlockDev) }) }) var _ = utils.SIGDescribe("HostPathType File [Slow]", func() { f := framework.NewDefaultFramework("host-path-type-file") var ( ns           string hostBaseDir  string mountBaseDir string basePod      *v1.Pod targetFile   string hostPathUnset             = v1.HostPathUnset hostPathDirectoryOrCreate = v1.HostPathDirectoryOrCreate hostPathDirectory         = v1.HostPathDirectory hostPathFileOrCreate      = v1.HostPathFileOrCreate hostPathFile              = v1.HostPathFile hostPathSocket            = v1.HostPathSocket hostPathCharDev           = v1.HostPathCharDev hostPathBlockDev          = v1.HostPathBlockDev ) ginkgo.BeforeEach(func() { ns = f.Namespace.Name ginkgo.By("Create a pod for further testing") hostBaseDir = path.Join("/tmp", ns) mountBaseDir = "/mnt/test" basePod = f.PodClient().CreateSync(newHostPathTypeTestPod(map[string]string{}, hostBaseDir, mountBaseDir, &hostPathDirectoryOrCreate)) ginkgo.By(fmt.Sprintf("running on node %s", basePod.Spec.NodeName)) targetFile = path.Join(hostBaseDir, "afile") ginkgo.By("Should automatically create a new file 'afile' when HostPathType is HostPathFileOrCreate") verifyPodHostPathType(f, map[string]string{"kubernetes.io/hostname": basePod.Spec.NodeName}, targetFile, &hostPathFileOrCreate) }) ginkgo.It("Should fail on mounting non-existent file 'does-not-exist-file' when HostPathType is HostPathFile", func() { filePath := path.Join(hostBaseDir, "does-not-exist-file") verifyPodHostPathTypeFailure(f, map[string]string{"kubernetes.io/hostname": basePod.Spec.NodeName}, filePath, fmt.Sprintf("%s is not a file", filePath), &hostPathFile) }) ginkgo.It("Should be able to mount file 'afile' successfully when HostPathType is HostPathFile", func() { verifyPodHostPathType(f, map[string]string{"kubernetes.io/hostname": basePod.Spec.NodeName}, targetFile, &hostPathFile) }) ginkgo.It("Should be able to mount file 'afile' successfully when HostPathType is HostPathUnset", func() { verifyPodHostPathType(f, map[string]string{"kubernetes.io/hostname": basePod.Spec.NodeName}, targetFile, &hostPathUnset) }) ginkgo.It("Should fail on mounting file 'afile' when HostPathType is HostPathDirectory", func() { verifyPodHostPathTypeFailure(f, map[string]string{"kubernetes.io/hostname": basePod.Spec.NodeName}, targetFile, fmt.Sprintf("%s is not a directory", targetFile), &hostPathDirectory) }) ginkgo.It("Should fail on mounting file 'afile' when HostPathType is HostPathSocket", func() { verifyPodHostPathTypeFailure(f, map[string]string{"kubernetes.io/hostname": basePod.Spec.NodeName}, targetFile, fmt.Sprintf("%s is not a socket", targetFile), &hostPathSocket) }) ginkgo.It("Should fail on mounting file 'afile' when HostPathType is HostPathCharDev", func() { verifyPodHostPathTypeFailure(f, map[string]string{"kubernetes.io/hostname": basePod.Spec.NodeName}, targetFile, fmt.Sprintf("%s is not a character device", targetFile), &hostPathCharDev) }) ginkgo.It("Should fail on mounting file 'afile' when HostPathType is HostPathBlockDev", func() { verifyPodHostPathTypeFailure(f, map[string]string{"kubernetes.io/hostname": basePod.Spec.NodeName}, targetFile, fmt.Sprintf("%s is not a block device", targetFile), &hostPathBlockDev) }) }) var _ = utils.SIGDescribe("HostPathType Socket [Slow]", func() { f := framework.NewDefaultFramework("host-path-type-socket") var ( ns           string hostBaseDir  string mountBaseDir string basePod      *v1.Pod targetSocket string hostPathUnset             = v1.HostPathUnset hostPathDirectoryOrCreate = v1.HostPathDirectoryOrCreate hostPathDirectory         = v1.HostPathDirectory hostPathFile              = v1.HostPathFile hostPathSocket            = v1.HostPathSocket hostPathCharDev           = v1.HostPathCharDev hostPathBlockDev          = v1.HostPathBlockDev ) ginkgo.BeforeEach(func() { ns = f.Namespace.Name ginkgo.By("Create a pod for further testing") hostBaseDir = path.Join("/tmp", ns) mountBaseDir = "/mnt/test" basePod = f.PodClient().CreateSync(newHostPathTypeTestPod(map[string]string{}, hostBaseDir, mountBaseDir, &hostPathDirectoryOrCreate)) ginkgo.By(fmt.Sprintf("running on node %s", basePod.Spec.NodeName)) targetSocket = path.Join(hostBaseDir, "asocket") ginkgo.By("Create a socket for further testing") _, err := utils.PodExec(f, basePod, fmt.Sprintf("nc -lU %s &", path.Join(mountBaseDir, "asocket"))) framework.ExpectNoError(err) }) ginkgo.It("Should fail on mounting non-existent socket 'does-not-exist-socket' when HostPathType is HostPathSocket", func() { socketPath := path.Join(hostBaseDir, "does-not-exist-socket") verifyPodHostPathTypeFailure(f, map[string]string{"kubernetes.io/hostname": basePod.Spec.NodeName}, socketPath, fmt.Sprintf("%s is not a socket", socketPath), &hostPathSocket) }) ginkgo.It("Should be able to mount socket 'asocket' successfully when HostPathType is HostPathSocket", func() { verifyPodHostPathType(f, map[string]string{"kubernetes.io/hostname": basePod.Spec.NodeName}, targetSocket, &hostPathSocket) }) ginkgo.It("Should be able to mount socket 'asocket' successfully when HostPathType is HostPathUnset", func() { verifyPodHostPathType(f, map[string]string{"kubernetes.io/hostname": basePod.Spec.NodeName}, targetSocket, &hostPathUnset) }) ginkgo.It("Should fail on mounting socket 'asocket' when HostPathType is HostPathDirectory", func() { verifyPodHostPathTypeFailure(f, map[string]string{"kubernetes.io/hostname": basePod.Spec.NodeName}, targetSocket, fmt.Sprintf("%s is not a directory", targetSocket), &hostPathDirectory) }) ginkgo.It("Should fail on mounting socket 'asocket' when HostPathType is HostPathFile", func() { verifyPodHostPathTypeFailure(f, map[string]string{"kubernetes.io/hostname": basePod.Spec.NodeName}, targetSocket, fmt.Sprintf("%s is not a file", targetSocket), &hostPathFile) }) ginkgo.It("Should fail on mounting socket 'asocket' when HostPathType is HostPathCharDev", func() { verifyPodHostPathTypeFailure(f, map[string]string{"kubernetes.io/hostname": basePod.Spec.NodeName}, targetSocket, fmt.Sprintf("%s is not a character device", targetSocket), &hostPathCharDev) }) ginkgo.It("Should fail on mounting socket 'asocket' when HostPathType is HostPathBlockDev", func() { verifyPodHostPathTypeFailure(f, map[string]string{"kubernetes.io/hostname": basePod.Spec.NodeName}, targetSocket, fmt.Sprintf("%s is not a block device", targetSocket), &hostPathBlockDev) }) }) var _ = utils.SIGDescribe("HostPathType Character Device [Slow]", func() { f := framework.NewDefaultFramework("host-path-type-char-dev") var ( ns            string hostBaseDir   string mountBaseDir  string basePod       *v1.Pod targetCharDev string hostPathUnset             = v1.HostPathUnset hostPathDirectoryOrCreate = v1.HostPathDirectoryOrCreate hostPathDirectory         = v1.HostPathDirectory hostPathFile              = v1.HostPathFile hostPathSocket            = v1.HostPathSocket hostPathCharDev           = v1.HostPathCharDev hostPathBlockDev          = v1.HostPathBlockDev ) ginkgo.BeforeEach(func() { ns = f.Namespace.Name ginkgo.By("Create a pod for further testing") hostBaseDir = path.Join("/tmp", ns) mountBaseDir = "/mnt/test" basePod = f.PodClient().CreateSync(newHostPathTypeTestPod(map[string]string{}, hostBaseDir, mountBaseDir, &hostPathDirectoryOrCreate)) ginkgo.By(fmt.Sprintf("running on node %s", basePod.Spec.NodeName)) targetCharDev = path.Join(hostBaseDir, "achardev") ginkgo.By("Create a character device for further testing") _, err := utils.PodExec(f, basePod, fmt.Sprintf("mknod %s c 89 1", path.Join(mountBaseDir, "achardev"))) framework.ExpectNoError(err) }) ginkgo.It("Should fail on mounting non-existent character device 'does-not-exist-char-dev' when HostPathType is HostPathCharDev", func() { charDevPath := path.Join(hostBaseDir, "does-not-exist-char-dev") verifyPodHostPathTypeFailure(f, map[string]string{"kubernetes.io/hostname": basePod.Spec.NodeName}, charDevPath, fmt.Sprintf("%s is not a character device", charDevPath), &hostPathCharDev) }) ginkgo.It("Should be able to mount character device 'achardev' successfully when HostPathType is HostPathCharDev", func() { verifyPodHostPathType(f, map[string]string{"kubernetes.io/hostname": basePod.Spec.NodeName}, targetCharDev, &hostPathCharDev) }) ginkgo.It("Should be able to mount character device 'achardev' successfully when HostPathType is HostPathUnset", func() { verifyPodHostPathType(f, map[string]string{"kubernetes.io/hostname": basePod.Spec.NodeName}, targetCharDev, &hostPathUnset) }) ginkgo.It("Should fail on mounting character device 'achardev' when HostPathType is HostPathDirectory", func() { verifyPodHostPathTypeFailure(f, map[string]string{"kubernetes.io/hostname": basePod.Spec.NodeName}, targetCharDev, fmt.Sprintf("%s is not a directory", targetCharDev), &hostPathDirectory) }) ginkgo.It("Should fail on mounting character device 'achardev' when HostPathType is HostPathFile", func() { verifyPodHostPathTypeFailure(f, map[string]string{"kubernetes.io/hostname": basePod.Spec.NodeName}, targetCharDev, fmt.Sprintf("%s is not a file", targetCharDev), &hostPathFile) }) ginkgo.It("Should fail on mounting character device 'achardev' when HostPathType is HostPathSocket", func() { verifyPodHostPathTypeFailure(f, map[string]string{"kubernetes.io/hostname": basePod.Spec.NodeName}, targetCharDev, fmt.Sprintf("%s is not a socket", targetCharDev), &hostPathSocket) }) ginkgo.It("Should fail on mounting character device 'achardev' when HostPathType is HostPathBlockDev", func() { verifyPodHostPathTypeFailure(f, map[string]string{"kubernetes.io/hostname": basePod.Spec.NodeName}, targetCharDev, fmt.Sprintf("%s is not a block device", targetCharDev), &hostPathBlockDev) }) }) var _ = utils.SIGDescribe("HostPathType Block Device [Slow]", func() { f := framework.NewDefaultFramework("host-path-type-block-dev") var ( ns             string hostBaseDir    string mountBaseDir   string basePod        *v1.Pod targetBlockDev string hostPathUnset             = v1.HostPathUnset hostPathDirectoryOrCreate = v1.HostPathDirectoryOrCreate hostPathDirectory         = v1.HostPathDirectory hostPathFile              = v1.HostPathFile hostPathSocket            = v1.HostPathSocket hostPathCharDev           = v1.HostPathCharDev hostPathBlockDev          = v1.HostPathBlockDev ) ginkgo.BeforeEach(func() { ns = f.Namespace.Name ginkgo.By("Create a pod for further testing") hostBaseDir = path.Join("/tmp", ns) mountBaseDir = "/mnt/test" basePod = f.PodClient().CreateSync(newHostPathTypeTestPod(map[string]string{}, hostBaseDir, mountBaseDir, &hostPathDirectoryOrCreate)) ginkgo.By(fmt.Sprintf("running on node %s", basePod.Spec.NodeName)) targetBlockDev = path.Join(hostBaseDir, "ablkdev") ginkgo.By("Create a block device for further testing") _, err := utils.PodExec(f, basePod, fmt.Sprintf("mknod %s b 89 1", path.Join(mountBaseDir, "ablkdev"))) framework.ExpectNoError(err) }) ginkgo.It("Should fail on mounting non-existent block device 'does-not-exist-blk-dev' when HostPathType is HostPathBlockDev", func() { blkDevPath := path.Join(hostBaseDir, "does-not-exist-blk-dev") verifyPodHostPathTypeFailure(f, map[string]string{"kubernetes.io/hostname": basePod.Spec.NodeName}, blkDevPath, fmt.Sprintf("%s is not a block device", blkDevPath), &hostPathBlockDev) }) ginkgo.It("Should be able to mount block device 'ablkdev' successfully when HostPathType is HostPathBlockDev", func() { verifyPodHostPathType(f, map[string]string{"kubernetes.io/hostname": basePod.Spec.NodeName}, targetBlockDev, &hostPathBlockDev) }) ginkgo.It("Should be able to mount block device 'ablkdev' successfully when HostPathType is HostPathUnset", func() { verifyPodHostPathType(f, map[string]string{"kubernetes.io/hostname": basePod.Spec.NodeName}, targetBlockDev, &hostPathUnset) }) ginkgo.It("Should fail on mounting block device 'ablkdev' when HostPathType is HostPathDirectory", func() { verifyPodHostPathTypeFailure(f, map[string]string{"kubernetes.io/hostname": basePod.Spec.NodeName}, targetBlockDev, fmt.Sprintf("%s is not a directory", targetBlockDev), &hostPathDirectory) }) ginkgo.It("Should fail on mounting block device 'ablkdev' when HostPathType is HostPathFile", func() { verifyPodHostPathTypeFailure(f, map[string]string{"kubernetes.io/hostname": basePod.Spec.NodeName}, targetBlockDev, fmt.Sprintf("%s is not a file", targetBlockDev), &hostPathFile) }) ginkgo.It("Should fail on mounting block device 'ablkdev' when HostPathType is HostPathSocket", func() { verifyPodHostPathTypeFailure(f, map[string]string{"kubernetes.io/hostname": basePod.Spec.NodeName}, targetBlockDev, fmt.Sprintf("%s is not a socket", targetBlockDev), &hostPathSocket) }) ginkgo.It("Should fail on mounting block device 'ablkdev' when HostPathType is HostPathCharDev", func() { verifyPodHostPathTypeFailure(f, map[string]string{"kubernetes.io/hostname": basePod.Spec.NodeName}, targetBlockDev, fmt.Sprintf("%s is not a character device", targetBlockDev), &hostPathCharDev) }) }) func newHostPathTypeTestPod(nodeSelector map[string]string, hostDir, mountDir string, hostPathType *v1.HostPathType) *v1.Pod { pod := &v1.Pod{ ObjectMeta: metav1.ObjectMeta{ GenerateName: "test-hostpath-type-", }, Spec: v1.PodSpec{ NodeSelector:  nodeSelector, RestartPolicy: v1.RestartPolicyNever, Containers: []v1.Container{ { Name:  "host-path-testing", Image: imageutils.GetE2EImage(imageutils.Agnhost), VolumeMounts: []v1.VolumeMount{ { Name:      "host", MountPath: mountDir, ReadOnly:  false, }, }, }, }, Volumes: []v1.Volume{ { Name: "host", VolumeSource: v1.VolumeSource{ HostPath: &v1.HostPathVolumeSource{ Path: hostDir, Type: hostPathType, }, }, }, }, }, } return pod } func verifyPodHostPathTypeFailure(f *framework.Framework, nodeSelector map[string]string, hostDir, pattern string, hostPathType *v1.HostPathType) { pod := newHostPathTypeTestPod(nodeSelector, hostDir, "/mnt/test", hostPathType) ginkgo.By(fmt.Sprintf("Creating pod %s", pod.Name)) pod, err := f.ClientSet.CoreV1().Pods(f.Namespace.Name).Create(context.TODO(), pod, metav1.CreateOptions{}) framework.ExpectNoError(err) ginkgo.By("Checking for HostPathType error event") eventSelector := fields.Set{ "involvedObject.kind":      "Pod", "involvedObject.name":      pod.Name, "involvedObject.namespace": f.Namespace.Name, "reason":                   events.FailedMountVolume, }.AsSelector().String() msg := "hostPath type check failed" err = e2eevents.WaitTimeoutForEvent(f.ClientSet, f.Namespace.Name, eventSelector, msg, framework.PodStartTimeout) // Events are unreliable, don't depend on the event. It's used only to speed up the test. if err != nil { framework.Logf("Warning: did not get event about FailedMountVolume") } // Check the pod is still not running p, err := f.ClientSet.CoreV1().Pods(f.Namespace.Name).Get(context.TODO(), pod.Name, metav1.GetOptions{}) framework.ExpectNoError(err, "could not re-read the pod after event (or timeout)") framework.ExpectEqual(p.Status.Phase, v1.PodPending, "Pod phase isn't pending") f.ClientSet.CoreV1().Pods(f.Namespace.Name).Delete(context.TODO(), pod.Name, *metav1.NewDeleteOptions(0)) } func verifyPodHostPathType(f *framework.Framework, nodeSelector map[string]string, hostDir string, hostPathType *v1.HostPathType) { newPod, err := f.ClientSet.CoreV1().Pods(f.Namespace.Name).Create(context.TODO(), newHostPathTypeTestPod(nodeSelector, hostDir, "/mnt/test", hostPathType), metav1.CreateOptions{}) framework.ExpectNoError(err) framework.ExpectNoError(e2epod.WaitTimeoutForPodRunningInNamespace(f.ClientSet, newPod.Name, newPod.Namespace, framework.PodStartShortTimeout)) f.ClientSet.CoreV1().Pods(f.Namespace.Name).Delete(context.TODO(), newPod.Name, *metav1.NewDeleteOptions(0)) } </ins>

Related discussion:
text: If this issue is safe to close now please do so with . Send feedback to sig-testing, kubernetes/test-infra and/or . /lifecycle stale
/remove-lifecycle stale
Issues go stale after 90d of inactivity. Mark the issue as fresh with . Stale issues rot after an additional 30d of inactivity and eventually close. If this issue is safe to close now please do so with . Send feedback to sig-testing, kubernetes/test-infra and/or . /lifecycle stale
Stale issues rot after 30d of inactivity. Mark the issue as fresh with . Rotten issues close after an additional 30d of inactivity. If this issue is safe to close now please do so with . Send feedback to sig-testing, kubernetes/test-infra and/or . /lifecycle rotten
/remove-lifecycle rotten
Issues go stale after 90d of inactivity. Mark the issue as fresh with . Stale issues rot after an additional 30d of inactivity and eventually close. If this issue is safe to close now please do so with . Send feedback to sig-testing, kubernetes/test-infra and/or . /lifecycle stale
/remove-lifecycle stale
Issues go stale after 90d of inactivity. Mark the issue as fresh with . Stale issues rot after an additional 30d of inactivity and eventually close. If this issue is safe to close now please do so with . Send feedback to sig-testing, kubernetes/test-infra and/or . /lifecycle stale
/remove-lifecycle stale
Issues go stale after 90d of inactivity. Mark the issue as fresh with . Stale issues rot after an additional 30d of inactivity and eventually close. If this issue is safe to close now please do so with . Send feedback to sig-testing, kubernetes/test-infra and/or . /lifecycle stale
Stale issues rot after 30d of inactivity. Mark the issue as fresh with . Rotten issues close after an additional 30d of inactivity. If this issue is safe to close now please do so with . Send feedback to sig-testing, kubernetes/test-infra and/or . /lifecycle rotten
Rotten issues close after 30d of inactivity. Reopen the issue with . Mark the issue as fresh with .