13100: Handle writable collections mounted below output dir.
authorTom Clegg <tclegg@veritasgenetics.com>
Mon, 9 Apr 2018 14:19:59 +0000 (10:19 -0400)
committerTom Clegg <tclegg@veritasgenetics.com>
Mon, 9 Apr 2018 14:19:59 +0000 (10:19 -0400)
Arvados-DCO-1.1-Signed-off-by: Tom Clegg <tclegg@veritasgenetics.com>

services/crunch-run/copier.go
services/crunch-run/copier_test.go

index b6093ce092933fbbf52dd39903540a28515471ba..3ba6eed3f73dae7e44715634cf97a6de904e6d80 100644 (file)
@@ -185,7 +185,7 @@ func (cp *copier) walkMountsBelow(dest, src string) error {
                if !strings.HasPrefix(mnt, src+"/") {
                        continue
                }
-               if mntinfo.Kind == "text" || mntinfo.Kind == "json" {
+               if cp.copyRegularFiles(mntinfo) {
                        // These got copied into the nearest parent
                        // mount as regular files during setup, so
                        // they get copied as regular files when we
@@ -284,15 +284,15 @@ func (cp *copier) walkHostFS(dest, src string, maxSymlinks int, includeMounts bo
                        if _, isSecret := cp.secretMounts[src]; isSecret {
                                continue
                        }
-                       if mntinfo, isMount := cp.mounts[src]; isMount && mntinfo.Kind != "text" && mntinfo.Kind != "json" {
+                       if mntinfo, isMount := cp.mounts[src]; isMount && !cp.copyRegularFiles(mntinfo) {
                                // If a regular file/dir somehow
                                // exists at a path that's also a
                                // mount target, ignore the file --
                                // the mount has already been included
                                // with walkMountsBelow().
                                //
-                               // (...except json/text mounts, which
-                               // are handled as regular files.)
+                               // (...except mount types that are
+                               // handled as regular files.)
                                continue
                        }
                        err = cp.walkHostFS(dest, src, maxSymlinks, false)
@@ -316,6 +316,10 @@ func (cp *copier) walkHostFS(dest, src string, maxSymlinks int, includeMounts bo
        return fmt.Errorf("Unsupported file type (mode %o) in output dir: %q", fi.Mode(), src)
 }
 
+func (cp *copier) copyRegularFiles(m arvados.Mount) bool {
+       return m.Kind == "text" || m.Kind == "json" || (m.Kind == "collection" && m.Writable)
+}
+
 func (cp *copier) getManifest(pdh string) (*manifest.Manifest, error) {
        if mft, ok := cp.manifestCache[pdh]; ok {
                return mft, nil
index 7b13ef905d396409540f167289b333d012c9bd16..41c2acdf90b758b391f6b7aaf9e3954f19b581d5 100644 (file)
@@ -172,14 +172,23 @@ func (s *copierSuite) TestUnsupportedMountKindBelow(c *check.C) {
        c.Check(err, check.NotNil)
 }
 
-func (s *copierSuite) TestUnsupportedWritableMountBelow(c *check.C) {
-       s.cp.mounts["/ctr/outdir/dirk"] = arvados.Mount{
+func (s *copierSuite) TestWritableMountBelow(c *check.C) {
+       s.cp.mounts["/ctr/outdir/mount"] = arvados.Mount{
                Kind:             "collection",
                PortableDataHash: arvadostest.FooPdh,
                Writable:         true,
        }
+       c.Assert(os.MkdirAll(s.cp.hostOutputDir+"/mount", 0755), check.IsNil)
+       s.writeFileInOutputDir(c, "file", "file")
+       s.writeFileInOutputDir(c, "mount/foo", "foo")
+
        err := s.cp.walkMount("", s.cp.ctrOutputDir, 10, true)
-       c.Check(err, check.NotNil)
+       c.Check(err, check.IsNil)
+       c.Check(s.cp.dirs, check.DeepEquals, []string{"/mount"})
+       c.Check(s.cp.files, check.DeepEquals, []filetodo{
+               {src: s.cp.hostOutputDir + "/file", dst: "/file", size: 4},
+               {src: s.cp.hostOutputDir + "/mount/foo", dst: "/mount/foo", size: 3},
+       })
 }
 
 func (s *copierSuite) writeFileInOutputDir(c *check.C, path, data string) {