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

     1  package client
     2  
     3  import (
     4  	"fmt"
     5  	"io/ioutil"
     6  	"log"
     7  	"net/http"
     8  	"net/http/httptest"
     9  	"os"
    10  	"path/filepath"
    11  	"reflect"
    12  	"syscall"
    13  	"testing"
    14  	"time"
    15  
    16  	"github.com/golang/snappy"
    17  	"github.com/hashicorp/nomad/client/allocdir"
    18  	"github.com/hashicorp/nomad/client/config"
    19  	cstructs "github.com/hashicorp/nomad/client/structs"
    20  	"github.com/hashicorp/nomad/client/vaultclient"
    21  	"github.com/hashicorp/nomad/nomad/mock"
    22  	"github.com/hashicorp/nomad/nomad/structs"
    23  	"github.com/hashicorp/nomad/testutil"
    24  
    25  	ctestutil "github.com/hashicorp/nomad/client/testutil"
    26  )
    27  
    28  func testLogger() *log.Logger {
    29  	return prefixedTestLogger("")
    30  }
    31  
    32  func prefixedTestLogger(prefix string) *log.Logger {
    33  	return log.New(os.Stderr, prefix, log.LstdFlags)
    34  }
    35  
    36  type MockTaskStateUpdater struct {
    37  	state  string
    38  	failed bool
    39  	events []*structs.TaskEvent
    40  }
    41  
    42  func (m *MockTaskStateUpdater) Update(name, state string, event *structs.TaskEvent) {
    43  	if state != "" {
    44  		m.state = state
    45  	}
    46  	if event != nil {
    47  		if event.FailsTask {
    48  			m.failed = true
    49  		}
    50  		m.events = append(m.events, event)
    51  	}
    52  }
    53  
    54  type taskRunnerTestCtx struct {
    55  	upd      *MockTaskStateUpdater
    56  	tr       *TaskRunner
    57  	allocDir *allocdir.AllocDir
    58  }
    59  
    60  // Cleanup calls Destroy on the task runner and alloc dir
    61  func (ctx *taskRunnerTestCtx) Cleanup() {
    62  	ctx.tr.Destroy(structs.NewTaskEvent(structs.TaskKilled))
    63  	ctx.allocDir.Destroy()
    64  }
    65  
    66  func testTaskRunner(t *testing.T, restarts bool) *taskRunnerTestCtx {
    67  	return testTaskRunnerFromAlloc(t, restarts, mock.Alloc())
    68  }
    69  
    70  // Creates a mock task runner using the first task in the first task group of
    71  // the passed allocation.
    72  //
    73  // Callers should defer Cleanup() to cleanup after completion
    74  func testTaskRunnerFromAlloc(t *testing.T, restarts bool, alloc *structs.Allocation) *taskRunnerTestCtx {
    75  	logger := testLogger()
    76  	conf := config.DefaultConfig()
    77  	conf.StateDir = os.TempDir()
    78  	conf.AllocDir = os.TempDir()
    79  	upd := &MockTaskStateUpdater{}
    80  	task := alloc.Job.TaskGroups[0].Tasks[0]
    81  	// Initialize the port listing. This should be done by the offer process but
    82  	// we have a mock so that doesn't happen.
    83  	task.Resources.Networks[0].ReservedPorts = []structs.Port{{Label: "", Value: 80}}
    84  
    85  	allocDir := allocdir.NewAllocDir(testLogger(), filepath.Join(conf.AllocDir, alloc.ID))
    86  	if err := allocDir.Build(); err != nil {
    87  		t.Fatalf("error building alloc dir: %v", err)
    88  		return nil
    89  	}
    90  
    91  	//HACK to get FSIsolation and chroot without using AllocRunner,
    92  	//     TaskRunner, or Drivers
    93  	fsi := cstructs.FSIsolationImage
    94  	switch task.Driver {
    95  	case "raw_exec":
    96  		fsi = cstructs.FSIsolationNone
    97  	case "exec", "java":
    98  		fsi = cstructs.FSIsolationChroot
    99  	}
   100  	taskDir := allocDir.NewTaskDir(task.Name)
   101  	if err := taskDir.Build(false, config.DefaultChrootEnv, fsi); err != nil {
   102  		t.Fatalf("error building task dir %q: %v", task.Name, err)
   103  		return nil
   104  	}
   105  
   106  	vclient := vaultclient.NewMockVaultClient()
   107  	tr := NewTaskRunner(logger, conf, upd.Update, taskDir, alloc, task, vclient)
   108  	if !restarts {
   109  		tr.restartTracker = noRestartsTracker()
   110  	}
   111  	return &taskRunnerTestCtx{upd, tr, allocDir}
   112  }
   113  
   114  // testWaitForTaskToStart waits for the task to or fails the test
   115  func testWaitForTaskToStart(t *testing.T, ctx *taskRunnerTestCtx) {
   116  	// Wait for the task to start
   117  	testutil.WaitForResult(func() (bool, error) {
   118  		l := len(ctx.upd.events)
   119  		if l < 2 {
   120  			return false, fmt.Errorf("Expect two events; got %v", l)
   121  		}
   122  
   123  		if ctx.upd.events[0].Type != structs.TaskReceived {
   124  			return false, fmt.Errorf("First Event was %v; want %v", ctx.upd.events[0].Type, structs.TaskReceived)
   125  		}
   126  
   127  		if l >= 3 {
   128  			if ctx.upd.events[1].Type != structs.TaskSetup {
   129  				return false, fmt.Errorf("Second Event was %v; want %v", ctx.upd.events[1].Type, structs.TaskSetup)
   130  			}
   131  			if ctx.upd.events[2].Type != structs.TaskStarted {
   132  				return false, fmt.Errorf("Third Event was %v; want %v", ctx.upd.events[2].Type, structs.TaskStarted)
   133  			}
   134  		} else {
   135  			if ctx.upd.events[1].Type != structs.TaskStarted {
   136  				return false, fmt.Errorf("Second Event was %v; want %v", ctx.upd.events[1].Type, structs.TaskStarted)
   137  			}
   138  		}
   139  
   140  		return true, nil
   141  	}, func(err error) {
   142  		t.Fatalf("err: %v", err)
   143  	})
   144  }
   145  
   146  func TestTaskRunner_SimpleRun(t *testing.T) {
   147  	ctestutil.ExecCompatible(t)
   148  	ctx := testTaskRunner(t, false)
   149  	ctx.tr.MarkReceived()
   150  	go ctx.tr.Run()
   151  	defer ctx.Cleanup()
   152  
   153  	select {
   154  	case <-ctx.tr.WaitCh():
   155  	case <-time.After(time.Duration(testutil.TestMultiplier()*15) * time.Second):
   156  		t.Fatalf("timeout")
   157  	}
   158  
   159  	if len(ctx.upd.events) != 4 {
   160  		t.Fatalf("should have 3 ctx.updates: %#v", ctx.upd.events)
   161  	}
   162  
   163  	if ctx.upd.state != structs.TaskStateDead {
   164  		t.Fatalf("TaskState %v; want %v", ctx.upd.state, structs.TaskStateDead)
   165  	}
   166  
   167  	if ctx.upd.events[0].Type != structs.TaskReceived {
   168  		t.Fatalf("First Event was %v; want %v", ctx.upd.events[0].Type, structs.TaskReceived)
   169  	}
   170  
   171  	if ctx.upd.events[1].Type != structs.TaskSetup {
   172  		t.Fatalf("Second Event was %v; want %v", ctx.upd.events[1].Type, structs.TaskSetup)
   173  	}
   174  
   175  	if ctx.upd.events[2].Type != structs.TaskStarted {
   176  		t.Fatalf("Second Event was %v; want %v", ctx.upd.events[2].Type, structs.TaskStarted)
   177  	}
   178  
   179  	if ctx.upd.events[3].Type != structs.TaskTerminated {
   180  		t.Fatalf("Third Event was %v; want %v", ctx.upd.events[3].Type, structs.TaskTerminated)
   181  	}
   182  }
   183  
   184  func TestTaskRunner_Run_RecoverableStartError(t *testing.T) {
   185  	alloc := mock.Alloc()
   186  	task := alloc.Job.TaskGroups[0].Tasks[0]
   187  	task.Driver = "mock_driver"
   188  	task.Config = map[string]interface{}{
   189  		"exit_code":               0,
   190  		"start_error":             "driver failure",
   191  		"start_error_recoverable": true,
   192  	}
   193  
   194  	ctx := testTaskRunnerFromAlloc(t, true, alloc)
   195  	ctx.tr.MarkReceived()
   196  	go ctx.tr.Run()
   197  	defer ctx.Cleanup()
   198  
   199  	testutil.WaitForResult(func() (bool, error) {
   200  		if l := len(ctx.upd.events); l < 4 {
   201  			return false, fmt.Errorf("Expect at least four events; got %v", l)
   202  		}
   203  
   204  		if ctx.upd.events[0].Type != structs.TaskReceived {
   205  			return false, fmt.Errorf("First Event was %v; want %v", ctx.upd.events[0].Type, structs.TaskReceived)
   206  		}
   207  
   208  		if ctx.upd.events[1].Type != structs.TaskSetup {
   209  			return false, fmt.Errorf("Second Event was %v; want %v", ctx.upd.events[1].Type, structs.TaskSetup)
   210  		}
   211  
   212  		if ctx.upd.events[2].Type != structs.TaskDriverFailure {
   213  			return false, fmt.Errorf("Third Event was %v; want %v", ctx.upd.events[2].Type, structs.TaskDriverFailure)
   214  		}
   215  
   216  		if ctx.upd.events[3].Type != structs.TaskRestarting {
   217  			return false, fmt.Errorf("Fourth Event was %v; want %v", ctx.upd.events[3].Type, structs.TaskRestarting)
   218  		}
   219  
   220  		return true, nil
   221  	}, func(err error) {
   222  		t.Fatalf("err: %v", err)
   223  	})
   224  }
   225  
   226  func TestTaskRunner_Destroy(t *testing.T) {
   227  	ctestutil.ExecCompatible(t)
   228  	ctx := testTaskRunner(t, true)
   229  	ctx.tr.MarkReceived()
   230  	//FIXME This didn't used to send a kill status update!!!???
   231  	defer ctx.Cleanup()
   232  
   233  	// Change command to ensure we run for a bit
   234  	ctx.tr.task.Config["command"] = "/bin/sleep"
   235  	ctx.tr.task.Config["args"] = []string{"1000"}
   236  	go ctx.tr.Run()
   237  
   238  	// Wait for the task to start
   239  	testWaitForTaskToStart(t, ctx)
   240  
   241  	// Make sure we are collecting a few stats
   242  	time.Sleep(2 * time.Second)
   243  	stats := ctx.tr.LatestResourceUsage()
   244  	if len(stats.Pids) == 0 || stats.ResourceUsage == nil || stats.ResourceUsage.MemoryStats.RSS == 0 {
   245  		t.Fatalf("expected task runner to have some stats")
   246  	}
   247  
   248  	// Begin the tear down
   249  	ctx.tr.Destroy(structs.NewTaskEvent(structs.TaskKilled))
   250  
   251  	select {
   252  	case <-ctx.tr.WaitCh():
   253  	case <-time.After(time.Duration(testutil.TestMultiplier()*15) * time.Second):
   254  		t.Fatalf("timeout")
   255  	}
   256  
   257  	if len(ctx.upd.events) != 5 {
   258  		t.Fatalf("should have 5 ctx.updates: %#v", ctx.upd.events)
   259  	}
   260  
   261  	if ctx.upd.state != structs.TaskStateDead {
   262  		t.Fatalf("TaskState %v; want %v", ctx.upd.state, structs.TaskStateDead)
   263  	}
   264  
   265  	if ctx.upd.events[3].Type != structs.TaskKilling {
   266  		t.Fatalf("Third Event was %v; want %v", ctx.upd.events[3].Type, structs.TaskKilling)
   267  	}
   268  
   269  	if ctx.upd.events[4].Type != structs.TaskKilled {
   270  		t.Fatalf("Third Event was %v; want %v", ctx.upd.events[4].Type, structs.TaskKilled)
   271  	}
   272  }
   273  
   274  func TestTaskRunner_Update(t *testing.T) {
   275  	ctestutil.ExecCompatible(t)
   276  	ctx := testTaskRunner(t, false)
   277  
   278  	// Change command to ensure we run for a bit
   279  	ctx.tr.task.Config["command"] = "/bin/sleep"
   280  	ctx.tr.task.Config["args"] = []string{"100"}
   281  	go ctx.tr.Run()
   282  	defer ctx.Cleanup()
   283  
   284  	// Update the task definition
   285  	updateAlloc := ctx.tr.alloc.Copy()
   286  
   287  	// Update the restart policy
   288  	newTG := updateAlloc.Job.TaskGroups[0]
   289  	newMode := "foo"
   290  	newTG.RestartPolicy.Mode = newMode
   291  
   292  	newTask := updateAlloc.Job.TaskGroups[0].Tasks[0]
   293  	newTask.Driver = "foobar"
   294  
   295  	// Update the kill timeout
   296  	testutil.WaitForResult(func() (bool, error) {
   297  		if ctx.tr.handle == nil {
   298  			return false, fmt.Errorf("task not started")
   299  		}
   300  		return true, nil
   301  	}, func(err error) {
   302  		t.Fatalf("err: %v", err)
   303  	})
   304  
   305  	oldHandle := ctx.tr.handle.ID()
   306  	newTask.KillTimeout = time.Hour
   307  
   308  	ctx.tr.Update(updateAlloc)
   309  
   310  	// Wait for ctx.update to take place
   311  	testutil.WaitForResult(func() (bool, error) {
   312  		if ctx.tr.task == newTask {
   313  			return false, fmt.Errorf("We copied the pointer! This would be very bad")
   314  		}
   315  		if ctx.tr.task.Driver != newTask.Driver {
   316  			return false, fmt.Errorf("Task not copied")
   317  		}
   318  		if ctx.tr.restartTracker.policy.Mode != newMode {
   319  			return false, fmt.Errorf("restart policy not ctx.updated")
   320  		}
   321  		if ctx.tr.handle.ID() == oldHandle {
   322  			return false, fmt.Errorf("handle not ctx.updated")
   323  		}
   324  		return true, nil
   325  	}, func(err error) {
   326  		t.Fatalf("err: %v", err)
   327  	})
   328  }
   329  
   330  func TestTaskRunner_SaveRestoreState(t *testing.T) {
   331  	alloc := mock.Alloc()
   332  	task := alloc.Job.TaskGroups[0].Tasks[0]
   333  	task.Driver = "mock_driver"
   334  	task.Config = map[string]interface{}{
   335  		"exit_code": "0",
   336  		"run_for":   "5s",
   337  	}
   338  
   339  	// Give it a Vault token
   340  	task.Vault = &structs.Vault{Policies: []string{"default"}}
   341  
   342  	ctx := testTaskRunnerFromAlloc(t, false, alloc)
   343  	ctx.tr.MarkReceived()
   344  	go ctx.tr.Run()
   345  	//FIXME This test didn't used to defer destroy the allocidr ???!!!
   346  	defer ctx.Cleanup()
   347  
   348  	// Wait for the task to be running and then snapshot the state
   349  	testWaitForTaskToStart(t, ctx)
   350  
   351  	if err := ctx.tr.SaveState(); err != nil {
   352  		t.Fatalf("err: %v", err)
   353  	}
   354  
   355  	// Read the token from the file system
   356  	tokenPath := filepath.Join(ctx.tr.taskDir.SecretsDir, vaultTokenFile)
   357  	data, err := ioutil.ReadFile(tokenPath)
   358  	if err != nil {
   359  		t.Fatalf("Failed to read file: %v", err)
   360  	}
   361  	token := string(data)
   362  	if len(token) == 0 {
   363  		t.Fatalf("Token not written to disk")
   364  	}
   365  
   366  	// Create a new task runner
   367  	task2 := &structs.Task{Name: ctx.tr.task.Name, Driver: ctx.tr.task.Driver}
   368  	tr2 := NewTaskRunner(ctx.tr.logger, ctx.tr.config, ctx.upd.Update,
   369  		ctx.tr.taskDir, ctx.tr.alloc, task2, ctx.tr.vaultClient)
   370  	tr2.restartTracker = noRestartsTracker()
   371  	if err := tr2.RestoreState(); err != nil {
   372  		t.Fatalf("err: %v", err)
   373  	}
   374  	go tr2.Run()
   375  	defer tr2.Destroy(structs.NewTaskEvent(structs.TaskKilled))
   376  
   377  	// Destroy and wait
   378  	select {
   379  	case <-tr2.WaitCh():
   380  	case <-time.After(time.Duration(testutil.TestMultiplier()*15) * time.Second):
   381  		t.Fatalf("timeout")
   382  	}
   383  
   384  	// Check that we recovered the token
   385  	if act := tr2.vaultFuture.Get(); act != token {
   386  		t.Fatalf("Vault token not properly recovered")
   387  	}
   388  }
   389  
   390  func TestTaskRunner_Download_List(t *testing.T) {
   391  	ctestutil.ExecCompatible(t)
   392  
   393  	ts := httptest.NewServer(http.FileServer(http.Dir(filepath.Dir("."))))
   394  	defer ts.Close()
   395  
   396  	// Create an allocation that has a task with a list of artifacts.
   397  	alloc := mock.Alloc()
   398  	task := alloc.Job.TaskGroups[0].Tasks[0]
   399  	f1 := "task_runner_test.go"
   400  	f2 := "task_runner.go"
   401  	artifact1 := structs.TaskArtifact{
   402  		GetterSource: fmt.Sprintf("%s/%s", ts.URL, f1),
   403  	}
   404  	artifact2 := structs.TaskArtifact{
   405  		GetterSource: fmt.Sprintf("%s/%s", ts.URL, f2),
   406  	}
   407  	task.Artifacts = []*structs.TaskArtifact{&artifact1, &artifact2}
   408  
   409  	ctx := testTaskRunnerFromAlloc(t, false, alloc)
   410  	ctx.tr.MarkReceived()
   411  	go ctx.tr.Run()
   412  	defer ctx.Cleanup()
   413  
   414  	select {
   415  	case <-ctx.tr.WaitCh():
   416  	case <-time.After(time.Duration(testutil.TestMultiplier()*15) * time.Second):
   417  		t.Fatalf("timeout")
   418  	}
   419  
   420  	if len(ctx.upd.events) != 5 {
   421  		t.Fatalf("should have 5 ctx.updates: %#v", ctx.upd.events)
   422  	}
   423  
   424  	if ctx.upd.state != structs.TaskStateDead {
   425  		t.Fatalf("TaskState %v; want %v", ctx.upd.state, structs.TaskStateDead)
   426  	}
   427  
   428  	if ctx.upd.events[0].Type != structs.TaskReceived {
   429  		t.Fatalf("First Event was %v; want %v", ctx.upd.events[0].Type, structs.TaskReceived)
   430  	}
   431  
   432  	if ctx.upd.events[1].Type != structs.TaskSetup {
   433  		t.Fatalf("Second Event was %v; want %v", ctx.upd.events[1].Type, structs.TaskSetup)
   434  	}
   435  
   436  	if ctx.upd.events[2].Type != structs.TaskDownloadingArtifacts {
   437  		t.Fatalf("Third Event was %v; want %v", ctx.upd.events[2].Type, structs.TaskDownloadingArtifacts)
   438  	}
   439  
   440  	if ctx.upd.events[3].Type != structs.TaskStarted {
   441  		t.Fatalf("Forth Event was %v; want %v", ctx.upd.events[3].Type, structs.TaskStarted)
   442  	}
   443  
   444  	if ctx.upd.events[4].Type != structs.TaskTerminated {
   445  		t.Fatalf("Fifth Event was %v; want %v", ctx.upd.events[4].Type, structs.TaskTerminated)
   446  	}
   447  
   448  	// Check that both files exist.
   449  	if _, err := os.Stat(filepath.Join(ctx.tr.taskDir.Dir, f1)); err != nil {
   450  		t.Fatalf("%v not downloaded", f1)
   451  	}
   452  	if _, err := os.Stat(filepath.Join(ctx.tr.taskDir.Dir, f2)); err != nil {
   453  		t.Fatalf("%v not downloaded", f2)
   454  	}
   455  }
   456  
   457  func TestTaskRunner_Download_Retries(t *testing.T) {
   458  	ctestutil.ExecCompatible(t)
   459  
   460  	// Create an allocation that has a task with bad artifacts.
   461  	alloc := mock.Alloc()
   462  	task := alloc.Job.TaskGroups[0].Tasks[0]
   463  	artifact := structs.TaskArtifact{
   464  		GetterSource: "http://127.1.1.111:12315/foo/bar/baz",
   465  	}
   466  	task.Artifacts = []*structs.TaskArtifact{&artifact}
   467  
   468  	// Make the restart policy try one ctx.upd.te
   469  	alloc.Job.TaskGroups[0].RestartPolicy = &structs.RestartPolicy{
   470  		Attempts: 1,
   471  		Interval: 10 * time.Minute,
   472  		Delay:    1 * time.Second,
   473  		Mode:     structs.RestartPolicyModeFail,
   474  	}
   475  
   476  	ctx := testTaskRunnerFromAlloc(t, true, alloc)
   477  	ctx.tr.MarkReceived()
   478  	go ctx.tr.Run()
   479  	defer ctx.Cleanup()
   480  
   481  	select {
   482  	case <-ctx.tr.WaitCh():
   483  	case <-time.After(time.Duration(testutil.TestMultiplier()*15) * time.Second):
   484  		t.Fatalf("timeout")
   485  	}
   486  
   487  	if len(ctx.upd.events) != 8 {
   488  		t.Fatalf("should have 8 ctx.updates: %#v", ctx.upd.events)
   489  	}
   490  
   491  	if ctx.upd.state != structs.TaskStateDead {
   492  		t.Fatalf("TaskState %v; want %v", ctx.upd.state, structs.TaskStateDead)
   493  	}
   494  
   495  	if ctx.upd.events[0].Type != structs.TaskReceived {
   496  		t.Fatalf("First Event was %v; want %v", ctx.upd.events[0].Type, structs.TaskReceived)
   497  	}
   498  
   499  	if ctx.upd.events[1].Type != structs.TaskSetup {
   500  		t.Fatalf("Second Event was %v; want %v", ctx.upd.events[1].Type, structs.TaskSetup)
   501  	}
   502  
   503  	if ctx.upd.events[2].Type != structs.TaskDownloadingArtifacts {
   504  		t.Fatalf("Third Event was %v; want %v", ctx.upd.events[2].Type, structs.TaskDownloadingArtifacts)
   505  	}
   506  
   507  	if ctx.upd.events[3].Type != structs.TaskArtifactDownloadFailed {
   508  		t.Fatalf("Fourth Event was %v; want %v", ctx.upd.events[3].Type, structs.TaskArtifactDownloadFailed)
   509  	}
   510  
   511  	if ctx.upd.events[4].Type != structs.TaskRestarting {
   512  		t.Fatalf("Fifth Event was %v; want %v", ctx.upd.events[4].Type, structs.TaskRestarting)
   513  	}
   514  
   515  	if ctx.upd.events[5].Type != structs.TaskDownloadingArtifacts {
   516  		t.Fatalf("Sixth Event was %v; want %v", ctx.upd.events[5].Type, structs.TaskDownloadingArtifacts)
   517  	}
   518  
   519  	if ctx.upd.events[6].Type != structs.TaskArtifactDownloadFailed {
   520  		t.Fatalf("Seventh Event was %v; want %v", ctx.upd.events[6].Type, structs.TaskArtifactDownloadFailed)
   521  	}
   522  
   523  	if ctx.upd.events[7].Type != structs.TaskNotRestarting {
   524  		t.Fatalf("Eighth Event was %v; want %v", ctx.upd.events[7].Type, structs.TaskNotRestarting)
   525  	}
   526  }
   527  
   528  func TestTaskRunner_Validate_UserEnforcement(t *testing.T) {
   529  	ctestutil.ExecCompatible(t)
   530  	ctx := testTaskRunner(t, false)
   531  	defer ctx.Cleanup()
   532  
   533  	if err := ctx.tr.setTaskEnv(); err != nil {
   534  		t.Fatalf("bad: %v", err)
   535  	}
   536  
   537  	// Try to run as root with exec.
   538  	ctx.tr.task.Driver = "exec"
   539  	ctx.tr.task.User = "root"
   540  	if err := ctx.tr.validateTask(); err == nil {
   541  		t.Fatalf("expected error running as root with exec")
   542  	}
   543  
   544  	// Try to run a non-blacklisted user with exec.
   545  	ctx.tr.task.Driver = "exec"
   546  	ctx.tr.task.User = "foobar"
   547  	if err := ctx.tr.validateTask(); err != nil {
   548  		t.Fatalf("unexpected error: %v", err)
   549  	}
   550  
   551  	// Try to run as root with docker.
   552  	ctx.tr.task.Driver = "docker"
   553  	ctx.tr.task.User = "root"
   554  	if err := ctx.tr.validateTask(); err != nil {
   555  		t.Fatalf("unexpected error: %v", err)
   556  	}
   557  }
   558  
   559  func TestTaskRunner_RestartTask(t *testing.T) {
   560  	alloc := mock.Alloc()
   561  	task := alloc.Job.TaskGroups[0].Tasks[0]
   562  	task.Driver = "mock_driver"
   563  	task.Config = map[string]interface{}{
   564  		"exit_code": "0",
   565  		"run_for":   "100s",
   566  	}
   567  
   568  	ctx := testTaskRunnerFromAlloc(t, true, alloc)
   569  	ctx.tr.MarkReceived()
   570  	go ctx.tr.Run()
   571  	defer ctx.Cleanup()
   572  
   573  	// Wait for it to start
   574  	go func() {
   575  		testWaitForTaskToStart(t, ctx)
   576  		ctx.tr.Restart("test", "restart")
   577  
   578  		// Wait for it to restart then kill
   579  		go func() {
   580  			// Wait for the task to start again
   581  			testutil.WaitForResult(func() (bool, error) {
   582  				if len(ctx.upd.events) != 8 {
   583  					t.Fatalf("task %q in alloc %q should have 8 ctx.updates: %#v", task.Name, alloc.ID, ctx.upd.events)
   584  				}
   585  
   586  				return true, nil
   587  			}, func(err error) {
   588  				t.Fatalf("err: %v", err)
   589  			})
   590  			ctx.tr.Kill("test", "restart", false)
   591  		}()
   592  	}()
   593  
   594  	select {
   595  	case <-ctx.tr.WaitCh():
   596  	case <-time.After(time.Duration(testutil.TestMultiplier()*15) * time.Second):
   597  		t.Fatalf("timeout")
   598  	}
   599  
   600  	if len(ctx.upd.events) != 10 {
   601  		t.Fatalf("should have 9 ctx.updates: %#v", ctx.upd.events)
   602  	}
   603  
   604  	if ctx.upd.state != structs.TaskStateDead {
   605  		t.Fatalf("TaskState %v; want %v", ctx.upd.state, structs.TaskStateDead)
   606  	}
   607  
   608  	if ctx.upd.events[0].Type != structs.TaskReceived {
   609  		t.Fatalf("First Event was %v; want %v", ctx.upd.events[0].Type, structs.TaskReceived)
   610  	}
   611  
   612  	if ctx.upd.events[1].Type != structs.TaskSetup {
   613  		t.Fatalf("Second Event was %v; want %v", ctx.upd.events[1].Type, structs.TaskSetup)
   614  	}
   615  
   616  	if ctx.upd.events[2].Type != structs.TaskStarted {
   617  		t.Fatalf("Third Event was %v; want %v", ctx.upd.events[2].Type, structs.TaskStarted)
   618  	}
   619  
   620  	if ctx.upd.events[3].Type != structs.TaskRestartSignal {
   621  		t.Fatalf("Fourth Event was %v; want %v", ctx.upd.events[3].Type, structs.TaskRestartSignal)
   622  	}
   623  
   624  	if ctx.upd.events[4].Type != structs.TaskKilling {
   625  		t.Fatalf("Fifth Event was %v; want %v", ctx.upd.events[4].Type, structs.TaskKilling)
   626  	}
   627  
   628  	if ctx.upd.events[5].Type != structs.TaskKilled {
   629  		t.Fatalf("Sixth Event was %v; want %v", ctx.upd.events[5].Type, structs.TaskKilled)
   630  	}
   631  
   632  	if ctx.upd.events[6].Type != structs.TaskRestarting {
   633  		t.Fatalf("Seventh Event was %v; want %v", ctx.upd.events[6].Type, structs.TaskRestarting)
   634  	}
   635  
   636  	if ctx.upd.events[7].Type != structs.TaskStarted {
   637  		t.Fatalf("Eighth Event was %v; want %v", ctx.upd.events[8].Type, structs.TaskStarted)
   638  	}
   639  	if ctx.upd.events[8].Type != structs.TaskKilling {
   640  		t.Fatalf("Nineth  Event was %v; want %v", ctx.upd.events[8].Type, structs.TaskKilling)
   641  	}
   642  
   643  	if ctx.upd.events[9].Type != structs.TaskKilled {
   644  		t.Fatalf("Tenth Event was %v; want %v", ctx.upd.events[9].Type, structs.TaskKilled)
   645  	}
   646  }
   647  
   648  func TestTaskRunner_KillTask(t *testing.T) {
   649  	alloc := mock.Alloc()
   650  	task := alloc.Job.TaskGroups[0].Tasks[0]
   651  	task.Driver = "mock_driver"
   652  	task.Config = map[string]interface{}{
   653  		"exit_code": "0",
   654  		"run_for":   "10s",
   655  	}
   656  
   657  	ctx := testTaskRunnerFromAlloc(t, false, alloc)
   658  	ctx.tr.MarkReceived()
   659  	go ctx.tr.Run()
   660  	defer ctx.Cleanup()
   661  
   662  	go func() {
   663  		testWaitForTaskToStart(t, ctx)
   664  		ctx.tr.Kill("test", "kill", true)
   665  	}()
   666  
   667  	select {
   668  	case <-ctx.tr.WaitCh():
   669  	case <-time.After(time.Duration(testutil.TestMultiplier()*15) * time.Second):
   670  		t.Fatalf("timeout")
   671  	}
   672  
   673  	if len(ctx.upd.events) != 5 {
   674  		t.Fatalf("should have 4 ctx.updates: %#v", ctx.upd.events)
   675  	}
   676  
   677  	if ctx.upd.state != structs.TaskStateDead {
   678  		t.Fatalf("TaskState %v; want %v", ctx.upd.state, structs.TaskStateDead)
   679  	}
   680  
   681  	if !ctx.upd.failed {
   682  		t.Fatalf("TaskState should be failed: %+v", ctx.upd)
   683  	}
   684  
   685  	if ctx.upd.events[0].Type != structs.TaskReceived {
   686  		t.Fatalf("First Event was %v; want %v", ctx.upd.events[0].Type, structs.TaskReceived)
   687  	}
   688  
   689  	if ctx.upd.events[1].Type != structs.TaskSetup {
   690  		t.Fatalf("Second Event was %v; want %v", ctx.upd.events[1].Type, structs.TaskSetup)
   691  	}
   692  
   693  	if ctx.upd.events[2].Type != structs.TaskStarted {
   694  		t.Fatalf("Third Event was %v; want %v", ctx.upd.events[2].Type, structs.TaskStarted)
   695  	}
   696  
   697  	if ctx.upd.events[3].Type != structs.TaskKilling {
   698  		t.Fatalf("Fourth Event was %v; want %v", ctx.upd.events[3].Type, structs.TaskKilling)
   699  	}
   700  
   701  	if ctx.upd.events[4].Type != structs.TaskKilled {
   702  		t.Fatalf("Fifth Event was %v; want %v", ctx.upd.events[4].Type, structs.TaskKilled)
   703  	}
   704  }
   705  
   706  func TestTaskRunner_SignalFailure(t *testing.T) {
   707  	alloc := mock.Alloc()
   708  	task := alloc.Job.TaskGroups[0].Tasks[0]
   709  	task.Driver = "mock_driver"
   710  	task.Config = map[string]interface{}{
   711  		"exit_code":    "0",
   712  		"run_for":      "10s",
   713  		"signal_error": "test forcing failure",
   714  	}
   715  
   716  	ctx := testTaskRunnerFromAlloc(t, false, alloc)
   717  	ctx.tr.MarkReceived()
   718  	go ctx.tr.Run()
   719  	defer ctx.Cleanup()
   720  
   721  	// Wait for the task to start
   722  	testWaitForTaskToStart(t, ctx)
   723  
   724  	if err := ctx.tr.Signal("test", "test", syscall.SIGINT); err == nil {
   725  		t.Fatalf("Didn't receive error")
   726  	}
   727  }
   728  
   729  func TestTaskRunner_BlockForVault(t *testing.T) {
   730  	alloc := mock.Alloc()
   731  	task := alloc.Job.TaskGroups[0].Tasks[0]
   732  	task.Driver = "mock_driver"
   733  	task.Config = map[string]interface{}{
   734  		"exit_code": "0",
   735  		"run_for":   "1s",
   736  	}
   737  	task.Vault = &structs.Vault{Policies: []string{"default"}}
   738  
   739  	ctx := testTaskRunnerFromAlloc(t, false, alloc)
   740  	ctx.tr.MarkReceived()
   741  	defer ctx.Cleanup()
   742  
   743  	// Control when we get a Vault token
   744  	token := "1234"
   745  	waitCh := make(chan struct{})
   746  	handler := func(*structs.Allocation, []string) (map[string]string, error) {
   747  		<-waitCh
   748  		return map[string]string{task.Name: token}, nil
   749  	}
   750  	ctx.tr.vaultClient.(*vaultclient.MockVaultClient).DeriveTokenFn = handler
   751  
   752  	go ctx.tr.Run()
   753  
   754  	select {
   755  	case <-ctx.tr.WaitCh():
   756  		t.Fatalf("premature exit")
   757  	case <-time.After(1 * time.Second):
   758  	}
   759  
   760  	if len(ctx.upd.events) != 2 {
   761  		t.Fatalf("should have 2 ctx.updates: %#v", ctx.upd.events)
   762  	}
   763  
   764  	if ctx.upd.state != structs.TaskStatePending {
   765  		t.Fatalf("TaskState %v; want %v", ctx.upd.state, structs.TaskStatePending)
   766  	}
   767  
   768  	if ctx.upd.events[0].Type != structs.TaskReceived {
   769  		t.Fatalf("First Event was %v; want %v", ctx.upd.events[0].Type, structs.TaskReceived)
   770  	}
   771  
   772  	if ctx.upd.events[1].Type != structs.TaskSetup {
   773  		t.Fatalf("Second Event was %v; want %v", ctx.upd.events[1].Type, structs.TaskSetup)
   774  	}
   775  
   776  	// Unblock
   777  	close(waitCh)
   778  
   779  	select {
   780  	case <-ctx.tr.WaitCh():
   781  	case <-time.After(time.Duration(testutil.TestMultiplier()*15) * time.Second):
   782  		t.Fatalf("timeout")
   783  	}
   784  
   785  	if len(ctx.upd.events) != 4 {
   786  		t.Fatalf("should have 4 ctx.updates: %#v", ctx.upd.events)
   787  	}
   788  
   789  	if ctx.upd.state != structs.TaskStateDead {
   790  		t.Fatalf("TaskState %v; want %v", ctx.upd.state, structs.TaskStateDead)
   791  	}
   792  
   793  	if ctx.upd.events[0].Type != structs.TaskReceived {
   794  		t.Fatalf("First Event was %v; want %v", ctx.upd.events[0].Type, structs.TaskReceived)
   795  	}
   796  
   797  	if ctx.upd.events[1].Type != structs.TaskSetup {
   798  		t.Fatalf("Second Event was %v; want %v", ctx.upd.events[1].Type, structs.TaskSetup)
   799  	}
   800  
   801  	if ctx.upd.events[2].Type != structs.TaskStarted {
   802  		t.Fatalf("Third Event was %v; want %v", ctx.upd.events[2].Type, structs.TaskStarted)
   803  	}
   804  
   805  	if ctx.upd.events[3].Type != structs.TaskTerminated {
   806  		t.Fatalf("Fourth Event was %v; want %v", ctx.upd.events[3].Type, structs.TaskTerminated)
   807  	}
   808  
   809  	// Check that the token is on disk
   810  	tokenPath := filepath.Join(ctx.tr.taskDir.SecretsDir, vaultTokenFile)
   811  	data, err := ioutil.ReadFile(tokenPath)
   812  	if err != nil {
   813  		t.Fatalf("Failed to read file: %v", err)
   814  	}
   815  
   816  	if act := string(data); act != token {
   817  		t.Fatalf("Token didn't get written to disk properly, got %q; want %q", act, token)
   818  	}
   819  
   820  	// Check the token was revoked
   821  	m := ctx.tr.vaultClient.(*vaultclient.MockVaultClient)
   822  	testutil.WaitForResult(func() (bool, error) {
   823  		if len(m.StoppedTokens) != 1 {
   824  			return false, fmt.Errorf("Expected a stopped token: %v", m.StoppedTokens)
   825  		}
   826  
   827  		if a := m.StoppedTokens[0]; a != token {
   828  			return false, fmt.Errorf("got stopped token %q; want %q", a, token)
   829  		}
   830  		return true, nil
   831  	}, func(err error) {
   832  		t.Fatalf("err: %v", err)
   833  	})
   834  }
   835  
   836  func TestTaskRunner_DeriveToken_Retry(t *testing.T) {
   837  	alloc := mock.Alloc()
   838  	task := alloc.Job.TaskGroups[0].Tasks[0]
   839  	task.Driver = "mock_driver"
   840  	task.Config = map[string]interface{}{
   841  		"exit_code": "0",
   842  		"run_for":   "1s",
   843  	}
   844  	task.Vault = &structs.Vault{Policies: []string{"default"}}
   845  
   846  	ctx := testTaskRunnerFromAlloc(t, false, alloc)
   847  	ctx.tr.MarkReceived()
   848  	defer ctx.Cleanup()
   849  
   850  	// Control when we get a Vault token
   851  	token := "1234"
   852  	count := 0
   853  	handler := func(*structs.Allocation, []string) (map[string]string, error) {
   854  		if count > 0 {
   855  			return map[string]string{task.Name: token}, nil
   856  		}
   857  
   858  		count++
   859  		return nil, structs.NewRecoverableError(fmt.Errorf("Want a retry"), true)
   860  	}
   861  	ctx.tr.vaultClient.(*vaultclient.MockVaultClient).DeriveTokenFn = handler
   862  	go ctx.tr.Run()
   863  
   864  	select {
   865  	case <-ctx.tr.WaitCh():
   866  	case <-time.After(time.Duration(testutil.TestMultiplier()*15) * time.Second):
   867  		t.Fatalf("timeout")
   868  	}
   869  
   870  	if len(ctx.upd.events) != 4 {
   871  		t.Fatalf("should have 4 ctx.updates: %#v", ctx.upd.events)
   872  	}
   873  
   874  	if ctx.upd.state != structs.TaskStateDead {
   875  		t.Fatalf("TaskState %v; want %v", ctx.upd.state, structs.TaskStateDead)
   876  	}
   877  
   878  	if ctx.upd.events[0].Type != structs.TaskReceived {
   879  		t.Fatalf("First Event was %v; want %v", ctx.upd.events[0].Type, structs.TaskReceived)
   880  	}
   881  
   882  	if ctx.upd.events[1].Type != structs.TaskSetup {
   883  		t.Fatalf("Second Event was %v; want %v", ctx.upd.events[1].Type, structs.TaskSetup)
   884  	}
   885  
   886  	if ctx.upd.events[2].Type != structs.TaskStarted {
   887  		t.Fatalf("Third Event was %v; want %v", ctx.upd.events[2].Type, structs.TaskStarted)
   888  	}
   889  
   890  	if ctx.upd.events[3].Type != structs.TaskTerminated {
   891  		t.Fatalf("Fourth Event was %v; want %v", ctx.upd.events[3].Type, structs.TaskTerminated)
   892  	}
   893  
   894  	// Check that the token is on disk
   895  	tokenPath := filepath.Join(ctx.tr.taskDir.SecretsDir, vaultTokenFile)
   896  	data, err := ioutil.ReadFile(tokenPath)
   897  	if err != nil {
   898  		t.Fatalf("Failed to read file: %v", err)
   899  	}
   900  
   901  	if act := string(data); act != token {
   902  		t.Fatalf("Token didn't get written to disk properly, got %q; want %q", act, token)
   903  	}
   904  
   905  	// Check the token was revoked
   906  	m := ctx.tr.vaultClient.(*vaultclient.MockVaultClient)
   907  	testutil.WaitForResult(func() (bool, error) {
   908  		if len(m.StoppedTokens) != 1 {
   909  			return false, fmt.Errorf("Expected a stopped token: %v", m.StoppedTokens)
   910  		}
   911  
   912  		if a := m.StoppedTokens[0]; a != token {
   913  			return false, fmt.Errorf("got stopped token %q; want %q", a, token)
   914  		}
   915  		return true, nil
   916  	}, func(err error) {
   917  		t.Fatalf("err: %v", err)
   918  	})
   919  }
   920  
   921  func TestTaskRunner_DeriveToken_Unrecoverable(t *testing.T) {
   922  	alloc := mock.Alloc()
   923  	task := alloc.Job.TaskGroups[0].Tasks[0]
   924  	task.Driver = "mock_driver"
   925  	task.Config = map[string]interface{}{
   926  		"exit_code": "0",
   927  		"run_for":   "10s",
   928  	}
   929  	task.Vault = &structs.Vault{
   930  		Policies:   []string{"default"},
   931  		ChangeMode: structs.VaultChangeModeRestart,
   932  	}
   933  
   934  	ctx := testTaskRunnerFromAlloc(t, false, alloc)
   935  	ctx.tr.MarkReceived()
   936  	defer ctx.Cleanup()
   937  
   938  	// Error the token derivation
   939  	vc := ctx.tr.vaultClient.(*vaultclient.MockVaultClient)
   940  	vc.SetDeriveTokenError(alloc.ID, []string{task.Name}, fmt.Errorf("Non recoverable"))
   941  	go ctx.tr.Run()
   942  
   943  	// Wait for the task to start
   944  	testutil.WaitForResult(func() (bool, error) {
   945  		if l := len(ctx.upd.events); l != 3 {
   946  			return false, fmt.Errorf("Expect 3 events; got %v", l)
   947  		}
   948  
   949  		if ctx.upd.events[0].Type != structs.TaskReceived {
   950  			return false, fmt.Errorf("First Event was %v; want %v", ctx.upd.events[0].Type, structs.TaskReceived)
   951  		}
   952  
   953  		if ctx.upd.events[1].Type != structs.TaskSetup {
   954  			return false, fmt.Errorf("Second Event was %v; want %v", ctx.upd.events[1].Type, structs.TaskSetup)
   955  		}
   956  
   957  		if ctx.upd.events[2].Type != structs.TaskKilling {
   958  			return false, fmt.Errorf("Third Event was %v; want %v", ctx.upd.events[2].Type, structs.TaskKilling)
   959  		}
   960  
   961  		return true, nil
   962  	}, func(err error) {
   963  		t.Fatalf("err: %v", err)
   964  	})
   965  }
   966  
   967  func TestTaskRunner_Template_Block(t *testing.T) {
   968  	testRetryRate = 2 * time.Second
   969  	defer func() {
   970  		testRetryRate = 0
   971  	}()
   972  	alloc := mock.Alloc()
   973  	task := alloc.Job.TaskGroups[0].Tasks[0]
   974  	task.Driver = "mock_driver"
   975  	task.Config = map[string]interface{}{
   976  		"exit_code": "0",
   977  		"run_for":   "1s",
   978  	}
   979  	task.Templates = []*structs.Template{
   980  		{
   981  			EmbeddedTmpl: "{{key \"foo\"}}",
   982  			DestPath:     "local/test",
   983  			ChangeMode:   structs.TemplateChangeModeNoop,
   984  		},
   985  	}
   986  
   987  	ctx := testTaskRunnerFromAlloc(t, false, alloc)
   988  	ctx.tr.MarkReceived()
   989  	go ctx.tr.Run()
   990  	defer ctx.Cleanup()
   991  
   992  	select {
   993  	case <-ctx.tr.WaitCh():
   994  		t.Fatalf("premature exit")
   995  	case <-time.After(1 * time.Second):
   996  	}
   997  
   998  	if len(ctx.upd.events) != 2 {
   999  		t.Fatalf("should have 2 ctx.updates: %#v", ctx.upd.events)
  1000  	}
  1001  
  1002  	if ctx.upd.state != structs.TaskStatePending {
  1003  		t.Fatalf("TaskState %v; want %v", ctx.upd.state, structs.TaskStatePending)
  1004  	}
  1005  
  1006  	if ctx.upd.events[0].Type != structs.TaskReceived {
  1007  		t.Fatalf("First Event was %v; want %v", ctx.upd.events[0].Type, structs.TaskReceived)
  1008  	}
  1009  
  1010  	if ctx.upd.events[1].Type != structs.TaskSetup {
  1011  		t.Fatalf("Second Event was %v; want %v", ctx.upd.events[1].Type, structs.TaskSetup)
  1012  	}
  1013  
  1014  	// Unblock
  1015  	ctx.tr.UnblockStart("test")
  1016  
  1017  	select {
  1018  	case <-ctx.tr.WaitCh():
  1019  	case <-time.After(time.Duration(testutil.TestMultiplier()*15) * time.Second):
  1020  		t.Fatalf("timeout")
  1021  	}
  1022  
  1023  	if len(ctx.upd.events) != 4 {
  1024  		t.Fatalf("should have 4 ctx.updates: %#v", ctx.upd.events)
  1025  	}
  1026  
  1027  	if ctx.upd.state != structs.TaskStateDead {
  1028  		t.Fatalf("TaskState %v; want %v", ctx.upd.state, structs.TaskStateDead)
  1029  	}
  1030  
  1031  	if ctx.upd.events[0].Type != structs.TaskReceived {
  1032  		t.Fatalf("First Event was %v; want %v", ctx.upd.events[0].Type, structs.TaskReceived)
  1033  	}
  1034  
  1035  	if ctx.upd.events[1].Type != structs.TaskSetup {
  1036  		t.Fatalf("Second Event was %v; want %v", ctx.upd.events[1].Type, structs.TaskSetup)
  1037  	}
  1038  
  1039  	if ctx.upd.events[2].Type != structs.TaskStarted {
  1040  		t.Fatalf("Third Event was %v; want %v", ctx.upd.events[2].Type, structs.TaskStarted)
  1041  	}
  1042  
  1043  	if ctx.upd.events[3].Type != structs.TaskTerminated {
  1044  		t.Fatalf("Fourth Event was %v; want %v", ctx.upd.events[3].Type, structs.TaskTerminated)
  1045  	}
  1046  }
  1047  
  1048  func TestTaskRunner_Template_Artifact(t *testing.T) {
  1049  	dir, err := os.Getwd()
  1050  	if err != nil {
  1051  		t.Fatalf("bad: %v", err)
  1052  	}
  1053  
  1054  	ts := httptest.NewServer(http.FileServer(http.Dir(filepath.Join(dir, ".."))))
  1055  	defer ts.Close()
  1056  
  1057  	alloc := mock.Alloc()
  1058  	task := alloc.Job.TaskGroups[0].Tasks[0]
  1059  	task.Driver = "mock_driver"
  1060  	task.Config = map[string]interface{}{
  1061  		"exit_code": "0",
  1062  		"run_for":   "1s",
  1063  	}
  1064  	// Create an allocation that has a task that renders a template from an
  1065  	// artifact
  1066  	f1 := "CHANGELOG.md"
  1067  	artifact := structs.TaskArtifact{
  1068  		GetterSource: fmt.Sprintf("%s/%s", ts.URL, f1),
  1069  	}
  1070  	task.Artifacts = []*structs.TaskArtifact{&artifact}
  1071  	task.Templates = []*structs.Template{
  1072  		{
  1073  			SourcePath: "CHANGELOG.md",
  1074  			DestPath:   "local/test",
  1075  			ChangeMode: structs.TemplateChangeModeNoop,
  1076  		},
  1077  	}
  1078  
  1079  	ctx := testTaskRunnerFromAlloc(t, false, alloc)
  1080  	ctx.tr.MarkReceived()
  1081  	defer ctx.Cleanup()
  1082  	go ctx.tr.Run()
  1083  
  1084  	select {
  1085  	case <-ctx.tr.WaitCh():
  1086  	case <-time.After(time.Duration(testutil.TestMultiplier()*15) * time.Second):
  1087  		t.Fatalf("timeout")
  1088  	}
  1089  
  1090  	if len(ctx.upd.events) != 5 {
  1091  		t.Fatalf("should have 5 ctx.updates: %#v", ctx.upd.events)
  1092  	}
  1093  
  1094  	if ctx.upd.state != structs.TaskStateDead {
  1095  		t.Fatalf("TaskState %v; want %v", ctx.upd.state, structs.TaskStateDead)
  1096  	}
  1097  
  1098  	if ctx.upd.events[0].Type != structs.TaskReceived {
  1099  		t.Fatalf("First Event was %v; want %v", ctx.upd.events[0].Type, structs.TaskReceived)
  1100  	}
  1101  
  1102  	if ctx.upd.events[1].Type != structs.TaskSetup {
  1103  		t.Fatalf("Second Event was %v; want %v", ctx.upd.events[1].Type, structs.TaskSetup)
  1104  	}
  1105  
  1106  	if ctx.upd.events[2].Type != structs.TaskDownloadingArtifacts {
  1107  		t.Fatalf("Third Event was %v; want %v", ctx.upd.events[2].Type, structs.TaskDownloadingArtifacts)
  1108  	}
  1109  
  1110  	if ctx.upd.events[3].Type != structs.TaskStarted {
  1111  		t.Fatalf("Fourth Event was %v; want %v", ctx.upd.events[3].Type, structs.TaskStarted)
  1112  	}
  1113  
  1114  	if ctx.upd.events[4].Type != structs.TaskTerminated {
  1115  		t.Fatalf("Fifth Event was %v; want %v", ctx.upd.events[4].Type, structs.TaskTerminated)
  1116  	}
  1117  
  1118  	// Check that both files exist.
  1119  	if _, err := os.Stat(filepath.Join(ctx.tr.taskDir.Dir, f1)); err != nil {
  1120  		t.Fatalf("%v not downloaded", f1)
  1121  	}
  1122  	if _, err := os.Stat(filepath.Join(ctx.tr.taskDir.LocalDir, "test")); err != nil {
  1123  		t.Fatalf("template not rendered")
  1124  	}
  1125  }
  1126  
  1127  func TestTaskRunner_Template_NewVaultToken(t *testing.T) {
  1128  	alloc := mock.Alloc()
  1129  	task := alloc.Job.TaskGroups[0].Tasks[0]
  1130  	task.Driver = "mock_driver"
  1131  	task.Config = map[string]interface{}{
  1132  		"exit_code": "0",
  1133  		"run_for":   "1s",
  1134  	}
  1135  	task.Templates = []*structs.Template{
  1136  		{
  1137  			EmbeddedTmpl: "{{key \"foo\"}}",
  1138  			DestPath:     "local/test",
  1139  			ChangeMode:   structs.TemplateChangeModeNoop,
  1140  		},
  1141  	}
  1142  	task.Vault = &structs.Vault{Policies: []string{"default"}}
  1143  
  1144  	ctx := testTaskRunnerFromAlloc(t, false, alloc)
  1145  	ctx.tr.MarkReceived()
  1146  	defer ctx.Cleanup()
  1147  	go ctx.tr.Run()
  1148  
  1149  	// Wait for a Vault token
  1150  	var token string
  1151  	testutil.WaitForResult(func() (bool, error) {
  1152  		if token = ctx.tr.vaultFuture.Get(); token == "" {
  1153  			return false, fmt.Errorf("No Vault token")
  1154  		}
  1155  
  1156  		return true, nil
  1157  	}, func(err error) {
  1158  		t.Fatalf("err: %v", err)
  1159  	})
  1160  
  1161  	// Error the token renewal
  1162  	vc := ctx.tr.vaultClient.(*vaultclient.MockVaultClient)
  1163  	renewalCh, ok := vc.RenewTokens[token]
  1164  	if !ok {
  1165  		t.Fatalf("no renewal channel")
  1166  	}
  1167  
  1168  	originalManager := ctx.tr.templateManager
  1169  
  1170  	renewalCh <- fmt.Errorf("Test killing")
  1171  	close(renewalCh)
  1172  
  1173  	// Wait for a new Vault token
  1174  	var token2 string
  1175  	testutil.WaitForResult(func() (bool, error) {
  1176  		if token2 = ctx.tr.vaultFuture.Get(); token2 == "" || token2 == token {
  1177  			return false, fmt.Errorf("No new Vault token")
  1178  		}
  1179  
  1180  		if originalManager == ctx.tr.templateManager {
  1181  			return false, fmt.Errorf("Template manager not ctx.updated")
  1182  		}
  1183  
  1184  		return true, nil
  1185  	}, func(err error) {
  1186  		t.Fatalf("err: %v", err)
  1187  	})
  1188  
  1189  	// Check the token was revoked
  1190  	m := ctx.tr.vaultClient.(*vaultclient.MockVaultClient)
  1191  	testutil.WaitForResult(func() (bool, error) {
  1192  		if len(m.StoppedTokens) != 1 {
  1193  			return false, fmt.Errorf("Expected a stopped token: %v", m.StoppedTokens)
  1194  		}
  1195  
  1196  		if a := m.StoppedTokens[0]; a != token {
  1197  			return false, fmt.Errorf("got stopped token %q; want %q", a, token)
  1198  		}
  1199  		return true, nil
  1200  	}, func(err error) {
  1201  		t.Fatalf("err: %v", err)
  1202  	})
  1203  }
  1204  
  1205  func TestTaskRunner_VaultManager_Restart(t *testing.T) {
  1206  	alloc := mock.Alloc()
  1207  	task := alloc.Job.TaskGroups[0].Tasks[0]
  1208  	task.Driver = "mock_driver"
  1209  	task.Config = map[string]interface{}{
  1210  		"exit_code": "0",
  1211  		"run_for":   "10s",
  1212  	}
  1213  	task.Vault = &structs.Vault{
  1214  		Policies:   []string{"default"},
  1215  		ChangeMode: structs.VaultChangeModeRestart,
  1216  	}
  1217  
  1218  	ctx := testTaskRunnerFromAlloc(t, false, alloc)
  1219  	ctx.tr.MarkReceived()
  1220  	defer ctx.Cleanup()
  1221  	go ctx.tr.Run()
  1222  
  1223  	// Wait for the task to start
  1224  	testWaitForTaskToStart(t, ctx)
  1225  
  1226  	// Error the token renewal
  1227  	vc := ctx.tr.vaultClient.(*vaultclient.MockVaultClient)
  1228  	renewalCh, ok := vc.RenewTokens[ctx.tr.vaultFuture.Get()]
  1229  	if !ok {
  1230  		t.Fatalf("no renewal channel")
  1231  	}
  1232  
  1233  	renewalCh <- fmt.Errorf("Test killing")
  1234  	close(renewalCh)
  1235  
  1236  	// Ensure a restart
  1237  	testutil.WaitForResult(func() (bool, error) {
  1238  		if l := len(ctx.upd.events); l != 8 {
  1239  			return false, fmt.Errorf("Expect eight events; got %#v", ctx.upd.events)
  1240  		}
  1241  
  1242  		if ctx.upd.events[0].Type != structs.TaskReceived {
  1243  			return false, fmt.Errorf("First Event was %v; want %v", ctx.upd.events[0].Type, structs.TaskReceived)
  1244  		}
  1245  
  1246  		if ctx.upd.events[1].Type != structs.TaskSetup {
  1247  			return false, fmt.Errorf("Second Event was %v; want %v", ctx.upd.events[1].Type, structs.TaskStarted)
  1248  		}
  1249  
  1250  		if ctx.upd.events[2].Type != structs.TaskStarted {
  1251  			return false, fmt.Errorf("Third Event was %v; want %v", ctx.upd.events[2].Type, structs.TaskStarted)
  1252  		}
  1253  
  1254  		if ctx.upd.events[3].Type != structs.TaskRestartSignal {
  1255  			return false, fmt.Errorf("Fourth Event was %v; want %v", ctx.upd.events[3].Type, structs.TaskRestartSignal)
  1256  		}
  1257  
  1258  		if ctx.upd.events[4].Type != structs.TaskKilling {
  1259  			return false, fmt.Errorf("Fifth Event was %v; want %v", ctx.upd.events[4].Type, structs.TaskKilling)
  1260  		}
  1261  
  1262  		if ctx.upd.events[5].Type != structs.TaskKilled {
  1263  			return false, fmt.Errorf("Sixth Event was %v; want %v", ctx.upd.events[5].Type, structs.TaskKilled)
  1264  		}
  1265  
  1266  		if ctx.upd.events[6].Type != structs.TaskRestarting {
  1267  			return false, fmt.Errorf("Seventh Event was %v; want %v", ctx.upd.events[6].Type, structs.TaskRestarting)
  1268  		}
  1269  
  1270  		if ctx.upd.events[7].Type != structs.TaskStarted {
  1271  			return false, fmt.Errorf("Eight Event was %v; want %v", ctx.upd.events[7].Type, structs.TaskStarted)
  1272  		}
  1273  
  1274  		return true, nil
  1275  	}, func(err error) {
  1276  		t.Fatalf("err: %v", err)
  1277  	})
  1278  }
  1279  
  1280  func TestTaskRunner_VaultManager_Signal(t *testing.T) {
  1281  	alloc := mock.Alloc()
  1282  	task := alloc.Job.TaskGroups[0].Tasks[0]
  1283  	task.Driver = "mock_driver"
  1284  	task.Config = map[string]interface{}{
  1285  		"exit_code": "0",
  1286  		"run_for":   "10s",
  1287  	}
  1288  	task.Vault = &structs.Vault{
  1289  		Policies:     []string{"default"},
  1290  		ChangeMode:   structs.VaultChangeModeSignal,
  1291  		ChangeSignal: "SIGUSR1",
  1292  	}
  1293  
  1294  	ctx := testTaskRunnerFromAlloc(t, false, alloc)
  1295  	ctx.tr.MarkReceived()
  1296  	go ctx.tr.Run()
  1297  	defer ctx.Cleanup()
  1298  
  1299  	// Wait for the task to start
  1300  	testWaitForTaskToStart(t, ctx)
  1301  
  1302  	// Error the token renewal
  1303  	vc := ctx.tr.vaultClient.(*vaultclient.MockVaultClient)
  1304  	renewalCh, ok := vc.RenewTokens[ctx.tr.vaultFuture.Get()]
  1305  	if !ok {
  1306  		t.Fatalf("no renewal channel")
  1307  	}
  1308  
  1309  	renewalCh <- fmt.Errorf("Test killing")
  1310  	close(renewalCh)
  1311  
  1312  	// Ensure a restart
  1313  	testutil.WaitForResult(func() (bool, error) {
  1314  		if l := len(ctx.upd.events); l != 4 {
  1315  			return false, fmt.Errorf("Expect four events; got %#v", ctx.upd.events)
  1316  		}
  1317  
  1318  		if ctx.upd.events[0].Type != structs.TaskReceived {
  1319  			return false, fmt.Errorf("First Event was %v; want %v", ctx.upd.events[0].Type, structs.TaskReceived)
  1320  		}
  1321  
  1322  		if ctx.upd.events[1].Type != structs.TaskSetup {
  1323  			return false, fmt.Errorf("Second Event was %v; want %v", ctx.upd.events[1].Type, structs.TaskSetup)
  1324  		}
  1325  
  1326  		if ctx.upd.events[2].Type != structs.TaskStarted {
  1327  			return false, fmt.Errorf("Third Event was %v; want %v", ctx.upd.events[2].Type, structs.TaskStarted)
  1328  		}
  1329  
  1330  		if ctx.upd.events[3].Type != structs.TaskSignaling {
  1331  			return false, fmt.Errorf("Fourth Event was %v; want %v", ctx.upd.events[3].Type, structs.TaskSignaling)
  1332  		}
  1333  
  1334  		return true, nil
  1335  	}, func(err error) {
  1336  		t.Fatalf("err: %v", err)
  1337  	})
  1338  }
  1339  
  1340  // Test that the payload is written to disk
  1341  func TestTaskRunner_SimpleRun_Dispatch(t *testing.T) {
  1342  	alloc := mock.Alloc()
  1343  	task := alloc.Job.TaskGroups[0].Tasks[0]
  1344  	task.Driver = "mock_driver"
  1345  	task.Config = map[string]interface{}{
  1346  		"exit_code": "0",
  1347  		"run_for":   "1s",
  1348  	}
  1349  	fileName := "test"
  1350  	task.DispatchPayload = &structs.DispatchPayloadConfig{
  1351  		File: fileName,
  1352  	}
  1353  	alloc.Job.ParameterizedJob = &structs.ParameterizedJobConfig{}
  1354  
  1355  	// Add an encrypted payload
  1356  	expected := []byte("hello world")
  1357  	compressed := snappy.Encode(nil, expected)
  1358  	alloc.Job.Payload = compressed
  1359  
  1360  	ctx := testTaskRunnerFromAlloc(t, false, alloc)
  1361  	ctx.tr.MarkReceived()
  1362  	defer ctx.tr.Destroy(structs.NewTaskEvent(structs.TaskKilled))
  1363  	defer ctx.allocDir.Destroy()
  1364  	go ctx.tr.Run()
  1365  
  1366  	select {
  1367  	case <-ctx.tr.WaitCh():
  1368  	case <-time.After(time.Duration(testutil.TestMultiplier()*15) * time.Second):
  1369  		t.Fatalf("timeout")
  1370  	}
  1371  
  1372  	if len(ctx.upd.events) != 4 {
  1373  		t.Fatalf("should have 4 updates: %#v", ctx.upd.events)
  1374  	}
  1375  
  1376  	if ctx.upd.state != structs.TaskStateDead {
  1377  		t.Fatalf("TaskState %v; want %v", ctx.upd.state, structs.TaskStateDead)
  1378  	}
  1379  
  1380  	if ctx.upd.events[0].Type != structs.TaskReceived {
  1381  		t.Fatalf("First Event was %v; want %v", ctx.upd.events[0].Type, structs.TaskReceived)
  1382  	}
  1383  
  1384  	if ctx.upd.events[1].Type != structs.TaskSetup {
  1385  		t.Fatalf("Second Event was %v; want %v", ctx.upd.events[1].Type, structs.TaskSetup)
  1386  	}
  1387  
  1388  	if ctx.upd.events[2].Type != structs.TaskStarted {
  1389  		t.Fatalf("Third Event was %v; want %v", ctx.upd.events[2].Type, structs.TaskStarted)
  1390  	}
  1391  
  1392  	if ctx.upd.events[3].Type != structs.TaskTerminated {
  1393  		t.Fatalf("Fourth Event was %v; want %v", ctx.upd.events[3].Type, structs.TaskTerminated)
  1394  	}
  1395  
  1396  	// Check that the file was written to disk properly
  1397  	payloadPath := filepath.Join(ctx.tr.taskDir.LocalDir, fileName)
  1398  	data, err := ioutil.ReadFile(payloadPath)
  1399  	if err != nil {
  1400  		t.Fatalf("Failed to read file: %v", err)
  1401  	}
  1402  	if !reflect.DeepEqual(data, expected) {
  1403  		t.Fatalf("Bad; got %v; want %v", string(data), string(expected))
  1404  	}
  1405  }
  1406  
  1407  // TestTaskRunner_CleanupEmpty ensures TaskRunner works when createdResources
  1408  // is empty.
  1409  func TestTaskRunner_CleanupEmpty(t *testing.T) {
  1410  	alloc := mock.Alloc()
  1411  	task := alloc.Job.TaskGroups[0].Tasks[0]
  1412  	task.Driver = "mock_driver"
  1413  
  1414  	ctx := testTaskRunnerFromAlloc(t, false, alloc)
  1415  	ctx.tr.MarkReceived()
  1416  
  1417  	defer ctx.Cleanup()
  1418  	ctx.tr.Run()
  1419  
  1420  	// Since we only failed once, createdResources should be empty
  1421  	if len(ctx.tr.createdResources.Resources) != 0 {
  1422  		t.Fatalf("createdResources should still be empty: %v", ctx.tr.createdResources)
  1423  	}
  1424  }
  1425  
  1426  func TestTaskRunner_CleanupOK(t *testing.T) {
  1427  	alloc := mock.Alloc()
  1428  	task := alloc.Job.TaskGroups[0].Tasks[0]
  1429  	task.Driver = "mock_driver"
  1430  	key := "ERR"
  1431  
  1432  	ctx := testTaskRunnerFromAlloc(t, false, alloc)
  1433  	ctx.tr.config.Options = map[string]string{
  1434  		"cleanup_fail_on":  key,
  1435  		"cleanup_fail_num": "1",
  1436  	}
  1437  	ctx.tr.MarkReceived()
  1438  
  1439  	ctx.tr.createdResources.Resources[key] = []string{"x", "y"}
  1440  	ctx.tr.createdResources.Resources["foo"] = []string{"z"}
  1441  
  1442  	defer ctx.Cleanup()
  1443  	ctx.tr.Run()
  1444  
  1445  	// Since we only failed once, createdResources should be empty
  1446  	if len(ctx.tr.createdResources.Resources) > 0 {
  1447  		t.Fatalf("expected all created resources to be removed: %#v", ctx.tr.createdResources.Resources)
  1448  	}
  1449  }
  1450  
  1451  func TestTaskRunner_CleanupFail(t *testing.T) {
  1452  	alloc := mock.Alloc()
  1453  	task := alloc.Job.TaskGroups[0].Tasks[0]
  1454  	task.Driver = "mock_driver"
  1455  	key := "ERR"
  1456  	ctx := testTaskRunnerFromAlloc(t, false, alloc)
  1457  	ctx.tr.config.Options = map[string]string{
  1458  		"cleanup_fail_on":  key,
  1459  		"cleanup_fail_num": "5",
  1460  	}
  1461  	ctx.tr.MarkReceived()
  1462  
  1463  	ctx.tr.createdResources.Resources[key] = []string{"x"}
  1464  	ctx.tr.createdResources.Resources["foo"] = []string{"y", "z"}
  1465  
  1466  	defer ctx.Cleanup()
  1467  	ctx.tr.Run()
  1468  
  1469  	// Since we failed > 3 times, the failed key should remain
  1470  	expected := map[string][]string{key: {"x"}}
  1471  	if !reflect.DeepEqual(expected, ctx.tr.createdResources.Resources) {
  1472  		t.Fatalf("expected %#v but found: %#v", expected, ctx.tr.createdResources.Resources)
  1473  	}
  1474  }