github.com/taylorchu/nomad@v0.5.3-rc1.0.20170407200202-db11e7dd7b55/client/driver/raw_exec_test.go (about)

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