[ARVADOS] updated: ebb21c7daa50d4101b34647b0e961e4f470a5b0b

Git user git at public.curoverse.com
Fri Jun 3 16:23:08 EDT 2016


Summary of changes:
 services/crunch-run/crunchrun.go      | 271 ++++++++++++++++++++++------------
 services/crunch-run/crunchrun_test.go |  46 ++++--
 services/crunch-run/logging_test.go   |   6 +-
 3 files changed, 214 insertions(+), 109 deletions(-)

       via  ebb21c7daa50d4101b34647b0e961e4f470a5b0b (commit)
       via  a903ecabc5b8d1f33c0f1a9338525c147c75b35a (commit)
       via  26d4cf61346b77ef06556f15b539d532a076d7fb (commit)
       via  6db539443f98f6f56935f55aa611f5ed29622e19 (commit)
       via  e7217857f942d11bdca90c58cf22f8f18c9d29df (commit)
       via  6b2f232c3d73a023d64112c609a28c8ff9cc27de (commit)
      from  e6cb66913899a35cda5a5a8df26869cb29c0ebcd (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.


commit ebb21c7daa50d4101b34647b0e961e4f470a5b0b
Merge: e6cb669 a903eca
Author: Tom Clegg <tom at curoverse.com>
Date:   Fri Jun 3 15:54:05 2016 -0400

    Merge branch '9272-use-container-auth'
    
    closes #9272


commit a903ecabc5b8d1f33c0f1a9338525c147c75b35a
Author: Tom Clegg <tom at curoverse.com>
Date:   Thu May 26 21:25:47 2016 -0400

    9272: Skip slow test when running -short tests.

diff --git a/services/crunch-run/logging_test.go b/services/crunch-run/logging_test.go
index 1c8c635..bb3123a 100644
--- a/services/crunch-run/logging_test.go
+++ b/services/crunch-run/logging_test.go
@@ -4,6 +4,7 @@ import (
 	"fmt"
 	"git.curoverse.com/arvados.git/sdk/go/arvadosclient"
 	. "gopkg.in/check.v1"
+	"testing"
 	"time"
 )
 
@@ -46,13 +47,16 @@ func (s *LoggingTestSuite) TestWriteLogs(c *C) {
 }
 
 func (s *LoggingTestSuite) TestWriteLogsLarge(c *C) {
+	if testing.Short() {
+		return
+	}
 	api := &ArvTestClient{}
 	kc := &KeepTestClient{}
 	cr := NewContainerRunner(api, kc, nil, "zzzzz-zzzzzzzzzzzzzzz")
 	cr.CrunchLog.Timestamper = (&TestTimestamper{}).Timestamp
 	cr.CrunchLog.Immediate = nil
 
-	for i := 0; i < 2000000; i += 1 {
+	for i := 0; i < 2000000; i++ {
 		cr.CrunchLog.Printf("Hello %d", i)
 	}
 	cr.CrunchLog.Print("Goodbye")

commit 26d4cf61346b77ef06556f15b539d532a076d7fb
Author: Tom Clegg <tom at curoverse.com>
Date:   Thu May 26 21:22:11 2016 -0400

    9272: Simplify json decoding with Unmarshal.

diff --git a/services/crunch-run/crunchrun_test.go b/services/crunch-run/crunchrun_test.go
index bbd375e..998c4bc 100644
--- a/services/crunch-run/crunchrun_test.go
+++ b/services/crunch-run/crunchrun_test.go
@@ -505,7 +505,7 @@ func (s *TestSuite) TestUpdateContainerRecordCancelled(c *C) {
 // dress rehearsal of the Run() function, starting from a JSON container record.
 func FullRunHelper(c *C, record string, fn func(t *TestDockerClient)) (api *ArvTestClient, cr *ContainerRunner) {
 	rec := ContainerRecord{}
-	err := json.NewDecoder(strings.NewReader(record)).Decode(&rec)
+	err := json.Unmarshal([]byte(record), &rec)
 	c.Check(err, IsNil)
 
 	docker := NewTestDockerClient()
@@ -644,7 +644,7 @@ func (s *TestSuite) TestCancel(c *C) {
 }`
 
 	rec := ContainerRecord{}
-	err := json.NewDecoder(strings.NewReader(record)).Decode(&rec)
+	err := json.Unmarshal([]byte(record), &rec)
 	c.Check(err, IsNil)
 
 	docker := NewTestDockerClient()
@@ -809,7 +809,7 @@ func (s *TestSuite) TestStdout(c *C) {
 // Used by the TestStdoutWithWrongPath*()
 func StdoutErrorRunHelper(c *C, record string, fn func(t *TestDockerClient)) (api *ArvTestClient, cr *ContainerRunner, err error) {
 	rec := ContainerRecord{}
-	err = json.NewDecoder(strings.NewReader(record)).Decode(&rec)
+	err = json.Unmarshal([]byte(record), &rec)
 	c.Check(err, IsNil)
 
 	docker := NewTestDockerClient()

commit 6db539443f98f6f56935f55aa611f5ed29622e19
Author: Tom Clegg <tom at curoverse.com>
Date:   Thu May 26 21:17:31 2016 -0400

    9272: Fix up state transitions:
    
    * Change state to Running only at the last possible moment before
      starting the container.
    
    * When erroring out before Running, change state back to Queued.
    
    * Do not save log/output/exit code when changing state to Cancelled.
    
    Incidental fixes:
    
    * Clean up error handling in Run()
    
    * Don't create a collection for (or try to attach to the container)
      the second "cleanup activities" log that gets opened after closing
      the real container log.

diff --git a/services/crunch-run/crunchrun.go b/services/crunch-run/crunchrun.go
index f08d82c..f558345 100644
--- a/services/crunch-run/crunchrun.go
+++ b/services/crunch-run/crunchrun.go
@@ -107,6 +107,7 @@ type ContainerRunner struct {
 	Kc        IKeepClient
 	ContainerRecord
 	dockerclient.ContainerConfig
+	dockerclient.HostConfig
 	token       string
 	ContainerID string
 	ExitCode    *int
@@ -459,17 +460,10 @@ func (runner *ContainerRunner) AttachStreams() (err error) {
 	return nil
 }
 
-// StartContainer creates the container and runs it.
-func (runner *ContainerRunner) StartContainer() (err error) {
+// CreateContainer creates the docker container.
+func (runner *ContainerRunner) CreateContainer() error {
 	runner.CrunchLog.Print("Creating Docker container")
 
-	runner.CancelLock.Lock()
-	defer runner.CancelLock.Unlock()
-
-	if runner.Cancelled {
-		return ErrCancelled
-	}
-
 	runner.ContainerConfig.Cmd = runner.ContainerRecord.Command
 	if runner.ContainerRecord.Cwd != "." {
 		runner.ContainerConfig.WorkingDir = runner.ContainerRecord.Cwd
@@ -491,24 +485,26 @@ func (runner *ContainerRunner) StartContainer() (err error) {
 	}
 
 	runner.ContainerConfig.NetworkDisabled = true
+
+	var err error
 	runner.ContainerID, err = runner.Docker.CreateContainer(&runner.ContainerConfig, "", nil)
 	if err != nil {
 		return fmt.Errorf("While creating container: %v", err)
 	}
-	hostConfig := &dockerclient.HostConfig{Binds: runner.Binds,
+
+	runner.HostConfig = dockerclient.HostConfig{Binds: runner.Binds,
 		LogConfig: dockerclient.LogConfig{Type: "none"}}
 
-	err = runner.AttachStreams()
-	if err != nil {
-		return err
-	}
+	return runner.AttachStreams()
+}
 
+// StartContainer starts the docker container created by CreateContainer.
+func (runner *ContainerRunner) StartContainer() error {
 	runner.CrunchLog.Printf("Starting Docker container id '%s'", runner.ContainerID)
-	err = runner.Docker.StartContainer(runner.ContainerID, hostConfig)
+	err := runner.Docker.StartContainer(runner.ContainerID, &runner.HostConfig)
 	if err != nil {
-		return fmt.Errorf("While starting container: %v", err)
+		return fmt.Errorf("could not start container: %v", err)
 	}
-
 	return nil
 }
 
@@ -622,6 +618,15 @@ func (runner *ContainerRunner) CommitLogs() error {
 	runner.CrunchLog = NewThrottledLogger(&ArvLogWriter{runner.ArvClient, runner.ContainerRecord.UUID,
 		"crunch-run", nil})
 
+	if runner.LogsPDH != nil {
+		// If we have already assigned something to LogsPDH,
+		// we must be closing the re-opened log, which won't
+		// end up getting attached to the container record and
+		// therefore doesn't need to be saved as a collection
+		// -- it exists only to send logs to other channels.
+		return nil
+	}
+
 	mt, err := runner.LogCollection.ManifestText()
 	if err != nil {
 		return fmt.Errorf("While creating log manifest: %v", err)
@@ -638,14 +643,18 @@ func (runner *ContainerRunner) CommitLogs() error {
 		return fmt.Errorf("While creating log collection: %v", err)
 	}
 
-	runner.LogsPDH = new(string)
-	*runner.LogsPDH = response.PortableDataHash
+	runner.LogsPDH = &response.PortableDataHash
 
 	return nil
 }
 
 // UpdateContainerRecordRunning updates the container state to "Running"
 func (runner *ContainerRunner) UpdateContainerRecordRunning() error {
+	runner.CancelLock.Lock()
+	defer runner.CancelLock.Unlock()
+	if runner.Cancelled {
+		return ErrCancelled
+	}
 	return runner.ArvClient.Update("containers", runner.ContainerRecord.UUID,
 		arvadosclient.Dict{"container": arvadosclient.Dict{"state": "Running"}}, nil)
 }
@@ -668,23 +677,30 @@ func (runner *ContainerRunner) ContainerToken() (string, error) {
 
 // UpdateContainerRecordComplete updates the container record state on API
 // server to "Complete" or "Cancelled"
-func (runner *ContainerRunner) UpdateContainerRecordComplete() error {
+func (runner *ContainerRunner) UpdateContainerRecordFinal() error {
 	update := arvadosclient.Dict{}
-	if runner.LogsPDH != nil {
-		update["log"] = *runner.LogsPDH
-	}
-	if runner.ExitCode != nil {
-		update["exit_code"] = *runner.ExitCode
-	}
-	if runner.OutputPDH != nil {
-		update["output"] = runner.OutputPDH
-	}
-
 	update["state"] = runner.finalState
-
+	if runner.finalState == "Complete" {
+		if runner.LogsPDH != nil {
+			update["log"] = *runner.LogsPDH
+		}
+		if runner.ExitCode != nil {
+			update["exit_code"] = *runner.ExitCode
+		}
+		if runner.OutputPDH != nil {
+			update["output"] = *runner.OutputPDH
+		}
+	}
 	return runner.ArvClient.Update("containers", runner.ContainerRecord.UUID, arvadosclient.Dict{"container": update}, nil)
 }
 
+// IsCancelled returns the value of Cancelled, with goroutine safety.
+func (runner *ContainerRunner) IsCancelled() bool {
+	runner.CancelLock.Lock()
+	defer runner.CancelLock.Unlock()
+	return runner.Cancelled
+}
+
 // NewArvLogWriter creates an ArvLogWriter
 func (runner *ContainerRunner) NewArvLogWriter(name string) io.WriteCloser {
 	return &ArvLogWriter{runner.ArvClient, runner.ContainerRecord.UUID, name, runner.LogCollection.Open(name + ".txt")}
@@ -701,93 +717,99 @@ func (runner *ContainerRunner) Run() (err error) {
 		runner.CrunchLog.Printf("Executing on host '%s'", hostname)
 	}
 
-	var runerr, waiterr error
+	// Clean up temporary directories _after_ finalizing
+	// everything (if we've made any by then)
+	defer runner.CleanupDirs()
+
+	runner.finalState = "Queued"
 
 	defer func() {
-		if err != nil {
-			runner.CrunchLog.Print(err)
+		// checkErr prints e (unless it's nil) and sets err to
+		// e (unless err is already non-nil). Thus, if err
+		// hasn't already been assigned when Run() returns,
+		// this cleanup func will cause Run() to return the
+		// first non-nil error that is passed to checkErr().
+		checkErr := func(e error) {
+			if e == nil {
+				return
+			}
+			runner.CrunchLog.Print(e)
+			if err == nil {
+				err = e
+			}
 		}
 
-		if runner.Cancelled {
-			runner.finalState = "Cancelled"
-		} else {
-			runner.finalState = "Complete"
-		}
+		// Log the error encountered in Run(), if any
+		checkErr(err)
 
-		// (6) capture output
-		outputerr := runner.CaptureOutput()
-		if outputerr != nil {
-			runner.CrunchLog.Print(outputerr)
+		if runner.finalState == "Queued" {
+			runner.UpdateContainerRecordFinal()
+			return
 		}
 
-		// (7) clean up temporary directories
-		runner.CleanupDirs()
-
-		// (8) write logs
-		logerr := runner.CommitLogs()
-		if logerr != nil {
-			runner.CrunchLog.Print(logerr)
+		if runner.IsCancelled() {
+			runner.finalState = "Cancelled"
+			// but don't return yet -- we still want to
+			// capture partial output and write logs
 		}
 
-		// (9) update container record with results
-		updateerr := runner.UpdateContainerRecordComplete()
-		if updateerr != nil {
-			runner.CrunchLog.Print(updateerr)
-		}
+		checkErr(runner.CaptureOutput())
+		checkErr(runner.CommitLogs())
+		checkErr(runner.UpdateContainerRecordFinal())
 
+		// The real log is already closed, but then we opened
+		// a new one in case we needed to log anything while
+		// finalizing.
 		runner.CrunchLog.Close()
-
-		if err == nil {
-			if runerr != nil {
-				err = runerr
-			} else if waiterr != nil {
-				err = waiterr
-			} else if logerr != nil {
-				err = logerr
-			} else if updateerr != nil {
-				err = updateerr
-			}
-		}
 	}()
 
 	err = runner.ArvClient.Get("containers", runner.ContainerRecord.UUID, nil, &runner.ContainerRecord)
 	if err != nil {
-		return fmt.Errorf("While getting container record: %v", err)
+		err = fmt.Errorf("While getting container record: %v", err)
+		return
 	}
 
-	// (1) setup signal handling
+	// setup signal handling
 	runner.SetupSignals()
 
-	// (2) check for and/or load image
+	// check for and/or load image
 	err = runner.LoadImage()
 	if err != nil {
-		return fmt.Errorf("While loading container image: %v", err)
+		err = fmt.Errorf("While loading container image: %v", err)
+		return
 	}
 
-	// (3) set up FUSE mount and binds
+	// set up FUSE mount and binds
 	err = runner.SetupMounts()
 	if err != nil {
-		return fmt.Errorf("While setting up mounts: %v", err)
+		err = fmt.Errorf("While setting up mounts: %v", err)
+		return
 	}
 
-	// (3) create and start container
-	err = runner.StartContainer()
+	err = runner.CreateContainer()
 	if err != nil {
-		if err == ErrCancelled {
-			err = nil
-		}
 		return
 	}
 
-	// (4) update container record state
+	if runner.IsCancelled() {
+		return
+	}
+
 	err = runner.UpdateContainerRecordRunning()
 	if err != nil {
-		runner.CrunchLog.Print(err)
+		return
 	}
+	runner.finalState = "Cancelled"
 
-	// (5) wait for container to finish
-	waiterr = runner.WaitFinish()
+	err = runner.StartContainer()
+	if err != nil {
+		return
+	}
 
+	err = runner.WaitFinish()
+	if err == nil {
+		runner.finalState = "Complete"
+	}
 	return
 }
 
diff --git a/services/crunch-run/crunchrun_test.go b/services/crunch-run/crunchrun_test.go
index 7194f2f..bbd375e 100644
--- a/services/crunch-run/crunchrun_test.go
+++ b/services/crunch-run/crunchrun_test.go
@@ -423,6 +423,9 @@ func (s *TestSuite) TestRunContainer(c *C) {
 	err := cr.LoadImage()
 	c.Check(err, IsNil)
 
+	err = cr.CreateContainer()
+	c.Check(err, IsNil)
+
 	err = cr.StartContainer()
 	c.Check(err, IsNil)
 
@@ -475,7 +478,7 @@ func (s *TestSuite) TestUpdateContainerRecordComplete(c *C) {
 	*cr.ExitCode = 42
 	cr.finalState = "Complete"
 
-	err := cr.UpdateContainerRecordComplete()
+	err := cr.UpdateContainerRecordFinal()
 	c.Check(err, IsNil)
 
 	c.Check(api.Content[0]["container"].(arvadosclient.Dict)["log"], Equals, *cr.LogsPDH)
@@ -490,7 +493,7 @@ func (s *TestSuite) TestUpdateContainerRecordCancelled(c *C) {
 	cr.Cancelled = true
 	cr.finalState = "Cancelled"
 
-	err := cr.UpdateContainerRecordComplete()
+	err := cr.UpdateContainerRecordFinal()
 	c.Check(err, IsNil)
 
 	c.Check(api.Content[0]["container"].(arvadosclient.Dict)["log"], IsNil)
@@ -668,10 +671,6 @@ func (s *TestSuite) TestCancel(c *C) {
 	err = cr.Run()
 
 	c.Check(err, IsNil)
-
-	c.Check(api.Calls, Equals, 6)
-	c.Check(api.Content[5]["container"].(arvadosclient.Dict)["log"], NotNil)
-
 	if err != nil {
 		for k, v := range api.Logs {
 			c.Log(k)
@@ -679,8 +678,9 @@ func (s *TestSuite) TestCancel(c *C) {
 		}
 	}
 
+	c.Assert(api.Calls, Equals, 6)
+	c.Check(api.Content[5]["container"].(arvadosclient.Dict)["log"], IsNil)
 	c.Check(api.Content[5]["container"].(arvadosclient.Dict)["state"], Equals, "Cancelled")
-
 	c.Check(strings.HasSuffix(api.Logs["stdout"].String(), "foo\n"), Equals, true)
 
 }

commit e7217857f942d11bdca90c58cf22f8f18c9d29df
Author: Tom Clegg <tom at curoverse.com>
Date:   Thu May 26 16:48:08 2016 -0400

    9272: Pass container auth info into container if requested.

diff --git a/services/crunch-run/crunchrun.go b/services/crunch-run/crunchrun.go
index a1b246c..f08d82c 100644
--- a/services/crunch-run/crunchrun.go
+++ b/services/crunch-run/crunchrun.go
@@ -55,19 +55,23 @@ type CollectionRecord struct {
 	PortableDataHash string `json:"portable_data_hash"`
 }
 
+type RuntimeConstraints struct {
+	API *bool
+}
+
 // ContainerRecord is the container record returned by the API server.
 type ContainerRecord struct {
-	UUID               string                 `json:"uuid"`
-	Command            []string               `json:"command"`
-	ContainerImage     string                 `json:"container_image"`
-	Cwd                string                 `json:"cwd"`
-	Environment        map[string]string      `json:"environment"`
-	Mounts             map[string]Mount       `json:"mounts"`
-	OutputPath         string                 `json:"output_path"`
-	Priority           int                    `json:"priority"`
-	RuntimeConstraints map[string]interface{} `json:"runtime_constraints"`
-	State              string                 `json:"state"`
-	Output             string                 `json:"output"`
+	UUID               string             `json:"uuid"`
+	Command            []string           `json:"command"`
+	ContainerImage     string             `json:"container_image"`
+	Cwd                string             `json:"cwd"`
+	Environment        map[string]string  `json:"environment"`
+	Mounts             map[string]Mount   `json:"mounts"`
+	OutputPath         string             `json:"output_path"`
+	Priority           int                `json:"priority"`
+	RuntimeConstraints RuntimeConstraints `json:"runtime_constraints"`
+	State              string             `json:"state"`
+	Output             string             `json:"output"`
 }
 
 // APIClientAuthorization is an arvados#api_client_authorization resource.
@@ -103,6 +107,7 @@ type ContainerRunner struct {
 	Kc        IKeepClient
 	ContainerRecord
 	dockerclient.ContainerConfig
+	token       string
 	ContainerID string
 	ExitCode    *int
 	NewLogWriter
@@ -469,9 +474,22 @@ func (runner *ContainerRunner) StartContainer() (err error) {
 	if runner.ContainerRecord.Cwd != "." {
 		runner.ContainerConfig.WorkingDir = runner.ContainerRecord.Cwd
 	}
+
 	for k, v := range runner.ContainerRecord.Environment {
 		runner.ContainerConfig.Env = append(runner.ContainerConfig.Env, k+"="+v)
 	}
+	if wantAPI := runner.ContainerRecord.RuntimeConstraints.API; wantAPI != nil && *wantAPI {
+		tok, err := runner.ContainerToken()
+		if err != nil {
+			return err
+		}
+		runner.ContainerConfig.Env = append(runner.ContainerConfig.Env,
+			"ARVADOS_API_TOKEN="+tok,
+			"ARVADOS_API_HOST="+os.Getenv("ARVADOS_API_HOST"),
+			"ARVADOS_API_HOST_INSECURE="+os.Getenv("ARVADOS_API_HOST_INSECURE"),
+		)
+	}
+
 	runner.ContainerConfig.NetworkDisabled = true
 	runner.ContainerID, err = runner.Docker.CreateContainer(&runner.ContainerConfig, "", nil)
 	if err != nil {
@@ -635,9 +653,17 @@ func (runner *ContainerRunner) UpdateContainerRecordRunning() error {
 // ContainerToken returns the api_token the container (and any
 // arv-mount processes) are allowed to use.
 func (runner *ContainerRunner) ContainerToken() (string, error) {
+	if runner.token != "" {
+		return runner.token, nil
+	}
+
 	var auth APIClientAuthorization
 	err := runner.ArvClient.Call("GET", "containers", runner.ContainerRecord.UUID, "auth", nil, &auth)
-	return auth.APIToken, err
+	if err != nil {
+		return "", err
+	}
+	runner.token = auth.APIToken
+	return runner.token, nil
 }
 
 // UpdateContainerRecordComplete updates the container record state on API

commit 6b2f232c3d73a023d64112c609a28c8ff9cc27de
Author: Tom Clegg <tom at curoverse.com>
Date:   Thu May 26 15:50:21 2016 -0400

    9272: Get container auth instead of passing the dispatcher token into the container.

diff --git a/services/crunch-run/crunchrun.go b/services/crunch-run/crunchrun.go
index cebebb1..a1b246c 100644
--- a/services/crunch-run/crunchrun.go
+++ b/services/crunch-run/crunchrun.go
@@ -27,6 +27,7 @@ type IArvadosClient interface {
 	Create(resourceType string, parameters arvadosclient.Dict, output interface{}) error
 	Get(resourceType string, uuid string, parameters arvadosclient.Dict, output interface{}) error
 	Update(resourceType string, uuid string, parameters arvadosclient.Dict, output interface{}) (err error)
+	Call(method, resourceType, uuid, action string, parameters arvadosclient.Dict, output interface{}) (err error)
 }
 
 // ErrCancelled is the error returned when the container is cancelled.
@@ -69,10 +70,16 @@ type ContainerRecord struct {
 	Output             string                 `json:"output"`
 }
 
+// APIClientAuthorization is an arvados#api_client_authorization resource.
+type APIClientAuthorization struct {
+	UUID     string `json:"uuid"`
+	APIToken string `json:"api_token"`
+}
+
 // NewLogWriter is a factory function to create a new log writer.
 type NewLogWriter func(name string) io.WriteCloser
 
-type RunArvMount func([]string) (*exec.Cmd, error)
+type RunArvMount func(args []string, tok string) (*exec.Cmd, error)
 
 type MkTempDir func(string, string) (string, error)
 
@@ -189,8 +196,19 @@ func (runner *ContainerRunner) LoadImage() (err error) {
 	return nil
 }
 
-func (runner *ContainerRunner) ArvMountCmd(arvMountCmd []string) (c *exec.Cmd, err error) {
+func (runner *ContainerRunner) ArvMountCmd(arvMountCmd []string, token string) (c *exec.Cmd, err error) {
 	c = exec.Command("arv-mount", arvMountCmd...)
+
+	// Copy our environment, but override ARVADOS_API_TOKEN with
+	// the container auth token.
+	c.Env = nil
+	for _, s := range os.Environ() {
+		if !strings.HasPrefix(s, "ARVADOS_API_TOKEN=") {
+			c.Env = append(c.Env, s)
+		}
+	}
+	c.Env = append(c.Env, "ARVADOS_API_TOKEN="+token)
+
 	nt := NewThrottledLogger(runner.NewLogWriter("arv-mount"))
 	c.Stdout = nt
 	c.Stderr = nt
@@ -328,7 +346,12 @@ func (runner *ContainerRunner) SetupMounts() (err error) {
 	}
 	arvMountCmd = append(arvMountCmd, runner.ArvMountPoint)
 
-	runner.ArvMount, err = runner.RunArvMount(arvMountCmd)
+	token, err := runner.ContainerToken()
+	if err != nil {
+		return fmt.Errorf("could not get container token: %s", err)
+	}
+
+	runner.ArvMount, err = runner.RunArvMount(arvMountCmd, token)
 	if err != nil {
 		return fmt.Errorf("While trying to start arv-mount: %v", err)
 	}
@@ -609,6 +632,14 @@ func (runner *ContainerRunner) UpdateContainerRecordRunning() error {
 		arvadosclient.Dict{"container": arvadosclient.Dict{"state": "Running"}}, nil)
 }
 
+// ContainerToken returns the api_token the container (and any
+// arv-mount processes) are allowed to use.
+func (runner *ContainerRunner) ContainerToken() (string, error) {
+	var auth APIClientAuthorization
+	err := runner.ArvClient.Call("GET", "containers", runner.ContainerRecord.UUID, "auth", nil, &auth)
+	return auth.APIToken, err
+}
+
 // UpdateContainerRecordComplete updates the container record state on API
 // server to "Complete" or "Cancelled"
 func (runner *ContainerRunner) UpdateContainerRecordComplete() error {
diff --git a/services/crunch-run/crunchrun_test.go b/services/crunch-run/crunchrun_test.go
index b064628..7194f2f 100644
--- a/services/crunch-run/crunchrun_test.go
+++ b/services/crunch-run/crunchrun_test.go
@@ -56,6 +56,9 @@ var hwImageId = "9c31ee32b3d15268a0754e8edc74d4f815ee014b693bc5109058e431dd5caea
 var otherManifest = ". 68a84f561b1d1708c6baff5e019a9ab3+46+Ae5d0af96944a3690becb1decdf60cc1c937f556d at 5693216f 0:46:md5sum.txt\n"
 var otherPDH = "a3e8f74c6f101eae01fa08bfb4e49b3a+54"
 
+var fakeAuthUUID = "zzzzz-gj3su-55pqoyepgi2glem"
+var fakeAuthToken = "a3ltuwzqcu2u4sc0q7yhpc2w7s00fdcqecg5d6e0u3pfohmbjt"
+
 type TestDockerClient struct {
 	imageLoaded string
 	logReader   io.ReadCloser
@@ -158,6 +161,19 @@ func (this *ArvTestClient) Create(resourceType string,
 	return nil
 }
 
+func (this *ArvTestClient) Call(method, resourceType, uuid, action string, parameters arvadosclient.Dict, output interface{}) error {
+	switch {
+	case method == "GET" && resourceType == "containers" && action == "auth":
+		return json.Unmarshal([]byte(`{
+			"kind": "arvados#api_client_authorization",
+			"uuid": "`+fakeAuthUUID+`",
+			"api_token": "`+fakeAuthToken+`"
+			}`), output)
+	default:
+		return fmt.Errorf("Not found")
+	}
+}
+
 func (this *ArvTestClient) Get(resourceType string, uuid string, parameters arvadosclient.Dict, output interface{}) error {
 	if resourceType == "collections" {
 		if uuid == hwPDH {
@@ -279,6 +295,10 @@ func (this ArvErrorTestClient) Create(resourceType string,
 	return nil
 }
 
+func (this ArvErrorTestClient) Call(method, resourceType, uuid, action string, parameters arvadosclient.Dict, output interface{}) error {
+	return errors.New("ArvError")
+}
+
 func (this ArvErrorTestClient) Get(resourceType string, uuid string, parameters arvadosclient.Dict, output interface{}) error {
 	return errors.New("ArvError")
 }
@@ -689,11 +709,13 @@ func (s *TestSuite) TestFullRunSetEnv(c *C) {
 }
 
 type ArvMountCmdLine struct {
-	Cmd []string
+	Cmd   []string
+	token string
 }
 
-func (am *ArvMountCmdLine) ArvMountTest(c []string) (*exec.Cmd, error) {
+func (am *ArvMountCmdLine) ArvMountTest(c []string, token string) (*exec.Cmd, error) {
 	am.Cmd = c
+	am.token = token
 	return nil, nil
 }
 

-----------------------------------------------------------------------


hooks/post-receive
-- 




More information about the arvados-commits mailing list