8015: Expand arv-mount command line tests
[arvados.git] / services / crunch-run / crunchrun_test.go
index eaa16d13bc436a8ef7196be2777f89ac5e27e3a2..72e09b18e8dc17cac3e366a32773a705bea35119 100644 (file)
@@ -13,6 +13,8 @@ import (
        . "gopkg.in/check.v1"
        "io"
        "io/ioutil"
+       "os"
+       "os/exec"
        "strings"
        "syscall"
        "testing"
@@ -139,18 +141,18 @@ func (this *ArvTestClient) Create(resourceType string,
        this.Content = parameters
 
        if resourceType == "logs" {
-               et := parameters["event_type"].(string)
+               et := parameters["log"].(arvadosclient.Dict)["event_type"].(string)
                if this.Logs == nil {
                        this.Logs = make(map[string]*bytes.Buffer)
                }
                if this.Logs[et] == nil {
                        this.Logs[et] = &bytes.Buffer{}
                }
-               this.Logs[et].Write([]byte(parameters["properties"].(map[string]string)["text"]))
+               this.Logs[et].Write([]byte(parameters["log"].(arvadosclient.Dict)["properties"].(map[string]string)["text"]))
        }
 
        if resourceType == "collections" && output != nil {
-               mt := parameters["manifest_text"].(string)
+               mt := parameters["collection"].(arvadosclient.Dict)["manifest_text"].(string)
                outmap := output.(*CollectionRecord)
                outmap.PortableDataHash = fmt.Sprintf("%x+%d", md5.Sum([]byte(mt)), len(mt))
        }
@@ -176,7 +178,7 @@ func (this *ArvTestClient) Update(resourceType string, uuid string, parameters a
 
        this.Content = parameters
        if resourceType == "containers" {
-               if parameters["state"] == "Running" {
+               if parameters["container"].(arvadosclient.Dict)["state"] == "Running" {
                        this.WasSetRunning = true
                }
 
@@ -210,7 +212,7 @@ func (this *KeepTestClient) ManifestFileReader(m manifest.Manifest, filename str
 func (s *TestSuite) TestLoadImage(c *C) {
        kc := &KeepTestClient{}
        docker := NewTestDockerClient()
-       cr := NewContainerRunner(&ArvTestClient{}, kc, docker)
+       cr := NewContainerRunner(&ArvTestClient{}, kc, docker, "zzzzz-zzzzz-zzzzzzzzzzzzzzz")
 
        _, err := cr.Docker.RemoveImage(hwImageId, true)
 
@@ -266,7 +268,7 @@ func (this ArvErrorTestClient) Update(resourceType string, uuid string, paramete
 }
 
 func (this KeepErrorTestClient) PutHB(hash string, buf []byte) (string, int, error) {
-       return "", 0, nil
+       return "", 0, errors.New("KeepError")
 }
 
 func (this KeepErrorTestClient) ManifestFileReader(m manifest.Manifest, filename string) (keepclient.ReadCloserWithLen, error) {
@@ -297,7 +299,7 @@ func (this KeepReadErrorTestClient) ManifestFileReader(m manifest.Manifest, file
 
 func (s *TestSuite) TestLoadImageArvError(c *C) {
        // (1) Arvados error
-       cr := NewContainerRunner(ArvErrorTestClient{}, &KeepTestClient{}, nil)
+       cr := NewContainerRunner(ArvErrorTestClient{}, &KeepTestClient{}, nil, "zzzzz-zzzzz-zzzzzzzzzzzzzzz")
        cr.ContainerRecord.ContainerImage = hwPDH
 
        err := cr.LoadImage()
@@ -307,7 +309,7 @@ func (s *TestSuite) TestLoadImageArvError(c *C) {
 func (s *TestSuite) TestLoadImageKeepError(c *C) {
        // (2) Keep error
        docker := NewTestDockerClient()
-       cr := NewContainerRunner(&ArvTestClient{}, KeepErrorTestClient{}, docker)
+       cr := NewContainerRunner(&ArvTestClient{}, KeepErrorTestClient{}, docker, "zzzzz-zzzzz-zzzzzzzzzzzzzzz")
        cr.ContainerRecord.ContainerImage = hwPDH
 
        err := cr.LoadImage()
@@ -316,7 +318,7 @@ func (s *TestSuite) TestLoadImageKeepError(c *C) {
 
 func (s *TestSuite) TestLoadImageCollectionError(c *C) {
        // (3) Collection doesn't contain image
-       cr := NewContainerRunner(&ArvTestClient{}, KeepErrorTestClient{}, nil)
+       cr := NewContainerRunner(&ArvTestClient{}, KeepErrorTestClient{}, nil, "zzzzz-zzzzz-zzzzzzzzzzzzzzz")
        cr.ContainerRecord.ContainerImage = otherPDH
 
        err := cr.LoadImage()
@@ -326,7 +328,7 @@ func (s *TestSuite) TestLoadImageCollectionError(c *C) {
 func (s *TestSuite) TestLoadImageKeepReadError(c *C) {
        // (4) Collection doesn't contain image
        docker := NewTestDockerClient()
-       cr := NewContainerRunner(&ArvTestClient{}, KeepReadErrorTestClient{}, docker)
+       cr := NewContainerRunner(&ArvTestClient{}, KeepReadErrorTestClient{}, docker, "zzzzz-zzzzz-zzzzzzzzzzzzzzz")
        cr.ContainerRecord.ContainerImage = hwPDH
 
        err := cr.LoadImage()
@@ -364,7 +366,7 @@ func (s *TestSuite) TestRunContainer(c *C) {
                t.stderrWriter.Close()
                t.finish <- dockerclient.WaitResult{}
        }
-       cr := NewContainerRunner(&ArvTestClient{}, &KeepTestClient{}, docker)
+       cr := NewContainerRunner(&ArvTestClient{}, &KeepTestClient{}, docker, "zzzzz-zzzzz-zzzzzzzzzzzzzzz")
 
        var logs TestLogs
        cr.NewLogWriter = logs.NewTestLoggingWriter
@@ -389,8 +391,7 @@ func (s *TestSuite) TestRunContainer(c *C) {
 func (s *TestSuite) TestCommitLogs(c *C) {
        api := &ArvTestClient{}
        kc := &KeepTestClient{}
-       cr := NewContainerRunner(api, kc, nil)
-       cr.ContainerRecord.UUID = "zzzzz-zzzzz-zzzzzzzzzzzzzzz"
+       cr := NewContainerRunner(api, kc, nil, "zzzzz-zzzzz-zzzzzzzzzzzzzzz")
        cr.CrunchLog.Timestamper = (&TestTimestamper{}).Timestamp
 
        cr.CrunchLog.Print("Hello world!")
@@ -400,28 +401,26 @@ func (s *TestSuite) TestCommitLogs(c *C) {
        err := cr.CommitLogs()
        c.Check(err, IsNil)
 
-       c.Check(api.Content["name"], Equals, "logs for zzzzz-zzzzz-zzzzzzzzzzzzzzz")
-       c.Check(api.Content["manifest_text"], Equals, ". 744b2e4553123b02fa7b452ec5c18993+123 0:123:crunch-run.txt\n")
+       c.Check(api.Content["collection"].(arvadosclient.Dict)["name"], Equals, "logs for zzzzz-zzzzz-zzzzzzzzzzzzzzz")
+       c.Check(api.Content["collection"].(arvadosclient.Dict)["manifest_text"], Equals, ". 744b2e4553123b02fa7b452ec5c18993+123 0:123:crunch-run.txt\n")
        c.Check(*cr.LogsPDH, Equals, "63da7bdacf08c40f604daad80c261e9a+60")
 }
 
 func (s *TestSuite) TestUpdateContainerRecordRunning(c *C) {
        api := &ArvTestClient{}
        kc := &KeepTestClient{}
-       cr := NewContainerRunner(api, kc, nil)
-       cr.ContainerRecord.UUID = "zzzzz-zzzzz-zzzzzzzzzzzzzzz"
+       cr := NewContainerRunner(api, kc, nil, "zzzzz-zzzzz-zzzzzzzzzzzzzzz")
 
        err := cr.UpdateContainerRecordRunning()
        c.Check(err, IsNil)
 
-       c.Check(api.Content["state"], Equals, "Running")
+       c.Check(api.Content["container"].(arvadosclient.Dict)["state"], Equals, "Running")
 }
 
 func (s *TestSuite) TestUpdateContainerRecordComplete(c *C) {
        api := &ArvTestClient{}
        kc := &KeepTestClient{}
-       cr := NewContainerRunner(api, kc, nil)
-       cr.ContainerRecord.UUID = "zzzzz-zzzzz-zzzzzzzzzzzzzzz"
+       cr := NewContainerRunner(api, kc, nil, "zzzzz-zzzzz-zzzzzzzzzzzzzzz")
 
        cr.LogsPDH = new(string)
        *cr.LogsPDH = "d3a229d2fe3690c2c3e75a71a153c6a3+60"
@@ -433,25 +432,24 @@ func (s *TestSuite) TestUpdateContainerRecordComplete(c *C) {
        err := cr.UpdateContainerRecordComplete()
        c.Check(err, IsNil)
 
-       c.Check(api.Content["log"], Equals, *cr.LogsPDH)
-       c.Check(api.Content["exit_code"], Equals, *cr.ExitCode)
-       c.Check(api.Content["state"], Equals, "Complete")
+       c.Check(api.Content["container"].(arvadosclient.Dict)["log"], Equals, *cr.LogsPDH)
+       c.Check(api.Content["container"].(arvadosclient.Dict)["exit_code"], Equals, *cr.ExitCode)
+       c.Check(api.Content["container"].(arvadosclient.Dict)["state"], Equals, "Complete")
 }
 
 func (s *TestSuite) TestUpdateContainerRecordCancelled(c *C) {
        api := &ArvTestClient{}
        kc := &KeepTestClient{}
-       cr := NewContainerRunner(api, kc, nil)
-       cr.ContainerRecord.UUID = "zzzzz-zzzzz-zzzzzzzzzzzzzzz"
+       cr := NewContainerRunner(api, kc, nil, "zzzzz-zzzzz-zzzzzzzzzzzzzzz")
        cr.Cancelled = true
        cr.finalState = "Cancelled"
 
        err := cr.UpdateContainerRecordComplete()
        c.Check(err, IsNil)
 
-       c.Check(api.Content["log"], IsNil)
-       c.Check(api.Content["exit_code"], IsNil)
-       c.Check(api.Content["state"], Equals, "Cancelled")
+       c.Check(api.Content["container"].(arvadosclient.Dict)["log"], IsNil)
+       c.Check(api.Content["container"].(arvadosclient.Dict)["exit_code"], IsNil)
+       c.Check(api.Content["container"].(arvadosclient.Dict)["state"], Equals, "Cancelled")
 }
 
 // Used by the TestFullRun*() test below to DRY up boilerplate setup to do full
@@ -466,13 +464,13 @@ func FullRunHelper(c *C, record string, fn func(t *TestDockerClient)) (api *ArvT
        docker.RemoveImage(hwImageId, true)
 
        api = &ArvTestClient{ContainerRecord: rec}
-       cr = NewContainerRunner(api, &KeepTestClient{}, docker)
+       cr = NewContainerRunner(api, &KeepTestClient{}, docker, "zzzzz-zzzzz-zzzzzzzzzzzzzzz")
 
-       err = cr.Run("zzzzz-zzzzz-zzzzzzzzzzzzzzz")
+       err = cr.Run()
        c.Check(err, IsNil)
        c.Check(api.WasSetRunning, Equals, true)
 
-       c.Check(api.Content["log"], NotNil)
+       c.Check(api.Content["container"].(arvadosclient.Dict)["log"], NotNil)
 
        if err != nil {
                for k, v := range api.Logs {
@@ -501,8 +499,8 @@ func (s *TestSuite) TestFullRunHello(c *C) {
                t.finish <- dockerclient.WaitResult{}
        })
 
-       c.Check(api.Content["exit_code"], Equals, 0)
-       c.Check(api.Content["state"], Equals, "Complete")
+       c.Check(api.Content["container"].(arvadosclient.Dict)["exit_code"], Equals, 0)
+       c.Check(api.Content["container"].(arvadosclient.Dict)["state"], Equals, "Complete")
 
        c.Check(strings.HasSuffix(api.Logs["stdout"].String(), "hello world\n"), Equals, true)
 
@@ -526,9 +524,9 @@ func (s *TestSuite) TestFullRunStderr(c *C) {
                t.finish <- dockerclient.WaitResult{ExitCode: 1}
        })
 
-       c.Check(api.Content["log"], NotNil)
-       c.Check(api.Content["exit_code"], Equals, 1)
-       c.Check(api.Content["state"], Equals, "Complete")
+       c.Check(api.Content["container"].(arvadosclient.Dict)["log"], NotNil)
+       c.Check(api.Content["container"].(arvadosclient.Dict)["exit_code"], Equals, 1)
+       c.Check(api.Content["container"].(arvadosclient.Dict)["state"], Equals, "Complete")
 
        c.Check(strings.HasSuffix(api.Logs["stdout"].String(), "hello\n"), Equals, true)
        c.Check(strings.HasSuffix(api.Logs["stderr"].String(), "world\n"), Equals, true)
@@ -551,8 +549,8 @@ func (s *TestSuite) TestFullRunDefaultCwd(c *C) {
                t.finish <- dockerclient.WaitResult{ExitCode: 0}
        })
 
-       c.Check(api.Content["exit_code"], Equals, 0)
-       c.Check(api.Content["state"], Equals, "Complete")
+       c.Check(api.Content["container"].(arvadosclient.Dict)["exit_code"], Equals, 0)
+       c.Check(api.Content["container"].(arvadosclient.Dict)["state"], Equals, "Complete")
 
        c.Check(strings.HasSuffix(api.Logs["stdout"].String(), "/\n"), Equals, true)
 }
@@ -574,8 +572,8 @@ func (s *TestSuite) TestFullRunSetCwd(c *C) {
                t.finish <- dockerclient.WaitResult{ExitCode: 0}
        })
 
-       c.Check(api.Content["exit_code"], Equals, 0)
-       c.Check(api.Content["state"], Equals, "Complete")
+       c.Check(api.Content["container"].(arvadosclient.Dict)["exit_code"], Equals, 0)
+       c.Check(api.Content["container"].(arvadosclient.Dict)["state"], Equals, "Complete")
 
        c.Check(strings.HasSuffix(api.Logs["stdout"].String(), "/bin\n"), Equals, true)
 }
@@ -607,7 +605,7 @@ func (s *TestSuite) TestCancel(c *C) {
        docker.RemoveImage(hwImageId, true)
 
        api := &ArvTestClient{ContainerRecord: rec}
-       cr := NewContainerRunner(api, &KeepTestClient{}, docker)
+       cr := NewContainerRunner(api, &KeepTestClient{}, docker, "zzzzz-zzzzz-zzzzzzzzzzzzzzz")
 
        go func() {
                for cr.ContainerID == "" {
@@ -616,11 +614,11 @@ func (s *TestSuite) TestCancel(c *C) {
                cr.SigChan <- syscall.SIGINT
        }()
 
-       err = cr.Run("zzzzz-zzzzz-zzzzzzzzzzzzzzz")
+       err = cr.Run()
 
        c.Check(err, IsNil)
 
-       c.Check(api.Content["log"], NotNil)
+       c.Check(api.Content["container"].(arvadosclient.Dict)["log"], NotNil)
 
        if err != nil {
                for k, v := range api.Logs {
@@ -629,7 +627,7 @@ func (s *TestSuite) TestCancel(c *C) {
                }
        }
 
-       c.Check(api.Content["state"], Equals, "Cancelled")
+       c.Check(api.Content["container"].(arvadosclient.Dict)["state"], Equals, "Cancelled")
 
        c.Check(strings.HasSuffix(api.Logs["stdout"].String(), "foo\n"), Equals, true)
 
@@ -652,8 +650,65 @@ func (s *TestSuite) TestFullRunSetEnv(c *C) {
                t.finish <- dockerclient.WaitResult{ExitCode: 0}
        })
 
-       c.Check(api.Content["exit_code"], Equals, 0)
-       c.Check(api.Content["state"], Equals, "Complete")
+       c.Check(api.Content["container"].(arvadosclient.Dict)["exit_code"], Equals, 0)
+       c.Check(api.Content["container"].(arvadosclient.Dict)["state"], Equals, "Complete")
 
        c.Check(strings.HasSuffix(api.Logs["stdout"].String(), "bilbo\n"), Equals, true)
 }
+
+type ArvMountCmdLine struct {
+       Cmd []string
+}
+
+func (am *ArvMountCmdLine) ArvMountTest(c []string) (*exec.Cmd, error) {
+       am.Cmd = c
+       return nil, nil
+}
+
+func (s *TestSuite) TestSetupMounts(c *C) {
+       api := &ArvTestClient{}
+       kc := &KeepTestClient{}
+       cr := NewContainerRunner(api, kc, nil, "zzzzz-zzzzz-zzzzzzzzzzzzzzz")
+       am := &ArvMountCmdLine{}
+       cr.RunArvMount = am.ArvMountTest
+
+       i := 0
+       cr.MkTempDir = func(string, string) (string, error) {
+               i += 1
+               return fmt.Sprintf("/tmp/mktmpdir%d", i), nil
+       }
+
+       cr.ContainerRecord.Mounts = make(map[string]Mount)
+       cr.ContainerRecord.Mounts["/tmp"] = Mount{Kind: "tmp"}
+       cr.OutputPath = "/tmp"
+
+       err := cr.SetupMounts()
+       c.Check(err, IsNil)
+       c.Check(am.Cmd, DeepEquals, []string{"--foreground", "--mount-by-pdh", "by_id", "/tmp/mktmpdir1"})
+       c.Check(cr.Binds, DeepEquals, []string{"/tmp/mktmpdir2:/tmp"})
+
+       i = 0
+       cr.ContainerRecord.Mounts = make(map[string]Mount)
+       cr.ContainerRecord.Mounts["/keeptmp"] = Mount{Kind: "collection", Writable: true}
+       cr.OutputPath = "/keeptmp"
+
+       os.MkdirAll("/tmp/mktmpdir1/tmp0", os.ModePerm)
+
+       err = cr.SetupMounts()
+       c.Check(err, IsNil)
+       c.Check(am.Cmd, DeepEquals, []string{"--foreground", "--mount-tmp", "tmp0", "--mount-by-pdh", "by_id", "/tmp/mktmpdir1"})
+       c.Check(cr.Binds, DeepEquals, []string{"/tmp/mktmpdir1/tmp0:/keeptmp"})
+
+       i = 0
+       cr.ContainerRecord.Mounts = make(map[string]Mount)
+       cr.ContainerRecord.Mounts["/keepinp"] = Mount{Kind: "collection", PortableDataHash: "59389a8f9ee9d399be35462a0f92541c+53"}
+       cr.ContainerRecord.Mounts["/keeptmp"] = Mount{Kind: "collection", Writable: true}
+       cr.OutputPath = "/keeptmp"
+
+       os.MkdirAll("/tmp/mktmpdir1/by_id/59389a8f9ee9d399be35462a0f92541c+53", os.ModePerm)
+
+       err = cr.SetupMounts()
+       c.Check(err, IsNil)
+       c.Check(am.Cmd, DeepEquals, []string{"--foreground", "--mount-tmp", "tmp0", "--mount-by-pdh", "by_id", "/tmp/mktmpdir1"})
+       c.Check(cr.Binds, DeepEquals, []string{"/tmp/mktmpdir1/by_id/59389a8f9ee9d399be35462a0f92541c+53:/keepinp:ro", "/tmp/mktmpdir1/tmp0:/keeptmp"})
+}