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