github.com/ryanslade/nomad@v0.2.4-0.20160128061903-fc95782f2089/client/driver/raw_exec_test.go (about)

     1  package driver
     2  
     3  import (
     4  	"fmt"
     5  	"io/ioutil"
     6  	"net/http"
     7  	"net/http/httptest"
     8  	"path/filepath"
     9  	"reflect"
    10  	"testing"
    11  	"time"
    12  
    13  	"github.com/hashicorp/nomad/client/config"
    14  	"github.com/hashicorp/nomad/client/driver/env"
    15  	"github.com/hashicorp/nomad/helper/testtask"
    16  	"github.com/hashicorp/nomad/nomad/structs"
    17  	"github.com/hashicorp/nomad/testutil"
    18  )
    19  
    20  func TestRawExecDriver_Fingerprint(t *testing.T) {
    21  	t.Parallel()
    22  	driverCtx, _ := testDriverContexts(&structs.Task{Name: "foo"})
    23  	d := NewRawExecDriver(driverCtx)
    24  	node := &structs.Node{
    25  		Attributes: make(map[string]string),
    26  	}
    27  
    28  	// Disable raw exec.
    29  	cfg := &config.Config{Options: map[string]string{rawExecConfigOption: "false"}}
    30  
    31  	apply, err := d.Fingerprint(cfg, node)
    32  	if err != nil {
    33  		t.Fatalf("err: %v", err)
    34  	}
    35  	if apply {
    36  		t.Fatalf("should not apply")
    37  	}
    38  	if node.Attributes["driver.raw_exec"] != "" {
    39  		t.Fatalf("driver incorrectly enabled")
    40  	}
    41  
    42  	// Enable raw exec.
    43  	cfg.Options[rawExecConfigOption] = "true"
    44  	apply, err = d.Fingerprint(cfg, node)
    45  	if err != nil {
    46  		t.Fatalf("err: %v", err)
    47  	}
    48  	if !apply {
    49  		t.Fatalf("should apply")
    50  	}
    51  	if node.Attributes["driver.raw_exec"] != "1" {
    52  		t.Fatalf("driver not enabled")
    53  	}
    54  }
    55  
    56  func TestRawExecDriver_StartOpen_Wait(t *testing.T) {
    57  	t.Parallel()
    58  	task := &structs.Task{
    59  		Name: "sleep",
    60  		Config: map[string]interface{}{
    61  			"command": testtask.Path(),
    62  			"args":    []string{"sleep", "1s"},
    63  		},
    64  		Resources: basicResources,
    65  	}
    66  	testtask.SetTaskEnv(task)
    67  	driverCtx, execCtx := testDriverContexts(task)
    68  	defer execCtx.AllocDir.Destroy()
    69  	d := NewRawExecDriver(driverCtx)
    70  
    71  	handle, err := d.Start(execCtx, task)
    72  	if err != nil {
    73  		t.Fatalf("err: %v", err)
    74  	}
    75  	if handle == nil {
    76  		t.Fatalf("missing handle")
    77  	}
    78  
    79  	// Attempt to open
    80  	handle2, err := d.Open(execCtx, handle.ID())
    81  	if err != nil {
    82  		t.Fatalf("err: %v", err)
    83  	}
    84  	if handle2 == nil {
    85  		t.Fatalf("missing handle")
    86  	}
    87  
    88  	// Task should terminate quickly
    89  	select {
    90  	case <-handle2.WaitCh():
    91  	case <-time.After(time.Duration(testutil.TestMultiplier()*5) * time.Second):
    92  		t.Fatalf("timeout")
    93  	}
    94  }
    95  
    96  func TestRawExecDriver_Start_Artifact_basic(t *testing.T) {
    97  	t.Parallel()
    98  	path := testtask.Path()
    99  	ts := httptest.NewServer(http.FileServer(http.Dir(filepath.Dir(path))))
   100  	defer ts.Close()
   101  
   102  	file := filepath.Base(path)
   103  	task := &structs.Task{
   104  		Name: "sleep",
   105  		Config: map[string]interface{}{
   106  			"artifact_source": fmt.Sprintf("%s/%s", ts.URL, file),
   107  			"command":         filepath.Join("$NOMAD_TASK_DIR", file),
   108  			"args":            []string{"sleep", "1s"},
   109  		},
   110  		Resources: basicResources,
   111  	}
   112  	testtask.SetTaskEnv(task)
   113  
   114  	driverCtx, execCtx := testDriverContexts(task)
   115  	defer execCtx.AllocDir.Destroy()
   116  	d := NewRawExecDriver(driverCtx)
   117  
   118  	handle, err := d.Start(execCtx, task)
   119  	if err != nil {
   120  		t.Fatalf("err: %v", err)
   121  	}
   122  	if handle == nil {
   123  		t.Fatalf("missing handle")
   124  	}
   125  
   126  	// Attempt to open
   127  	handle2, err := d.Open(execCtx, handle.ID())
   128  	if err != nil {
   129  		t.Fatalf("err: %v", err)
   130  	}
   131  	if handle2 == nil {
   132  		t.Fatalf("missing handle")
   133  	}
   134  
   135  	// Task should terminate quickly
   136  	select {
   137  	case <-handle2.WaitCh():
   138  	case <-time.After(time.Duration(testutil.TestMultiplier()*5) * time.Second):
   139  		t.Fatalf("timeout")
   140  	}
   141  }
   142  
   143  func TestRawExecDriver_Start_Artifact_expanded(t *testing.T) {
   144  	t.Parallel()
   145  	path := testtask.Path()
   146  	ts := httptest.NewServer(http.FileServer(http.Dir(filepath.Dir(path))))
   147  	defer ts.Close()
   148  
   149  	file := filepath.Base(path)
   150  	task := &structs.Task{
   151  		Name: "sleep",
   152  		Config: map[string]interface{}{
   153  			"artifact_source": fmt.Sprintf("%s/%s", ts.URL, file),
   154  			"command":         filepath.Join("$NOMAD_TASK_DIR", file),
   155  			"args":            []string{"sleep", "1s"},
   156  		},
   157  		Resources: basicResources,
   158  	}
   159  	testtask.SetTaskEnv(task)
   160  
   161  	driverCtx, execCtx := testDriverContexts(task)
   162  	defer execCtx.AllocDir.Destroy()
   163  	d := NewRawExecDriver(driverCtx)
   164  
   165  	handle, err := d.Start(execCtx, task)
   166  	if err != nil {
   167  		t.Fatalf("err: %v", err)
   168  	}
   169  	if handle == nil {
   170  		t.Fatalf("missing handle")
   171  	}
   172  
   173  	// Attempt to open
   174  	handle2, err := d.Open(execCtx, handle.ID())
   175  	if err != nil {
   176  		t.Fatalf("err: %v", err)
   177  	}
   178  	if handle2 == nil {
   179  		t.Fatalf("missing handle")
   180  	}
   181  
   182  	// Task should terminate quickly
   183  	select {
   184  	case <-handle2.WaitCh():
   185  	case <-time.After(time.Duration(testutil.TestMultiplier()*5) * time.Second):
   186  		t.Fatalf("timeout")
   187  	}
   188  }
   189  
   190  func TestRawExecDriver_Start_Wait(t *testing.T) {
   191  	t.Parallel()
   192  	task := &structs.Task{
   193  		Name: "sleep",
   194  		Config: map[string]interface{}{
   195  			"command": testtask.Path(),
   196  			"args":    []string{"sleep", "1s"},
   197  		},
   198  		Resources: basicResources,
   199  	}
   200  	testtask.SetTaskEnv(task)
   201  	driverCtx, execCtx := testDriverContexts(task)
   202  	defer execCtx.AllocDir.Destroy()
   203  	d := NewRawExecDriver(driverCtx)
   204  
   205  	handle, err := d.Start(execCtx, task)
   206  	if err != nil {
   207  		t.Fatalf("err: %v", err)
   208  	}
   209  	if handle == nil {
   210  		t.Fatalf("missing handle")
   211  	}
   212  
   213  	// Update should be a no-op
   214  	err = handle.Update(task)
   215  	if err != nil {
   216  		t.Fatalf("err: %v", err)
   217  	}
   218  
   219  	// Task should terminate quickly
   220  	select {
   221  	case res := <-handle.WaitCh():
   222  		if !res.Successful() {
   223  			t.Fatalf("err: %v", res)
   224  		}
   225  	case <-time.After(time.Duration(testutil.TestMultiplier()*5) * time.Second):
   226  		t.Fatalf("timeout")
   227  	}
   228  }
   229  
   230  func TestRawExecDriver_Start_Wait_AllocDir(t *testing.T) {
   231  	t.Parallel()
   232  	exp := []byte{'w', 'i', 'n'}
   233  	file := "output.txt"
   234  	outPath := fmt.Sprintf(`$%s/%s`, env.AllocDir, file)
   235  	task := &structs.Task{
   236  		Name: "sleep",
   237  		Config: map[string]interface{}{
   238  			"command": testtask.Path(),
   239  			"args": []string{
   240  				"sleep", "1s",
   241  				"write", string(exp), outPath,
   242  			},
   243  		},
   244  		Resources: basicResources,
   245  	}
   246  	testtask.SetTaskEnv(task)
   247  
   248  	driverCtx, execCtx := testDriverContexts(task)
   249  	defer execCtx.AllocDir.Destroy()
   250  	d := NewRawExecDriver(driverCtx)
   251  
   252  	handle, err := d.Start(execCtx, task)
   253  	if err != nil {
   254  		t.Fatalf("err: %v", err)
   255  	}
   256  	if handle == nil {
   257  		t.Fatalf("missing handle")
   258  	}
   259  
   260  	// Task should terminate quickly
   261  	select {
   262  	case res := <-handle.WaitCh():
   263  		if !res.Successful() {
   264  			t.Fatalf("err: %v", res)
   265  		}
   266  	case <-time.After(time.Duration(testutil.TestMultiplier()*5) * time.Second):
   267  		t.Fatalf("timeout")
   268  	}
   269  
   270  	// Check that data was written to the shared alloc directory.
   271  	outputFile := filepath.Join(execCtx.AllocDir.SharedDir, file)
   272  	act, err := ioutil.ReadFile(outputFile)
   273  	if err != nil {
   274  		t.Fatalf("Couldn't read expected output: %v", err)
   275  	}
   276  
   277  	if !reflect.DeepEqual(act, exp) {
   278  		t.Fatalf("Command outputted %v; want %v", act, exp)
   279  	}
   280  }
   281  
   282  func TestRawExecDriver_Start_Kill_Wait(t *testing.T) {
   283  	t.Parallel()
   284  	task := &structs.Task{
   285  		Name: "sleep",
   286  		Config: map[string]interface{}{
   287  			"command": testtask.Path(),
   288  			"args":    []string{"sleep", "15s"},
   289  		},
   290  		Resources: basicResources,
   291  	}
   292  	testtask.SetTaskEnv(task)
   293  
   294  	driverCtx, execCtx := testDriverContexts(task)
   295  	defer execCtx.AllocDir.Destroy()
   296  	d := NewRawExecDriver(driverCtx)
   297  
   298  	handle, err := d.Start(execCtx, task)
   299  	if err != nil {
   300  		t.Fatalf("err: %v", err)
   301  	}
   302  	if handle == nil {
   303  		t.Fatalf("missing handle")
   304  	}
   305  
   306  	go func() {
   307  		time.Sleep(1 * time.Second)
   308  		err := handle.Kill()
   309  
   310  		// Can't rely on the ordering between wait and kill on travis...
   311  		if !testutil.IsTravis() && err != nil {
   312  			t.Fatalf("err: %v", err)
   313  		}
   314  	}()
   315  
   316  	// Task should terminate quickly
   317  	select {
   318  	case res := <-handle.WaitCh():
   319  		if res.Successful() {
   320  			t.Fatal("should err")
   321  		}
   322  	case <-time.After(time.Duration(testutil.TestMultiplier()*5) * time.Second):
   323  		t.Fatalf("timeout")
   324  	}
   325  }