github.com/cloudfoundry-attic/garden-linux@v0.333.2-candidate/containerizer/system/mount_linux_test.go (about) 1 package system_test 2 3 import ( 4 "fmt" 5 "io" 6 "io/ioutil" 7 "os" 8 "path/filepath" 9 "syscall" 10 11 "github.com/cloudfoundry-incubator/garden-linux/containerizer/system" 12 . "github.com/onsi/ginkgo" 13 . "github.com/onsi/gomega" 14 "github.com/onsi/gomega/gbytes" 15 ) 16 17 var _ = Describe("Mount", func() { 18 var ( 19 dest string 20 src string 21 ) 22 23 BeforeEach(func() { 24 var err error 25 src, err = ioutil.TempDir("", "") 26 Expect(err).ToNot(HaveOccurred()) 27 dest = fmt.Sprintf("/tmp/mount-dest-temp-%d", GinkgoParallelNode()) 28 }) 29 30 AfterEach(func() { 31 Expect(os.RemoveAll(src)).To(Succeed()) 32 Expect(os.RemoveAll(dest)).To(Succeed()) 33 }) 34 35 var testMount = func(privileged bool) { 36 Context("with an invalid mount type", func() { 37 It("returns an informative error", func() { 38 stderr := gbytes.NewBuffer() 39 Expect( 40 runInContainer(GinkgoWriter, io.MultiWriter(stderr, GinkgoWriter), 41 privileged, "fake_mounter", "-type=not-a-mount-type", "-targetPath="+dest, "-flags=0", "cat", "/proc/mounts"), 42 ).To(HaveOccurred()) 43 44 Expect(stderr).To(gbytes.Say("error: system: mount not-a-mount-type on %s: no such device", dest)) 45 }) 46 }) 47 48 It("can mount tmpfs", func() { 49 stdout := gbytes.NewBuffer() 50 Expect( 51 runInContainer(io.MultiWriter(stdout, GinkgoWriter), GinkgoWriter, 52 privileged, "fake_mounter", "-type="+string(system.Tmpfs), "-targetPath="+dest, "-flags=0", "cat", "/proc/mounts"), 53 ).To(Succeed()) 54 55 Expect(stdout).To(gbytes.Say(fmt.Sprintf("tmpfs %s tmpfs", dest))) 56 }) 57 58 Context("when flags are supplied", func() { 59 It("mounts using the flags", func() { 60 stdout := gbytes.NewBuffer() 61 Expect( 62 runInContainer(io.MultiWriter(stdout, GinkgoWriter), GinkgoWriter, 63 privileged, "fake_mounter", "-type="+string(system.Tmpfs), "-targetPath="+dest, fmt.Sprintf("-flags=%d", syscall.MS_NODEV), "cat", "/proc/mounts"), 64 ).To(Succeed()) 65 66 Expect(stdout).To(gbytes.Say(fmt.Sprintf("tmpfs %s tmpfs rw,nodev", dest))) 67 }) 68 }) 69 70 Context("when data is provided", func() { 71 It("mounts using the data", func() { 72 stdout := gbytes.NewBuffer() 73 Expect( 74 runInContainer(io.MultiWriter(stdout, GinkgoWriter), GinkgoWriter, 75 privileged, "fake_mounter", "-type="+string(system.Devpts), "-targetPath="+dest, "-flags=0", "-data=newinstance,ptmxmode=0666", "cat", "/proc/mounts"), 76 ).To(Succeed()) 77 78 Expect(stdout).To(gbytes.Say(fmt.Sprintf("devpts %s devpts rw,relatime,mode=600,ptmxmode=666", dest))) 79 }) 80 }) 81 82 Context("when the destination does not already exist", func() { 83 It("creates the directory before mounting", func() { 84 stdout := gbytes.NewBuffer() 85 Expect( 86 runInContainer(io.MultiWriter(stdout, GinkgoWriter), GinkgoWriter, 87 privileged, "fake_mounter", "-type="+string(system.Tmpfs), "-targetPath="+filepath.Join(dest, "foo"), "-flags=0", "cat", "/proc/mounts"), 88 ).To(Succeed()) 89 90 Expect(stdout).To(gbytes.Say(fmt.Sprintf("tmpfs %s/foo tmpfs", dest))) 91 }) 92 }) 93 94 Context("when the destination cannot be created", func() { 95 BeforeEach(func() { 96 var err error 97 dest, err = ioutil.TempDir("", "") 98 Expect(err).ToNot(HaveOccurred()) 99 }) 100 101 It("returns an informative error", func() { 102 ioutil.WriteFile(filepath.Join(dest, "foo"), []byte("block"), 0700) 103 stderr := gbytes.NewBuffer() 104 Expect( 105 runInContainer(GinkgoWriter, io.MultiWriter(stderr, GinkgoWriter), 106 privileged, "fake_mounter", "-type=tmpfs", "-targetPath="+filepath.Join(dest, "foo"), "-flags=0", "cat", "/proc/mounts"), 107 ).To(HaveOccurred()) 108 109 Expect(stderr).To(gbytes.Say("error: system: create mount point directory %s/foo: ", dest)) 110 }) 111 }) 112 113 Context("when the sourcePath is provided", func() { 114 It("mounts using the sourcePath", func() { 115 stdout := gbytes.NewBuffer() 116 Expect( 117 runInContainer(io.MultiWriter(stdout, GinkgoWriter), GinkgoWriter, 118 privileged, "fake_mounter", "-type=bind", "-sourcePath="+src, "-targetPath="+dest, fmt.Sprintf("-flags=%d", syscall.MS_BIND), "cat", "/proc/mounts"), 119 ).To(Succeed()) 120 121 Expect(stdout).To(gbytes.Say("%s (aufs|ext4|btrfs) rw,relatime", dest)) 122 }) 123 124 Context("when file is mounted", func() { 125 var ( 126 srcFile string 127 dstFile string 128 ) 129 130 BeforeEach(func() { 131 file, err := ioutil.TempFile("", "") 132 Expect(err).ToNot(HaveOccurred()) 133 fmt.Fprintf(file, "MountMe") 134 srcFile = file.Name() 135 dstFile = fmt.Sprintf("/tmp/fake-mount-file-%d", GinkgoParallelNode()) 136 }) 137 138 AfterEach(func() { 139 Expect(os.Remove(srcFile)).To(Succeed()) 140 }) 141 142 It("mounts a file using the sourcePath", func() { 143 stdout := gbytes.NewBuffer() 144 Expect( 145 runInContainer(io.MultiWriter(stdout, GinkgoWriter), GinkgoWriter, 146 privileged, "fake_mounter", "-type=bind", "-sourcePath="+srcFile, "-targetPath="+dstFile, fmt.Sprintf("-flags=%d", syscall.MS_BIND), "cat", "/proc/mounts"), 147 ).To(Succeed()) 148 149 info, err := os.Stat(dstFile) 150 Expect(err).ToNot(HaveOccurred()) 151 Expect(info.IsDir()).ToNot(BeTrue()) 152 Expect(stdout).To(gbytes.Say("%s (aufs|ext4|btrfs) rw,relatime", dstFile)) 153 Expect(os.Remove(dstFile)).To(Succeed()) 154 }) 155 156 Context("when destination file is created in non-existing directory", func() { 157 BeforeEach(func() { 158 dstFile = fmt.Sprintf("/tmp/non-existing-dir-%d/fake-mount-file-%d", GinkgoParallelNode(), GinkgoParallelNode()) 159 }) 160 161 It("mounts a file using the sourcePath", func() { 162 stdout := gbytes.NewBuffer() 163 Expect( 164 runInContainer(io.MultiWriter(stdout, GinkgoWriter), GinkgoWriter, 165 privileged, "fake_mounter", "-type=bind", "-sourcePath="+srcFile, "-targetPath="+dstFile, fmt.Sprintf("-flags=%d", syscall.MS_BIND), "cat", "/proc/mounts"), 166 ).To(Succeed()) 167 168 info, err := os.Stat(dstFile) 169 Expect(err).ToNot(HaveOccurred()) 170 Expect(info.IsDir()).ToNot(BeTrue()) 171 Expect(stdout).To(gbytes.Say("%s (aufs|ext4|btrfs) rw,relatime", dstFile)) 172 Expect(os.Remove(dstFile)).To(Succeed()) 173 }) 174 }) 175 176 Context("when destination file cannot be created", func() { 177 It("returns an informative error", func() { 178 stderr := gbytes.NewBuffer() 179 Expect( 180 runInContainer(GinkgoWriter, io.MultiWriter(GinkgoWriter, stderr), 181 privileged, "fake_mounter", "-type=bind", "-sourcePath="+srcFile, "-targetPath=/tmp", fmt.Sprintf("-flags=%d", syscall.MS_BIND), "cat", "/proc/mounts"), 182 ).To(HaveOccurred()) 183 184 Expect(stderr).To(gbytes.Say("error: system: create mount point file /tmp: ")) 185 }) 186 }) 187 }) 188 }) 189 } 190 191 Context("in an unprivileged container", func() { 192 testMount(false) 193 }) 194 195 Context("in an privileged container", func() { 196 testMount(true) 197 }) 198 })