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