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  })