type TaskDef struct {
commands []string `json:"commands"`
- env map[string]string `json:"task.env"`
- stdin string `json:"task.stdin"`
- stdout string `json:"task.stdout"`
- vwd map[string]string `json:"task.vwd"`
- successCodes []int `json:"task.successCodes"`
- permanentFailCodes []int `json:"task.permanentFailCodes"`
- temporaryFailCodes []int `json:"task.temporaryFailCodes"`
+ env map[string]string `json:"env"`
+ stdin string `json:"stdin"`
+ stdout string `json:"stdout"`
+ vwd map[string]string `json:"vwd"`
+ successCodes []int `json:"successCodes"`
+ permanentFailCodes []int `json:"permanentFailCodes"`
+ temporaryFailCodes []int `json:"temporaryFailCodes"`
}
type Tasks struct {
progress float32 `json:"sequence"`
}
-func setupDirectories(tmpdir string) (outdir string, err error) {
+func setupDirectories(tmpdir, taskUuid string) (outdir string, err error) {
err = os.Chdir(tmpdir)
if err != nil {
return "", err
return "", err
}
- err = os.Mkdir("outdir", 0700)
+ err = os.Mkdir(taskUuid, 0700)
if err != nil {
return "", err
}
- os.Chdir("outdir")
+ os.Chdir(taskUuid)
if err != nil {
return "", err
}
func setupCommand(cmd *exec.Cmd, taskp TaskDef, keepmount, outdir string) error {
var err error
- //if taskp.vwd != nil {
- // Set up VWD symlinks in outdir
- // TODO
- //}
+ if taskp.vwd != nil {
+ for k, v := range taskp.vwd {
+ os.Symlink(keepmount+"/"+v, outdir+"/"+k)
+ }
+ }
if taskp.stdin != "" {
// Set up stdin redirection
cmd.Stdin, err = os.Open(keepmount + "/" + taskp.stdin)
if err != nil {
- log.Fatal(err)
+ return err
}
}
// Set up stdout redirection
cmd.Stdout, err = os.Create(outdir + "/" + taskp.stdout)
if err != nil {
- log.Fatal(err)
+ return err
}
} else {
cmd.Stdout = os.Stdout
cmd := exec.Command(taskp.commands[0], taskp.commands[1:]...)
var outdir string
- outdir, err = setupDirectories(tmpdir)
+ outdir, err = setupDirectories(tmpdir, taskUuid)
if err != nil {
return TempFail{err}
}
err = cmd.Run()
if err != nil {
- return TempFail{err}
+ // Run() returns ExitError on non-zero exit code, but we handle
+ // that down below. So only return if it's not ExitError.
+ if _, ok := err.(*exec.ExitError); !ok {
+ return TempFail{err}
+ }
}
const success = 1
} else if inCodes(exitCode, taskp.permanentFailCodes) {
status = permfail
} else if inCodes(exitCode, taskp.temporaryFailCodes) {
- os.Exit(TASK_TEMPFAIL)
+ return TempFail{nil}
} else if cmd.ProcessState.Success() {
status = success
} else {
}
func checkOutput(c *C, tmpdir string) {
- file, err := os.Open(tmpdir + "/" + "outdir/output.txt")
+ file, err := os.Open(tmpdir + "/zzzz-ot0gb-111111111111111/output.txt")
c.Assert(err, IsNil)
data := make([]byte, 100)
tmpfile, _ := ioutil.TempFile("", "")
tmpfile.Write([]byte("foo\n"))
- tmpfile.Sync()
- defer tmpfile.Close()
+ tmpfile.Close()
+ defer os.Remove(tmpfile.Name())
tmpdir, _ := ioutil.TempDir("", "")
defer func() {
c.Check(err, IsNil)
}
+
+func (s *TestSuite) TestRunFail(c *C) {
+
+ api := ArvTestClient{}
+
+ tmpdir, _ := ioutil.TempDir("", "")
+ defer func() {
+ os.RemoveAll(tmpdir)
+ }()
+
+ err := runner(api,
+ "zzzz-8i9sb-111111111111111",
+ "zzzz-ot0gb-111111111111111",
+ tmpdir,
+ "",
+ Job{script_parameters: Tasks{[]TaskDef{TaskDef{
+ commands: []string{"/bin/sh", "-c", "exit 1"}}}}},
+ Task{sequence: 0})
+ c.Check(err, FitsTypeOf, PermFail{})
+}
+
+func (s *TestSuite) TestRunSuccessCode(c *C) {
+
+ api := ArvTestClient{}
+
+ tmpdir, _ := ioutil.TempDir("", "")
+ defer func() {
+ os.RemoveAll(tmpdir)
+ }()
+
+ err := runner(api,
+ "zzzz-8i9sb-111111111111111",
+ "zzzz-ot0gb-111111111111111",
+ tmpdir,
+ "",
+ Job{script_parameters: Tasks{[]TaskDef{TaskDef{
+ commands: []string{"/bin/sh", "-c", "exit 1"},
+ successCodes: []int{0, 1}}}}},
+ Task{sequence: 0})
+ c.Check(err, IsNil)
+}
+
+func (s *TestSuite) TestRunFailCode(c *C) {
+ api := ArvTestClient{}
+
+ tmpdir, _ := ioutil.TempDir("", "")
+ defer func() {
+ os.RemoveAll(tmpdir)
+ }()
+
+ err := runner(api,
+ "zzzz-8i9sb-111111111111111",
+ "zzzz-ot0gb-111111111111111",
+ tmpdir,
+ "",
+ Job{script_parameters: Tasks{[]TaskDef{TaskDef{
+ commands: []string{"/bin/sh", "-c", "exit 0"},
+ permanentFailCodes: []int{0, 1}}}}},
+ Task{sequence: 0})
+ c.Check(err, FitsTypeOf, PermFail{})
+}
+
+func (s *TestSuite) TestRunTempFailCode(c *C) {
+ api := ArvTestClient{}
+
+ tmpdir, _ := ioutil.TempDir("", "")
+ defer func() {
+ os.RemoveAll(tmpdir)
+ }()
+
+ err := runner(api,
+ "zzzz-8i9sb-111111111111111",
+ "zzzz-ot0gb-111111111111111",
+ tmpdir,
+ "",
+ Job{script_parameters: Tasks{[]TaskDef{TaskDef{
+ commands: []string{"/bin/sh", "-c", "exit 1"},
+ temporaryFailCodes: []int{1}}}}},
+ Task{sequence: 0})
+ c.Check(err, FitsTypeOf, TempFail{})
+}
+
+func (s *TestSuite) TestVwd(c *C) {
+ api := ArvTestClient{}
+
+ tmpfile, _ := ioutil.TempFile("", "")
+ tmpfile.Write([]byte("foo\n"))
+ tmpfile.Close()
+ defer os.Remove(tmpfile.Name())
+
+ tmpdir, _ := ioutil.TempDir("", "")
+ defer func() {
+ os.RemoveAll(tmpdir)
+ }()
+
+ err := runner(api,
+ "zzzz-8i9sb-111111111111111",
+ "zzzz-ot0gb-111111111111111",
+ tmpdir,
+ "",
+ Job{script_parameters: Tasks{[]TaskDef{TaskDef{
+ commands: []string{"ls", "output.txt"},
+ vwd: map[string]string{
+ "output.txt": tmpfile.Name()}}}}},
+ Task{sequence: 0})
+ c.Check(err, IsNil)
+ checkOutput(c, tmpdir)
+}