open-nomad/client/driver/exec_test.go

297 lines
6.3 KiB
Go
Raw Normal View History

2015-08-20 23:50:28 +00:00
package driver
import (
"fmt"
"io/ioutil"
"path/filepath"
"reflect"
2015-08-20 23:50:28 +00:00
"testing"
2015-08-29 23:20:07 +00:00
"time"
2015-08-20 23:53:43 +00:00
"github.com/hashicorp/nomad/client/config"
2016-01-06 02:02:11 +00:00
"github.com/hashicorp/nomad/client/driver/env"
2015-08-20 23:53:43 +00:00
"github.com/hashicorp/nomad/nomad/structs"
2015-09-25 23:49:14 +00:00
ctestutils "github.com/hashicorp/nomad/client/testutil"
2015-08-20 23:50:28 +00:00
)
func TestExecDriver_Fingerprint(t *testing.T) {
t.Parallel()
2015-09-25 23:49:14 +00:00
ctestutils.ExecCompatible(t)
2016-01-06 02:02:11 +00:00
driverCtx, _ := testDriverContexts(&structs.Task{Name: "foo"})
d := NewExecDriver(driverCtx)
2015-08-20 23:53:43 +00:00
node := &structs.Node{
Attributes: make(map[string]string),
}
apply, err := d.Fingerprint(&config.Config{}, node)
2015-08-20 23:50:28 +00:00
if err != nil {
t.Fatalf("err: %v", err)
}
if !apply {
t.Fatalf("should apply")
}
2015-08-20 23:53:43 +00:00
if node.Attributes["driver.exec"] == "" {
t.Fatalf("missing driver")
}
2015-08-20 23:50:28 +00:00
}
2015-08-29 23:20:07 +00:00
2015-09-25 23:49:14 +00:00
func TestExecDriver_StartOpen_Wait(t *testing.T) {
t.Parallel()
2015-09-25 23:49:14 +00:00
ctestutils.ExecCompatible(t)
2015-08-29 23:20:07 +00:00
task := &structs.Task{
2015-09-25 23:49:14 +00:00
Name: "sleep",
Config: map[string]interface{}{
2015-08-29 23:20:07 +00:00
"command": "/bin/sleep",
"args": []string{"5"},
2015-08-29 23:20:07 +00:00
},
Resources: basicResources,
2015-08-29 23:20:07 +00:00
}
2015-09-25 23:49:14 +00:00
2016-01-06 02:02:11 +00:00
driverCtx, execCtx := testDriverContexts(task)
defer execCtx.AllocDir.Destroy()
2015-09-25 23:49:14 +00:00
d := NewExecDriver(driverCtx)
2016-01-06 02:02:11 +00:00
handle, err := d.Start(execCtx, task)
2015-08-29 23:20:07 +00:00
if err != nil {
t.Fatalf("err: %v", err)
}
if handle == nil {
t.Fatalf("missing handle")
}
// Attempt to open
2016-01-06 02:02:11 +00:00
handle2, err := d.Open(execCtx, handle.ID())
2015-08-29 23:20:07 +00:00
if err != nil {
t.Fatalf("err: %v", err)
}
if handle2 == nil {
t.Fatalf("missing handle")
}
}
func TestExecDriver_Start_Wait(t *testing.T) {
t.Parallel()
2015-09-25 23:49:14 +00:00
ctestutils.ExecCompatible(t)
2015-08-29 23:20:07 +00:00
task := &structs.Task{
2015-09-25 23:49:14 +00:00
Name: "sleep",
Config: map[string]interface{}{
2015-08-29 23:20:07 +00:00
"command": "/bin/sleep",
"args": []string{"2"},
2015-08-29 23:20:07 +00:00
},
Resources: basicResources,
2015-08-29 23:20:07 +00:00
}
2015-09-25 23:49:14 +00:00
2016-01-06 02:02:11 +00:00
driverCtx, execCtx := testDriverContexts(task)
defer execCtx.AllocDir.Destroy()
2015-09-25 23:49:14 +00:00
d := NewExecDriver(driverCtx)
2016-01-06 02:02:11 +00:00
handle, err := d.Start(execCtx, task)
2015-08-29 23:20:07 +00:00
if err != nil {
t.Fatalf("err: %v", err)
}
if handle == nil {
t.Fatalf("missing handle")
}
// Update should be a no-op
err = handle.Update(task)
if err != nil {
t.Fatalf("err: %v", err)
}
// Task should terminate quickly
select {
case res := <-handle.WaitCh():
if !res.Successful() {
t.Fatalf("err: %v", res)
2015-08-29 23:20:07 +00:00
}
2015-10-15 23:59:08 +00:00
case <-time.After(4 * time.Second):
2015-08-29 23:20:07 +00:00
t.Fatalf("timeout")
}
}
func TestExecDriver_Start_Artifact_basic(t *testing.T) {
t.Parallel()
ctestutils.ExecCompatible(t)
file := "hi_linux_amd64"
checksum := "sha256:6f99b4c5184726e601ecb062500aeb9537862434dfe1898dbe5c68d9f50c179c"
task := &structs.Task{
Name: "sleep",
Config: map[string]interface{}{
"artifact_source": fmt.Sprintf("https://dl.dropboxusercontent.com/u/47675/jar_thing/%s?checksum=%s", file, checksum),
"command": filepath.Join("$NOMAD_TASK_DIR", file),
},
Resources: basicResources,
}
2016-01-06 02:02:11 +00:00
driverCtx, execCtx := testDriverContexts(task)
defer execCtx.AllocDir.Destroy()
d := NewExecDriver(driverCtx)
2016-01-06 02:02:11 +00:00
handle, err := d.Start(execCtx, task)
if err != nil {
t.Fatalf("err: %v", err)
}
if handle == nil {
t.Fatalf("missing handle")
}
// Update should be a no-op
err = handle.Update(task)
if err != nil {
t.Fatalf("err: %v", err)
}
// Task should terminate quickly
select {
case res := <-handle.WaitCh():
if !res.Successful() {
t.Fatalf("err: %v", res)
}
case <-time.After(5 * time.Second):
t.Fatalf("timeout")
}
}
func TestExecDriver_Start_Artifact_expanded(t *testing.T) {
t.Parallel()
ctestutils.ExecCompatible(t)
file := "hi_linux_amd64"
task := &structs.Task{
Name: "sleep",
Config: map[string]interface{}{
"artifact_source": fmt.Sprintf("https://dl.dropboxusercontent.com/u/47675/jar_thing/%s", file),
"command": "/bin/bash",
"args": []string{
"-c",
fmt.Sprintf(`/bin/sleep 1 && %s`, filepath.Join("$NOMAD_TASK_DIR", file)),
},
},
Resources: basicResources,
}
2016-01-06 02:02:11 +00:00
driverCtx, execCtx := testDriverContexts(task)
defer execCtx.AllocDir.Destroy()
d := NewExecDriver(driverCtx)
2016-01-06 02:02:11 +00:00
handle, err := d.Start(execCtx, task)
if err != nil {
t.Fatalf("err: %v", err)
}
if handle == nil {
t.Fatalf("missing handle")
}
// Update should be a no-op
err = handle.Update(task)
if err != nil {
t.Fatalf("err: %v", err)
}
// Task should terminate quickly
select {
case res := <-handle.WaitCh():
if !res.Successful() {
t.Fatalf("err: %v", res)
}
case <-time.After(5 * time.Second):
t.Fatalf("timeout")
}
}
func TestExecDriver_Start_Wait_AllocDir(t *testing.T) {
t.Parallel()
ctestutils.ExecCompatible(t)
exp := []byte{'w', 'i', 'n'}
file := "output.txt"
task := &structs.Task{
Name: "sleep",
Config: map[string]interface{}{
"command": "/bin/bash",
"args": []string{
"-c",
2016-01-06 02:02:11 +00:00
fmt.Sprintf(`sleep 1; echo -n %s > $%s/%s`, string(exp), env.AllocDir, file),
},
},
Resources: basicResources,
}
2016-01-06 02:02:11 +00:00
driverCtx, execCtx := testDriverContexts(task)
defer execCtx.AllocDir.Destroy()
d := NewExecDriver(driverCtx)
2016-01-06 02:02:11 +00:00
handle, err := d.Start(execCtx, task)
if err != nil {
t.Fatalf("err: %v", err)
}
if handle == nil {
t.Fatalf("missing handle")
}
// Task should terminate quickly
select {
case res := <-handle.WaitCh():
if !res.Successful() {
t.Fatalf("err: %v", res)
}
case <-time.After(2 * time.Second):
t.Fatalf("timeout")
}
// Check that data was written to the shared alloc directory.
2016-01-06 02:02:11 +00:00
outputFile := filepath.Join(execCtx.AllocDir.SharedDir, file)
act, err := ioutil.ReadFile(outputFile)
if err != nil {
t.Fatalf("Couldn't read expected output: %v", err)
}
if !reflect.DeepEqual(act, exp) {
t.Fatalf("Command outputted %v; want %v", act, exp)
}
}
2015-08-29 23:20:07 +00:00
func TestExecDriver_Start_Kill_Wait(t *testing.T) {
t.Parallel()
2015-09-25 23:49:14 +00:00
ctestutils.ExecCompatible(t)
2015-08-29 23:20:07 +00:00
task := &structs.Task{
2015-09-25 23:49:14 +00:00
Name: "sleep",
Config: map[string]interface{}{
2015-08-29 23:20:07 +00:00
"command": "/bin/sleep",
"args": []string{"1"},
2015-08-29 23:20:07 +00:00
},
Resources: basicResources,
2015-08-29 23:20:07 +00:00
}
2015-09-25 23:49:14 +00:00
2016-01-06 02:02:11 +00:00
driverCtx, execCtx := testDriverContexts(task)
defer execCtx.AllocDir.Destroy()
2015-09-25 23:49:14 +00:00
d := NewExecDriver(driverCtx)
2016-01-06 02:02:11 +00:00
handle, err := d.Start(execCtx, task)
2015-08-29 23:20:07 +00:00
if err != nil {
t.Fatalf("err: %v", err)
}
if handle == nil {
t.Fatalf("missing handle")
}
go func() {
time.Sleep(100 * time.Millisecond)
err := handle.Kill()
if err != nil {
t.Fatalf("err: %v", err)
}
}()
// Task should terminate quickly
select {
case res := <-handle.WaitCh():
if res.Successful() {
2015-09-26 00:55:29 +00:00
t.Fatal("should err")
2015-08-29 23:20:07 +00:00
}
case <-time.After(8 * time.Second):
2015-08-29 23:20:07 +00:00
t.Fatalf("timeout")
}
}