github.com/bigcommerce/nomad@v0.9.3-bc/nomad/state/state_store_test.go (about)

     1  package state
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"reflect"
     7  	"sort"
     8  	"strings"
     9  	"testing"
    10  	"time"
    11  
    12  	"github.com/hashicorp/go-memdb"
    13  	"github.com/hashicorp/nomad/helper"
    14  	"github.com/hashicorp/nomad/helper/uuid"
    15  	"github.com/hashicorp/nomad/nomad/mock"
    16  	"github.com/hashicorp/nomad/nomad/structs"
    17  	"github.com/stretchr/testify/assert"
    18  	"github.com/stretchr/testify/require"
    19  )
    20  
    21  func testStateStore(t *testing.T) *StateStore {
    22  	return TestStateStore(t)
    23  }
    24  
    25  func TestStateStore_Blocking_Error(t *testing.T) {
    26  	t.Parallel()
    27  	expected := fmt.Errorf("test error")
    28  	errFn := func(memdb.WatchSet, *StateStore) (interface{}, uint64, error) {
    29  		return nil, 0, expected
    30  	}
    31  
    32  	state := testStateStore(t)
    33  	_, idx, err := state.BlockingQuery(errFn, 10, context.Background())
    34  	assert.EqualError(t, err, expected.Error())
    35  	assert.Zero(t, idx)
    36  }
    37  
    38  func TestStateStore_Blocking_Timeout(t *testing.T) {
    39  	t.Parallel()
    40  	noopFn := func(memdb.WatchSet, *StateStore) (interface{}, uint64, error) {
    41  		return nil, 5, nil
    42  	}
    43  
    44  	state := testStateStore(t)
    45  	timeout := time.Now().Add(250 * time.Millisecond)
    46  	deadlineCtx, cancel := context.WithDeadline(context.Background(), timeout)
    47  	defer cancel()
    48  
    49  	_, idx, err := state.BlockingQuery(noopFn, 10, deadlineCtx)
    50  	assert.EqualError(t, err, context.DeadlineExceeded.Error())
    51  	assert.EqualValues(t, 5, idx)
    52  	assert.WithinDuration(t, timeout, time.Now(), 100*time.Millisecond)
    53  }
    54  
    55  func TestStateStore_Blocking_MinQuery(t *testing.T) {
    56  	node := mock.Node()
    57  	count := 0
    58  	queryFn := func(ws memdb.WatchSet, s *StateStore) (interface{}, uint64, error) {
    59  		_, err := s.NodeByID(ws, node.ID)
    60  		if err != nil {
    61  			return nil, 0, err
    62  		}
    63  
    64  		count++
    65  		if count == 1 {
    66  			return false, 5, nil
    67  		} else if count > 2 {
    68  			return false, 20, fmt.Errorf("called too many times")
    69  		}
    70  
    71  		return true, 11, nil
    72  	}
    73  
    74  	state := testStateStore(t)
    75  	timeout := time.Now().Add(100 * time.Millisecond)
    76  	deadlineCtx, cancel := context.WithDeadline(context.Background(), timeout)
    77  	defer cancel()
    78  
    79  	time.AfterFunc(5*time.Millisecond, func() {
    80  		state.UpsertNode(11, node)
    81  	})
    82  
    83  	resp, idx, err := state.BlockingQuery(queryFn, 10, deadlineCtx)
    84  	if assert.Nil(t, err) {
    85  		assert.Equal(t, 2, count)
    86  		assert.EqualValues(t, 11, idx)
    87  		assert.True(t, resp.(bool))
    88  	}
    89  }
    90  
    91  // COMPAT 0.11: Uses AllocUpdateRequest.Alloc
    92  // This test checks that:
    93  // 1) The job is denormalized
    94  // 2) Allocations are created
    95  func TestStateStore_UpsertPlanResults_AllocationsCreated_Denormalized(t *testing.T) {
    96  	state := testStateStore(t)
    97  	alloc := mock.Alloc()
    98  	job := alloc.Job
    99  	alloc.Job = nil
   100  
   101  	if err := state.UpsertJob(999, job); err != nil {
   102  		t.Fatalf("err: %v", err)
   103  	}
   104  
   105  	eval := mock.Eval()
   106  	eval.JobID = job.ID
   107  
   108  	// Create an eval
   109  	if err := state.UpsertEvals(1, []*structs.Evaluation{eval}); err != nil {
   110  		t.Fatalf("err: %v", err)
   111  	}
   112  
   113  	// Create a plan result
   114  	res := structs.ApplyPlanResultsRequest{
   115  		AllocUpdateRequest: structs.AllocUpdateRequest{
   116  			Alloc: []*structs.Allocation{alloc},
   117  			Job:   job,
   118  		},
   119  		EvalID: eval.ID,
   120  	}
   121  	assert := assert.New(t)
   122  	err := state.UpsertPlanResults(1000, &res)
   123  	assert.Nil(err)
   124  
   125  	ws := memdb.NewWatchSet()
   126  	out, err := state.AllocByID(ws, alloc.ID)
   127  	assert.Nil(err)
   128  	assert.Equal(alloc, out)
   129  
   130  	index, err := state.Index("allocs")
   131  	assert.Nil(err)
   132  	assert.EqualValues(1000, index)
   133  
   134  	if watchFired(ws) {
   135  		t.Fatalf("bad")
   136  	}
   137  
   138  	evalOut, err := state.EvalByID(ws, eval.ID)
   139  	assert.Nil(err)
   140  	assert.NotNil(evalOut)
   141  	assert.EqualValues(1000, evalOut.ModifyIndex)
   142  }
   143  
   144  // This test checks that:
   145  // 1) The job is denormalized
   146  // 2) Allocations are denormalized and updated with the diff
   147  // That stopped allocs Job is unmodified
   148  func TestStateStore_UpsertPlanResults_AllocationsDenormalized(t *testing.T) {
   149  	state := testStateStore(t)
   150  	alloc := mock.Alloc()
   151  	job := alloc.Job
   152  	alloc.Job = nil
   153  
   154  	stoppedAlloc := mock.Alloc()
   155  	stoppedAlloc.Job = job
   156  	stoppedAllocDiff := &structs.AllocationDiff{
   157  		ID:                 stoppedAlloc.ID,
   158  		DesiredDescription: "desired desc",
   159  		ClientStatus:       structs.AllocClientStatusLost,
   160  	}
   161  	preemptedAlloc := mock.Alloc()
   162  	preemptedAlloc.Job = job
   163  	preemptedAllocDiff := &structs.AllocationDiff{
   164  		ID:                    preemptedAlloc.ID,
   165  		PreemptedByAllocation: alloc.ID,
   166  	}
   167  
   168  	require := require.New(t)
   169  	require.NoError(state.UpsertAllocs(900, []*structs.Allocation{stoppedAlloc, preemptedAlloc}))
   170  	require.NoError(state.UpsertJob(999, job))
   171  
   172  	// modify job and ensure that stopped and preempted alloc point to original Job
   173  	mJob := job.Copy()
   174  	mJob.TaskGroups[0].Name = "other"
   175  
   176  	require.NoError(state.UpsertJob(1001, mJob))
   177  
   178  	eval := mock.Eval()
   179  	eval.JobID = job.ID
   180  
   181  	// Create an eval
   182  	require.NoError(state.UpsertEvals(1, []*structs.Evaluation{eval}))
   183  
   184  	// Create a plan result
   185  	res := structs.ApplyPlanResultsRequest{
   186  		AllocUpdateRequest: structs.AllocUpdateRequest{
   187  			AllocsUpdated: []*structs.Allocation{alloc},
   188  			AllocsStopped: []*structs.AllocationDiff{stoppedAllocDiff},
   189  			Job:           mJob,
   190  		},
   191  		EvalID:          eval.ID,
   192  		AllocsPreempted: []*structs.AllocationDiff{preemptedAllocDiff},
   193  	}
   194  	assert := assert.New(t)
   195  	planModifyIndex := uint64(1000)
   196  	err := state.UpsertPlanResults(planModifyIndex, &res)
   197  	require.NoError(err)
   198  
   199  	ws := memdb.NewWatchSet()
   200  	out, err := state.AllocByID(ws, alloc.ID)
   201  	require.NoError(err)
   202  	assert.Equal(alloc, out)
   203  
   204  	outJob, err := state.JobByID(ws, job.Namespace, job.ID)
   205  	require.NoError(err)
   206  	require.Equal(mJob.TaskGroups, outJob.TaskGroups)
   207  	require.NotEmpty(job.TaskGroups, outJob.TaskGroups)
   208  
   209  	updatedStoppedAlloc, err := state.AllocByID(ws, stoppedAlloc.ID)
   210  	require.NoError(err)
   211  	assert.Equal(stoppedAllocDiff.DesiredDescription, updatedStoppedAlloc.DesiredDescription)
   212  	assert.Equal(structs.AllocDesiredStatusStop, updatedStoppedAlloc.DesiredStatus)
   213  	assert.Equal(stoppedAllocDiff.ClientStatus, updatedStoppedAlloc.ClientStatus)
   214  	assert.Equal(planModifyIndex, updatedStoppedAlloc.AllocModifyIndex)
   215  	assert.Equal(planModifyIndex, updatedStoppedAlloc.AllocModifyIndex)
   216  	assert.Equal(job.TaskGroups, updatedStoppedAlloc.Job.TaskGroups)
   217  
   218  	updatedPreemptedAlloc, err := state.AllocByID(ws, preemptedAlloc.ID)
   219  	require.NoError(err)
   220  	assert.Equal(structs.AllocDesiredStatusEvict, updatedPreemptedAlloc.DesiredStatus)
   221  	assert.Equal(preemptedAllocDiff.PreemptedByAllocation, updatedPreemptedAlloc.PreemptedByAllocation)
   222  	assert.Equal(planModifyIndex, updatedPreemptedAlloc.AllocModifyIndex)
   223  	assert.Equal(planModifyIndex, updatedPreemptedAlloc.AllocModifyIndex)
   224  	assert.Equal(job.TaskGroups, updatedPreemptedAlloc.Job.TaskGroups)
   225  
   226  	index, err := state.Index("allocs")
   227  	require.NoError(err)
   228  	assert.EqualValues(planModifyIndex, index)
   229  
   230  	require.False(watchFired(ws))
   231  
   232  	evalOut, err := state.EvalByID(ws, eval.ID)
   233  	require.NoError(err)
   234  	require.NotNil(evalOut)
   235  	assert.EqualValues(planModifyIndex, evalOut.ModifyIndex)
   236  
   237  }
   238  
   239  // This test checks that the deployment is created and allocations count towards
   240  // the deployment
   241  func TestStateStore_UpsertPlanResults_Deployment(t *testing.T) {
   242  	state := testStateStore(t)
   243  	alloc := mock.Alloc()
   244  	alloc2 := mock.Alloc()
   245  	job := alloc.Job
   246  	alloc.Job = nil
   247  	alloc2.Job = nil
   248  
   249  	d := mock.Deployment()
   250  	alloc.DeploymentID = d.ID
   251  	alloc2.DeploymentID = d.ID
   252  
   253  	if err := state.UpsertJob(999, job); err != nil {
   254  		t.Fatalf("err: %v", err)
   255  	}
   256  
   257  	eval := mock.Eval()
   258  	eval.JobID = job.ID
   259  
   260  	// Create an eval
   261  	if err := state.UpsertEvals(1, []*structs.Evaluation{eval}); err != nil {
   262  		t.Fatalf("err: %v", err)
   263  	}
   264  
   265  	// Create a plan result
   266  	res := structs.ApplyPlanResultsRequest{
   267  		AllocUpdateRequest: structs.AllocUpdateRequest{
   268  			Alloc: []*structs.Allocation{alloc, alloc2},
   269  			Job:   job,
   270  		},
   271  		Deployment: d,
   272  		EvalID:     eval.ID,
   273  	}
   274  
   275  	err := state.UpsertPlanResults(1000, &res)
   276  	if err != nil {
   277  		t.Fatalf("err: %v", err)
   278  	}
   279  
   280  	ws := memdb.NewWatchSet()
   281  	assert := assert.New(t)
   282  	out, err := state.AllocByID(ws, alloc.ID)
   283  	assert.Nil(err)
   284  	assert.Equal(alloc, out)
   285  
   286  	dout, err := state.DeploymentByID(ws, d.ID)
   287  	assert.Nil(err)
   288  	assert.NotNil(dout)
   289  
   290  	tg, ok := dout.TaskGroups[alloc.TaskGroup]
   291  	assert.True(ok)
   292  	assert.NotNil(tg)
   293  	assert.Equal(2, tg.PlacedAllocs)
   294  
   295  	evalOut, err := state.EvalByID(ws, eval.ID)
   296  	assert.Nil(err)
   297  	assert.NotNil(evalOut)
   298  	assert.EqualValues(1000, evalOut.ModifyIndex)
   299  
   300  	if watchFired(ws) {
   301  		t.Fatalf("bad")
   302  	}
   303  
   304  	// Update the allocs to be part of a new deployment
   305  	d2 := d.Copy()
   306  	d2.ID = uuid.Generate()
   307  
   308  	allocNew := alloc.Copy()
   309  	allocNew.DeploymentID = d2.ID
   310  	allocNew2 := alloc2.Copy()
   311  	allocNew2.DeploymentID = d2.ID
   312  
   313  	// Create another plan
   314  	res = structs.ApplyPlanResultsRequest{
   315  		AllocUpdateRequest: structs.AllocUpdateRequest{
   316  			Alloc: []*structs.Allocation{allocNew, allocNew2},
   317  			Job:   job,
   318  		},
   319  		Deployment: d2,
   320  		EvalID:     eval.ID,
   321  	}
   322  
   323  	err = state.UpsertPlanResults(1001, &res)
   324  	if err != nil {
   325  		t.Fatalf("err: %v", err)
   326  	}
   327  
   328  	dout, err = state.DeploymentByID(ws, d2.ID)
   329  	assert.Nil(err)
   330  	assert.NotNil(dout)
   331  
   332  	tg, ok = dout.TaskGroups[alloc.TaskGroup]
   333  	assert.True(ok)
   334  	assert.NotNil(tg)
   335  	assert.Equal(2, tg.PlacedAllocs)
   336  
   337  	evalOut, err = state.EvalByID(ws, eval.ID)
   338  	assert.Nil(err)
   339  	assert.NotNil(evalOut)
   340  	assert.EqualValues(1001, evalOut.ModifyIndex)
   341  }
   342  
   343  // This test checks that:
   344  // 1) Preempted allocations in plan results are updated
   345  // 2) Evals are inserted for preempted jobs
   346  func TestStateStore_UpsertPlanResults_PreemptedAllocs(t *testing.T) {
   347  	require := require.New(t)
   348  
   349  	state := testStateStore(t)
   350  	alloc := mock.Alloc()
   351  	job := alloc.Job
   352  	alloc.Job = nil
   353  
   354  	// Insert job
   355  	err := state.UpsertJob(999, job)
   356  	require.NoError(err)
   357  
   358  	// Create an eval
   359  	eval := mock.Eval()
   360  	eval.JobID = job.ID
   361  	err = state.UpsertEvals(1, []*structs.Evaluation{eval})
   362  	require.NoError(err)
   363  
   364  	// Insert alloc that will be preempted in the plan
   365  	preemptedAlloc := mock.Alloc()
   366  	err = state.UpsertAllocs(2, []*structs.Allocation{preemptedAlloc})
   367  	require.NoError(err)
   368  
   369  	minimalPreemptedAlloc := &structs.Allocation{
   370  		ID:                    preemptedAlloc.ID,
   371  		PreemptedByAllocation: alloc.ID,
   372  		ModifyTime:            time.Now().Unix(),
   373  	}
   374  
   375  	// Create eval for preempted job
   376  	eval2 := mock.Eval()
   377  	eval2.JobID = preemptedAlloc.JobID
   378  
   379  	// Create a plan result
   380  	res := structs.ApplyPlanResultsRequest{
   381  		AllocUpdateRequest: structs.AllocUpdateRequest{
   382  			Alloc: []*structs.Allocation{alloc},
   383  			Job:   job,
   384  		},
   385  		EvalID:          eval.ID,
   386  		NodePreemptions: []*structs.Allocation{minimalPreemptedAlloc},
   387  		PreemptionEvals: []*structs.Evaluation{eval2},
   388  	}
   389  
   390  	err = state.UpsertPlanResults(1000, &res)
   391  	require.NoError(err)
   392  
   393  	ws := memdb.NewWatchSet()
   394  
   395  	// Verify alloc and eval created by plan
   396  	out, err := state.AllocByID(ws, alloc.ID)
   397  	require.NoError(err)
   398  	require.Equal(alloc, out)
   399  
   400  	index, err := state.Index("allocs")
   401  	require.NoError(err)
   402  	require.EqualValues(1000, index)
   403  
   404  	evalOut, err := state.EvalByID(ws, eval.ID)
   405  	require.NoError(err)
   406  	require.NotNil(evalOut)
   407  	require.EqualValues(1000, evalOut.ModifyIndex)
   408  
   409  	// Verify preempted alloc
   410  	preempted, err := state.AllocByID(ws, preemptedAlloc.ID)
   411  	require.NoError(err)
   412  	require.Equal(preempted.DesiredStatus, structs.AllocDesiredStatusEvict)
   413  	require.Equal(preempted.DesiredDescription, fmt.Sprintf("Preempted by alloc ID %v", alloc.ID))
   414  	require.Equal(preempted.Job.ID, preemptedAlloc.Job.ID)
   415  	require.Equal(preempted.Job, preemptedAlloc.Job)
   416  
   417  	// Verify eval for preempted job
   418  	preemptedJobEval, err := state.EvalByID(ws, eval2.ID)
   419  	require.NoError(err)
   420  	require.NotNil(preemptedJobEval)
   421  	require.EqualValues(1000, preemptedJobEval.ModifyIndex)
   422  
   423  }
   424  
   425  // This test checks that deployment updates are applied correctly
   426  func TestStateStore_UpsertPlanResults_DeploymentUpdates(t *testing.T) {
   427  	state := testStateStore(t)
   428  
   429  	// Create a job that applies to all
   430  	job := mock.Job()
   431  	if err := state.UpsertJob(998, job); err != nil {
   432  		t.Fatalf("err: %v", err)
   433  	}
   434  
   435  	// Create a deployment that we will update its status
   436  	doutstanding := mock.Deployment()
   437  	doutstanding.JobID = job.ID
   438  
   439  	if err := state.UpsertDeployment(1000, doutstanding); err != nil {
   440  		t.Fatalf("err: %v", err)
   441  	}
   442  
   443  	eval := mock.Eval()
   444  	eval.JobID = job.ID
   445  
   446  	// Create an eval
   447  	if err := state.UpsertEvals(1, []*structs.Evaluation{eval}); err != nil {
   448  		t.Fatalf("err: %v", err)
   449  	}
   450  	alloc := mock.Alloc()
   451  	alloc.Job = nil
   452  
   453  	dnew := mock.Deployment()
   454  	dnew.JobID = job.ID
   455  	alloc.DeploymentID = dnew.ID
   456  
   457  	// Update the old deployment
   458  	update := &structs.DeploymentStatusUpdate{
   459  		DeploymentID:      doutstanding.ID,
   460  		Status:            "foo",
   461  		StatusDescription: "bar",
   462  	}
   463  
   464  	// Create a plan result
   465  	res := structs.ApplyPlanResultsRequest{
   466  		AllocUpdateRequest: structs.AllocUpdateRequest{
   467  			Alloc: []*structs.Allocation{alloc},
   468  			Job:   job,
   469  		},
   470  		Deployment:        dnew,
   471  		DeploymentUpdates: []*structs.DeploymentStatusUpdate{update},
   472  		EvalID:            eval.ID,
   473  	}
   474  
   475  	err := state.UpsertPlanResults(1000, &res)
   476  	if err != nil {
   477  		t.Fatalf("err: %v", err)
   478  	}
   479  	assert := assert.New(t)
   480  	ws := memdb.NewWatchSet()
   481  
   482  	// Check the deployments are correctly updated.
   483  	dout, err := state.DeploymentByID(ws, dnew.ID)
   484  	assert.Nil(err)
   485  	assert.NotNil(dout)
   486  
   487  	tg, ok := dout.TaskGroups[alloc.TaskGroup]
   488  	assert.True(ok)
   489  	assert.NotNil(tg)
   490  	assert.Equal(1, tg.PlacedAllocs)
   491  
   492  	doutstandingout, err := state.DeploymentByID(ws, doutstanding.ID)
   493  	assert.Nil(err)
   494  	assert.NotNil(doutstandingout)
   495  	assert.Equal(update.Status, doutstandingout.Status)
   496  	assert.Equal(update.StatusDescription, doutstandingout.StatusDescription)
   497  	assert.EqualValues(1000, doutstandingout.ModifyIndex)
   498  
   499  	evalOut, err := state.EvalByID(ws, eval.ID)
   500  	assert.Nil(err)
   501  	assert.NotNil(evalOut)
   502  	assert.EqualValues(1000, evalOut.ModifyIndex)
   503  	if watchFired(ws) {
   504  		t.Fatalf("bad")
   505  	}
   506  }
   507  
   508  func TestStateStore_UpsertDeployment(t *testing.T) {
   509  	state := testStateStore(t)
   510  	deployment := mock.Deployment()
   511  
   512  	// Create a watchset so we can test that upsert fires the watch
   513  	ws := memdb.NewWatchSet()
   514  	_, err := state.DeploymentsByJobID(ws, deployment.Namespace, deployment.ID, true)
   515  	if err != nil {
   516  		t.Fatalf("bad: %v", err)
   517  	}
   518  
   519  	err = state.UpsertDeployment(1000, deployment)
   520  	if err != nil {
   521  		t.Fatalf("err: %v", err)
   522  	}
   523  	if !watchFired(ws) {
   524  		t.Fatalf("bad")
   525  	}
   526  
   527  	ws = memdb.NewWatchSet()
   528  	out, err := state.DeploymentByID(ws, deployment.ID)
   529  	if err != nil {
   530  		t.Fatalf("err: %v", err)
   531  	}
   532  
   533  	if !reflect.DeepEqual(deployment, out) {
   534  		t.Fatalf("bad: %#v %#v", deployment, out)
   535  	}
   536  
   537  	index, err := state.Index("deployment")
   538  	if err != nil {
   539  		t.Fatalf("err: %v", err)
   540  	}
   541  	if index != 1000 {
   542  		t.Fatalf("bad: %d", index)
   543  	}
   544  
   545  	if watchFired(ws) {
   546  		t.Fatalf("bad")
   547  	}
   548  }
   549  
   550  // Tests that deployments of older create index and same job id are not returned
   551  func TestStateStore_OldDeployment(t *testing.T) {
   552  	state := testStateStore(t)
   553  	job := mock.Job()
   554  	job.ID = "job1"
   555  	state.UpsertJob(1000, job)
   556  
   557  	deploy1 := mock.Deployment()
   558  	deploy1.JobID = job.ID
   559  	deploy1.JobCreateIndex = job.CreateIndex
   560  
   561  	deploy2 := mock.Deployment()
   562  	deploy2.JobID = job.ID
   563  	deploy2.JobCreateIndex = 11
   564  
   565  	require := require.New(t)
   566  
   567  	// Insert both deployments
   568  	err := state.UpsertDeployment(1001, deploy1)
   569  	require.Nil(err)
   570  
   571  	err = state.UpsertDeployment(1002, deploy2)
   572  	require.Nil(err)
   573  
   574  	ws := memdb.NewWatchSet()
   575  	// Should return both deployments
   576  	deploys, err := state.DeploymentsByJobID(ws, deploy1.Namespace, job.ID, true)
   577  	require.Nil(err)
   578  	require.Len(deploys, 2)
   579  
   580  	// Should only return deploy1
   581  	deploys, err = state.DeploymentsByJobID(ws, deploy1.Namespace, job.ID, false)
   582  	require.Nil(err)
   583  	require.Len(deploys, 1)
   584  	require.Equal(deploy1.ID, deploys[0].ID)
   585  }
   586  
   587  func TestStateStore_DeleteDeployment(t *testing.T) {
   588  	state := testStateStore(t)
   589  	d1 := mock.Deployment()
   590  	d2 := mock.Deployment()
   591  
   592  	err := state.UpsertDeployment(1000, d1)
   593  	if err != nil {
   594  		t.Fatalf("err: %v", err)
   595  	}
   596  	if err := state.UpsertDeployment(1001, d2); err != nil {
   597  		t.Fatalf("err: %v", err)
   598  	}
   599  
   600  	// Create a watchset so we can test that delete fires the watch
   601  	ws := memdb.NewWatchSet()
   602  	if _, err := state.DeploymentByID(ws, d1.ID); err != nil {
   603  		t.Fatalf("bad: %v", err)
   604  	}
   605  
   606  	err = state.DeleteDeployment(1002, []string{d1.ID, d2.ID})
   607  	if err != nil {
   608  		t.Fatalf("err: %v", err)
   609  	}
   610  
   611  	if !watchFired(ws) {
   612  		t.Fatalf("bad")
   613  	}
   614  
   615  	ws = memdb.NewWatchSet()
   616  	out, err := state.DeploymentByID(ws, d1.ID)
   617  	if err != nil {
   618  		t.Fatalf("err: %v", err)
   619  	}
   620  
   621  	if out != nil {
   622  		t.Fatalf("bad: %#v %#v", d1, out)
   623  	}
   624  
   625  	index, err := state.Index("deployment")
   626  	if err != nil {
   627  		t.Fatalf("err: %v", err)
   628  	}
   629  	if index != 1002 {
   630  		t.Fatalf("bad: %d", index)
   631  	}
   632  
   633  	if watchFired(ws) {
   634  		t.Fatalf("bad")
   635  	}
   636  }
   637  
   638  func TestStateStore_Deployments(t *testing.T) {
   639  	state := testStateStore(t)
   640  	var deployments []*structs.Deployment
   641  
   642  	for i := 0; i < 10; i++ {
   643  		deployment := mock.Deployment()
   644  		deployments = append(deployments, deployment)
   645  
   646  		err := state.UpsertDeployment(1000+uint64(i), deployment)
   647  		if err != nil {
   648  			t.Fatalf("err: %v", err)
   649  		}
   650  	}
   651  
   652  	ws := memdb.NewWatchSet()
   653  	iter, err := state.Deployments(ws)
   654  	if err != nil {
   655  		t.Fatalf("err: %v", err)
   656  	}
   657  
   658  	var out []*structs.Deployment
   659  	for {
   660  		raw := iter.Next()
   661  		if raw == nil {
   662  			break
   663  		}
   664  		out = append(out, raw.(*structs.Deployment))
   665  	}
   666  
   667  	lessThan := func(i, j int) bool {
   668  		return deployments[i].ID < deployments[j].ID
   669  	}
   670  	sort.Slice(deployments, lessThan)
   671  	sort.Slice(out, lessThan)
   672  
   673  	if !reflect.DeepEqual(deployments, out) {
   674  		t.Fatalf("bad: %#v %#v", deployments, out)
   675  	}
   676  
   677  	if watchFired(ws) {
   678  		t.Fatalf("bad")
   679  	}
   680  }
   681  
   682  func TestStateStore_DeploymentsByIDPrefix(t *testing.T) {
   683  	state := testStateStore(t)
   684  	deploy := mock.Deployment()
   685  
   686  	deploy.ID = "11111111-662e-d0ab-d1c9-3e434af7bdb4"
   687  	err := state.UpsertDeployment(1000, deploy)
   688  	if err != nil {
   689  		t.Fatalf("err: %v", err)
   690  	}
   691  
   692  	// Create a watchset so we can test that getters don't cause it to fire
   693  	ws := memdb.NewWatchSet()
   694  	iter, err := state.DeploymentsByIDPrefix(ws, deploy.Namespace, deploy.ID)
   695  	if err != nil {
   696  		t.Fatalf("err: %v", err)
   697  	}
   698  
   699  	gatherDeploys := func(iter memdb.ResultIterator) []*structs.Deployment {
   700  		var deploys []*structs.Deployment
   701  		for {
   702  			raw := iter.Next()
   703  			if raw == nil {
   704  				break
   705  			}
   706  			deploy := raw.(*structs.Deployment)
   707  			deploys = append(deploys, deploy)
   708  		}
   709  		return deploys
   710  	}
   711  
   712  	deploys := gatherDeploys(iter)
   713  	if len(deploys) != 1 {
   714  		t.Fatalf("err: %v", err)
   715  	}
   716  
   717  	if watchFired(ws) {
   718  		t.Fatalf("bad")
   719  	}
   720  
   721  	iter, err = state.DeploymentsByIDPrefix(ws, deploy.Namespace, "11")
   722  	if err != nil {
   723  		t.Fatalf("err: %v", err)
   724  	}
   725  
   726  	deploys = gatherDeploys(iter)
   727  	if len(deploys) != 1 {
   728  		t.Fatalf("err: %v", err)
   729  	}
   730  
   731  	deploy = mock.Deployment()
   732  	deploy.ID = "11222222-662e-d0ab-d1c9-3e434af7bdb4"
   733  	err = state.UpsertDeployment(1001, deploy)
   734  	if err != nil {
   735  		t.Fatalf("err: %v", err)
   736  	}
   737  
   738  	if !watchFired(ws) {
   739  		t.Fatalf("bad")
   740  	}
   741  
   742  	ws = memdb.NewWatchSet()
   743  	iter, err = state.DeploymentsByIDPrefix(ws, deploy.Namespace, "11")
   744  	if err != nil {
   745  		t.Fatalf("err: %v", err)
   746  	}
   747  
   748  	deploys = gatherDeploys(iter)
   749  	if len(deploys) != 2 {
   750  		t.Fatalf("err: %v", err)
   751  	}
   752  
   753  	iter, err = state.DeploymentsByIDPrefix(ws, deploy.Namespace, "1111")
   754  	if err != nil {
   755  		t.Fatalf("err: %v", err)
   756  	}
   757  
   758  	deploys = gatherDeploys(iter)
   759  	if len(deploys) != 1 {
   760  		t.Fatalf("err: %v", err)
   761  	}
   762  
   763  	if watchFired(ws) {
   764  		t.Fatalf("bad")
   765  	}
   766  }
   767  
   768  func TestStateStore_UpsertNode_Node(t *testing.T) {
   769  	require := require.New(t)
   770  	state := testStateStore(t)
   771  	node := mock.Node()
   772  
   773  	// Create a watchset so we can test that upsert fires the watch
   774  	ws := memdb.NewWatchSet()
   775  	_, err := state.NodeByID(ws, node.ID)
   776  	require.NoError(err)
   777  
   778  	require.NoError(state.UpsertNode(1000, node))
   779  	require.True(watchFired(ws))
   780  
   781  	ws = memdb.NewWatchSet()
   782  	out, err := state.NodeByID(ws, node.ID)
   783  	require.NoError(err)
   784  
   785  	out2, err := state.NodeBySecretID(ws, node.SecretID)
   786  	require.NoError(err)
   787  	require.EqualValues(node, out)
   788  	require.EqualValues(node, out2)
   789  	require.Len(out.Events, 1)
   790  	require.Equal(NodeRegisterEventRegistered, out.Events[0].Message)
   791  
   792  	index, err := state.Index("nodes")
   793  	require.NoError(err)
   794  	require.EqualValues(1000, index)
   795  	require.False(watchFired(ws))
   796  
   797  	// Transition the node to down and then up and ensure we get a re-register
   798  	// event
   799  	down := out.Copy()
   800  	down.Status = structs.NodeStatusDown
   801  	require.NoError(state.UpsertNode(1001, down))
   802  	require.NoError(state.UpsertNode(1002, out))
   803  
   804  	out, err = state.NodeByID(ws, node.ID)
   805  	require.NoError(err)
   806  	require.Len(out.Events, 2)
   807  	require.Equal(NodeRegisterEventReregistered, out.Events[1].Message)
   808  }
   809  
   810  func TestStateStore_DeleteNode_Node(t *testing.T) {
   811  	state := testStateStore(t)
   812  	node := mock.Node()
   813  
   814  	err := state.UpsertNode(1000, node)
   815  	if err != nil {
   816  		t.Fatalf("err: %v", err)
   817  	}
   818  
   819  	// Create a watchset so we can test that delete fires the watch
   820  	ws := memdb.NewWatchSet()
   821  	if _, err := state.NodeByID(ws, node.ID); err != nil {
   822  		t.Fatalf("bad: %v", err)
   823  	}
   824  
   825  	err = state.DeleteNode(1001, node.ID)
   826  	if err != nil {
   827  		t.Fatalf("err: %v", err)
   828  	}
   829  
   830  	if !watchFired(ws) {
   831  		t.Fatalf("bad")
   832  	}
   833  
   834  	ws = memdb.NewWatchSet()
   835  	out, err := state.NodeByID(ws, node.ID)
   836  	if err != nil {
   837  		t.Fatalf("err: %v", err)
   838  	}
   839  
   840  	if out != nil {
   841  		t.Fatalf("bad: %#v %#v", node, out)
   842  	}
   843  
   844  	index, err := state.Index("nodes")
   845  	if err != nil {
   846  		t.Fatalf("err: %v", err)
   847  	}
   848  	if index != 1001 {
   849  		t.Fatalf("bad: %d", index)
   850  	}
   851  
   852  	if watchFired(ws) {
   853  		t.Fatalf("bad")
   854  	}
   855  }
   856  
   857  func TestStateStore_UpdateNodeStatus_Node(t *testing.T) {
   858  	require := require.New(t)
   859  	state := testStateStore(t)
   860  	node := mock.Node()
   861  
   862  	require.NoError(state.UpsertNode(800, node))
   863  
   864  	// Create a watchset so we can test that update node status fires the watch
   865  	ws := memdb.NewWatchSet()
   866  	_, err := state.NodeByID(ws, node.ID)
   867  	require.NoError(err)
   868  
   869  	event := &structs.NodeEvent{
   870  		Message:   "Node ready foo",
   871  		Subsystem: structs.NodeEventSubsystemCluster,
   872  		Timestamp: time.Now(),
   873  	}
   874  
   875  	require.NoError(state.UpdateNodeStatus(801, node.ID, structs.NodeStatusReady, 70, event))
   876  	require.True(watchFired(ws))
   877  
   878  	ws = memdb.NewWatchSet()
   879  	out, err := state.NodeByID(ws, node.ID)
   880  	require.NoError(err)
   881  	require.Equal(structs.NodeStatusReady, out.Status)
   882  	require.EqualValues(801, out.ModifyIndex)
   883  	require.EqualValues(70, out.StatusUpdatedAt)
   884  	require.Len(out.Events, 2)
   885  	require.Equal(event.Message, out.Events[1].Message)
   886  
   887  	index, err := state.Index("nodes")
   888  	require.NoError(err)
   889  	require.EqualValues(801, index)
   890  	require.False(watchFired(ws))
   891  }
   892  
   893  func TestStateStore_BatchUpdateNodeDrain(t *testing.T) {
   894  	require := require.New(t)
   895  	state := testStateStore(t)
   896  
   897  	n1, n2 := mock.Node(), mock.Node()
   898  	require.Nil(state.UpsertNode(1000, n1))
   899  	require.Nil(state.UpsertNode(1001, n2))
   900  
   901  	// Create a watchset so we can test that update node drain fires the watch
   902  	ws := memdb.NewWatchSet()
   903  	_, err := state.NodeByID(ws, n1.ID)
   904  	require.Nil(err)
   905  
   906  	expectedDrain := &structs.DrainStrategy{
   907  		DrainSpec: structs.DrainSpec{
   908  			Deadline: -1 * time.Second,
   909  		},
   910  	}
   911  
   912  	update := map[string]*structs.DrainUpdate{
   913  		n1.ID: {
   914  			DrainStrategy: expectedDrain,
   915  		},
   916  		n2.ID: {
   917  			DrainStrategy: expectedDrain,
   918  		},
   919  	}
   920  
   921  	event := &structs.NodeEvent{
   922  		Message:   "Drain strategy enabled",
   923  		Subsystem: structs.NodeEventSubsystemDrain,
   924  		Timestamp: time.Now(),
   925  	}
   926  	events := map[string]*structs.NodeEvent{
   927  		n1.ID: event,
   928  		n2.ID: event,
   929  	}
   930  
   931  	require.Nil(state.BatchUpdateNodeDrain(1002, 7, update, events))
   932  	require.True(watchFired(ws))
   933  
   934  	ws = memdb.NewWatchSet()
   935  	for _, id := range []string{n1.ID, n2.ID} {
   936  		out, err := state.NodeByID(ws, id)
   937  		require.Nil(err)
   938  		require.True(out.Drain)
   939  		require.NotNil(out.DrainStrategy)
   940  		require.Equal(out.DrainStrategy, expectedDrain)
   941  		require.Len(out.Events, 2)
   942  		require.EqualValues(1002, out.ModifyIndex)
   943  		require.EqualValues(7, out.StatusUpdatedAt)
   944  	}
   945  
   946  	index, err := state.Index("nodes")
   947  	require.Nil(err)
   948  	require.EqualValues(1002, index)
   949  	require.False(watchFired(ws))
   950  }
   951  
   952  func TestStateStore_UpdateNodeDrain_Node(t *testing.T) {
   953  	require := require.New(t)
   954  	state := testStateStore(t)
   955  	node := mock.Node()
   956  
   957  	require.Nil(state.UpsertNode(1000, node))
   958  
   959  	// Create a watchset so we can test that update node drain fires the watch
   960  	ws := memdb.NewWatchSet()
   961  	_, err := state.NodeByID(ws, node.ID)
   962  	require.Nil(err)
   963  
   964  	expectedDrain := &structs.DrainStrategy{
   965  		DrainSpec: structs.DrainSpec{
   966  			Deadline: -1 * time.Second,
   967  		},
   968  	}
   969  
   970  	event := &structs.NodeEvent{
   971  		Message:   "Drain strategy enabled",
   972  		Subsystem: structs.NodeEventSubsystemDrain,
   973  		Timestamp: time.Now(),
   974  	}
   975  	require.Nil(state.UpdateNodeDrain(1001, node.ID, expectedDrain, false, 7, event))
   976  	require.True(watchFired(ws))
   977  
   978  	ws = memdb.NewWatchSet()
   979  	out, err := state.NodeByID(ws, node.ID)
   980  	require.Nil(err)
   981  	require.True(out.Drain)
   982  	require.NotNil(out.DrainStrategy)
   983  	require.Equal(out.DrainStrategy, expectedDrain)
   984  	require.Len(out.Events, 2)
   985  	require.EqualValues(1001, out.ModifyIndex)
   986  	require.EqualValues(7, out.StatusUpdatedAt)
   987  
   988  	index, err := state.Index("nodes")
   989  	require.Nil(err)
   990  	require.EqualValues(1001, index)
   991  	require.False(watchFired(ws))
   992  }
   993  
   994  func TestStateStore_AddSingleNodeEvent(t *testing.T) {
   995  	require := require.New(t)
   996  	state := testStateStore(t)
   997  
   998  	node := mock.Node()
   999  
  1000  	// We create a new node event every time we register a node
  1001  	err := state.UpsertNode(1000, node)
  1002  	require.Nil(err)
  1003  
  1004  	require.Equal(1, len(node.Events))
  1005  	require.Equal(structs.NodeEventSubsystemCluster, node.Events[0].Subsystem)
  1006  	require.Equal(NodeRegisterEventRegistered, node.Events[0].Message)
  1007  
  1008  	// Create a watchset so we can test that AddNodeEvent fires the watch
  1009  	ws := memdb.NewWatchSet()
  1010  	_, err = state.NodeByID(ws, node.ID)
  1011  	require.Nil(err)
  1012  
  1013  	nodeEvent := &structs.NodeEvent{
  1014  		Message:   "failed",
  1015  		Subsystem: "Driver",
  1016  		Timestamp: time.Now(),
  1017  	}
  1018  	nodeEvents := map[string][]*structs.NodeEvent{
  1019  		node.ID: {nodeEvent},
  1020  	}
  1021  	err = state.UpsertNodeEvents(uint64(1001), nodeEvents)
  1022  	require.Nil(err)
  1023  
  1024  	require.True(watchFired(ws))
  1025  
  1026  	ws = memdb.NewWatchSet()
  1027  	out, err := state.NodeByID(ws, node.ID)
  1028  	require.Nil(err)
  1029  
  1030  	require.Equal(2, len(out.Events))
  1031  	require.Equal(nodeEvent, out.Events[1])
  1032  }
  1033  
  1034  // To prevent stale node events from accumulating, we limit the number of
  1035  // stored node events to 10.
  1036  func TestStateStore_NodeEvents_RetentionWindow(t *testing.T) {
  1037  	require := require.New(t)
  1038  	state := testStateStore(t)
  1039  
  1040  	node := mock.Node()
  1041  
  1042  	err := state.UpsertNode(1000, node)
  1043  	if err != nil {
  1044  		t.Fatalf("err: %v", err)
  1045  	}
  1046  	require.Equal(1, len(node.Events))
  1047  	require.Equal(structs.NodeEventSubsystemCluster, node.Events[0].Subsystem)
  1048  	require.Equal(NodeRegisterEventRegistered, node.Events[0].Message)
  1049  
  1050  	var out *structs.Node
  1051  	for i := 1; i <= 20; i++ {
  1052  		ws := memdb.NewWatchSet()
  1053  		out, err = state.NodeByID(ws, node.ID)
  1054  		require.Nil(err)
  1055  
  1056  		nodeEvent := &structs.NodeEvent{
  1057  			Message:   fmt.Sprintf("%dith failed", i),
  1058  			Subsystem: "Driver",
  1059  			Timestamp: time.Now(),
  1060  		}
  1061  
  1062  		nodeEvents := map[string][]*structs.NodeEvent{
  1063  			out.ID: {nodeEvent},
  1064  		}
  1065  		err := state.UpsertNodeEvents(uint64(i), nodeEvents)
  1066  		require.Nil(err)
  1067  
  1068  		require.True(watchFired(ws))
  1069  		ws = memdb.NewWatchSet()
  1070  		out, err = state.NodeByID(ws, node.ID)
  1071  		require.Nil(err)
  1072  	}
  1073  
  1074  	ws := memdb.NewWatchSet()
  1075  	out, err = state.NodeByID(ws, node.ID)
  1076  	require.Nil(err)
  1077  
  1078  	require.Equal(10, len(out.Events))
  1079  	require.Equal(uint64(11), out.Events[0].CreateIndex)
  1080  	require.Equal(uint64(20), out.Events[len(out.Events)-1].CreateIndex)
  1081  }
  1082  
  1083  func TestStateStore_UpdateNodeDrain_ResetEligiblity(t *testing.T) {
  1084  	require := require.New(t)
  1085  	state := testStateStore(t)
  1086  	node := mock.Node()
  1087  	require.Nil(state.UpsertNode(1000, node))
  1088  
  1089  	// Create a watchset so we can test that update node drain fires the watch
  1090  	ws := memdb.NewWatchSet()
  1091  	_, err := state.NodeByID(ws, node.ID)
  1092  	require.Nil(err)
  1093  
  1094  	drain := &structs.DrainStrategy{
  1095  		DrainSpec: structs.DrainSpec{
  1096  			Deadline: -1 * time.Second,
  1097  		},
  1098  	}
  1099  
  1100  	event1 := &structs.NodeEvent{
  1101  		Message:   "Drain strategy enabled",
  1102  		Subsystem: structs.NodeEventSubsystemDrain,
  1103  		Timestamp: time.Now(),
  1104  	}
  1105  	require.Nil(state.UpdateNodeDrain(1001, node.ID, drain, false, 7, event1))
  1106  	require.True(watchFired(ws))
  1107  
  1108  	// Remove the drain
  1109  	event2 := &structs.NodeEvent{
  1110  		Message:   "Drain strategy disabled",
  1111  		Subsystem: structs.NodeEventSubsystemDrain,
  1112  		Timestamp: time.Now(),
  1113  	}
  1114  	require.Nil(state.UpdateNodeDrain(1002, node.ID, nil, true, 9, event2))
  1115  
  1116  	ws = memdb.NewWatchSet()
  1117  	out, err := state.NodeByID(ws, node.ID)
  1118  	require.Nil(err)
  1119  	require.False(out.Drain)
  1120  	require.Nil(out.DrainStrategy)
  1121  	require.Equal(out.SchedulingEligibility, structs.NodeSchedulingEligible)
  1122  	require.Len(out.Events, 3)
  1123  	require.EqualValues(1002, out.ModifyIndex)
  1124  	require.EqualValues(9, out.StatusUpdatedAt)
  1125  
  1126  	index, err := state.Index("nodes")
  1127  	require.Nil(err)
  1128  	require.EqualValues(1002, index)
  1129  	require.False(watchFired(ws))
  1130  }
  1131  
  1132  func TestStateStore_UpdateNodeEligibility(t *testing.T) {
  1133  	require := require.New(t)
  1134  	state := testStateStore(t)
  1135  	node := mock.Node()
  1136  
  1137  	err := state.UpsertNode(1000, node)
  1138  	if err != nil {
  1139  		t.Fatalf("err: %v", err)
  1140  	}
  1141  
  1142  	expectedEligibility := structs.NodeSchedulingIneligible
  1143  
  1144  	// Create a watchset so we can test that update node drain fires the watch
  1145  	ws := memdb.NewWatchSet()
  1146  	if _, err := state.NodeByID(ws, node.ID); err != nil {
  1147  		t.Fatalf("bad: %v", err)
  1148  	}
  1149  
  1150  	event := &structs.NodeEvent{
  1151  		Message:   "Node marked as ineligible",
  1152  		Subsystem: structs.NodeEventSubsystemCluster,
  1153  		Timestamp: time.Now(),
  1154  	}
  1155  	require.Nil(state.UpdateNodeEligibility(1001, node.ID, expectedEligibility, 7, event))
  1156  	require.True(watchFired(ws))
  1157  
  1158  	ws = memdb.NewWatchSet()
  1159  	out, err := state.NodeByID(ws, node.ID)
  1160  	require.Nil(err)
  1161  	require.Equal(out.SchedulingEligibility, expectedEligibility)
  1162  	require.Len(out.Events, 2)
  1163  	require.Equal(out.Events[1], event)
  1164  	require.EqualValues(1001, out.ModifyIndex)
  1165  	require.EqualValues(7, out.StatusUpdatedAt)
  1166  
  1167  	index, err := state.Index("nodes")
  1168  	require.Nil(err)
  1169  	require.EqualValues(1001, index)
  1170  	require.False(watchFired(ws))
  1171  
  1172  	// Set a drain strategy
  1173  	expectedDrain := &structs.DrainStrategy{
  1174  		DrainSpec: structs.DrainSpec{
  1175  			Deadline: -1 * time.Second,
  1176  		},
  1177  	}
  1178  	require.Nil(state.UpdateNodeDrain(1002, node.ID, expectedDrain, false, 7, nil))
  1179  
  1180  	// Try to set the node to eligible
  1181  	err = state.UpdateNodeEligibility(1003, node.ID, structs.NodeSchedulingEligible, 9, nil)
  1182  	require.NotNil(err)
  1183  	require.Contains(err.Error(), "while it is draining")
  1184  }
  1185  
  1186  func TestStateStore_Nodes(t *testing.T) {
  1187  	state := testStateStore(t)
  1188  	var nodes []*structs.Node
  1189  
  1190  	for i := 0; i < 10; i++ {
  1191  		node := mock.Node()
  1192  		nodes = append(nodes, node)
  1193  
  1194  		err := state.UpsertNode(1000+uint64(i), node)
  1195  		if err != nil {
  1196  			t.Fatalf("err: %v", err)
  1197  		}
  1198  	}
  1199  
  1200  	// Create a watchset so we can test that getters don't cause it to fire
  1201  	ws := memdb.NewWatchSet()
  1202  	iter, err := state.Nodes(ws)
  1203  	if err != nil {
  1204  		t.Fatalf("bad: %v", err)
  1205  	}
  1206  
  1207  	var out []*structs.Node
  1208  	for {
  1209  		raw := iter.Next()
  1210  		if raw == nil {
  1211  			break
  1212  		}
  1213  		out = append(out, raw.(*structs.Node))
  1214  	}
  1215  
  1216  	sort.Sort(NodeIDSort(nodes))
  1217  	sort.Sort(NodeIDSort(out))
  1218  
  1219  	if !reflect.DeepEqual(nodes, out) {
  1220  		t.Fatalf("bad: %#v %#v", nodes, out)
  1221  	}
  1222  
  1223  	if watchFired(ws) {
  1224  		t.Fatalf("bad")
  1225  	}
  1226  }
  1227  
  1228  func TestStateStore_NodesByIDPrefix(t *testing.T) {
  1229  	state := testStateStore(t)
  1230  	node := mock.Node()
  1231  
  1232  	node.ID = "11111111-662e-d0ab-d1c9-3e434af7bdb4"
  1233  	err := state.UpsertNode(1000, node)
  1234  	if err != nil {
  1235  		t.Fatalf("err: %v", err)
  1236  	}
  1237  
  1238  	// Create a watchset so we can test that getters don't cause it to fire
  1239  	ws := memdb.NewWatchSet()
  1240  	iter, err := state.NodesByIDPrefix(ws, node.ID)
  1241  	if err != nil {
  1242  		t.Fatalf("err: %v", err)
  1243  	}
  1244  
  1245  	gatherNodes := func(iter memdb.ResultIterator) []*structs.Node {
  1246  		var nodes []*structs.Node
  1247  		for {
  1248  			raw := iter.Next()
  1249  			if raw == nil {
  1250  				break
  1251  			}
  1252  			node := raw.(*structs.Node)
  1253  			nodes = append(nodes, node)
  1254  		}
  1255  		return nodes
  1256  	}
  1257  
  1258  	nodes := gatherNodes(iter)
  1259  	if len(nodes) != 1 {
  1260  		t.Fatalf("err: %v", err)
  1261  	}
  1262  
  1263  	if watchFired(ws) {
  1264  		t.Fatalf("bad")
  1265  	}
  1266  
  1267  	iter, err = state.NodesByIDPrefix(ws, "11")
  1268  	if err != nil {
  1269  		t.Fatalf("err: %v", err)
  1270  	}
  1271  
  1272  	nodes = gatherNodes(iter)
  1273  	if len(nodes) != 1 {
  1274  		t.Fatalf("err: %v", err)
  1275  	}
  1276  
  1277  	node = mock.Node()
  1278  	node.ID = "11222222-662e-d0ab-d1c9-3e434af7bdb4"
  1279  	err = state.UpsertNode(1001, node)
  1280  	if err != nil {
  1281  		t.Fatalf("err: %v", err)
  1282  	}
  1283  
  1284  	if !watchFired(ws) {
  1285  		t.Fatalf("bad")
  1286  	}
  1287  
  1288  	ws = memdb.NewWatchSet()
  1289  	iter, err = state.NodesByIDPrefix(ws, "11")
  1290  	if err != nil {
  1291  		t.Fatalf("err: %v", err)
  1292  	}
  1293  
  1294  	nodes = gatherNodes(iter)
  1295  	if len(nodes) != 2 {
  1296  		t.Fatalf("err: %v", err)
  1297  	}
  1298  
  1299  	iter, err = state.NodesByIDPrefix(ws, "1111")
  1300  	if err != nil {
  1301  		t.Fatalf("err: %v", err)
  1302  	}
  1303  
  1304  	nodes = gatherNodes(iter)
  1305  	if len(nodes) != 1 {
  1306  		t.Fatalf("err: %v", err)
  1307  	}
  1308  
  1309  	if watchFired(ws) {
  1310  		t.Fatalf("bad")
  1311  	}
  1312  }
  1313  
  1314  func TestStateStore_RestoreNode(t *testing.T) {
  1315  	state := testStateStore(t)
  1316  	node := mock.Node()
  1317  
  1318  	restore, err := state.Restore()
  1319  	if err != nil {
  1320  		t.Fatalf("err: %v", err)
  1321  	}
  1322  
  1323  	err = restore.NodeRestore(node)
  1324  	if err != nil {
  1325  		t.Fatalf("err: %v", err)
  1326  	}
  1327  	restore.Commit()
  1328  
  1329  	ws := memdb.NewWatchSet()
  1330  	out, err := state.NodeByID(ws, node.ID)
  1331  	if err != nil {
  1332  		t.Fatalf("err: %v", err)
  1333  	}
  1334  
  1335  	if !reflect.DeepEqual(out, node) {
  1336  		t.Fatalf("Bad: %#v %#v", out, node)
  1337  	}
  1338  }
  1339  
  1340  func TestStateStore_UpsertJob_Job(t *testing.T) {
  1341  	state := testStateStore(t)
  1342  	job := mock.Job()
  1343  
  1344  	// Create a watchset so we can test that upsert fires the watch
  1345  	ws := memdb.NewWatchSet()
  1346  	_, err := state.JobByID(ws, job.Namespace, job.ID)
  1347  	if err != nil {
  1348  		t.Fatalf("bad: %v", err)
  1349  	}
  1350  
  1351  	if err := state.UpsertJob(1000, job); err != nil {
  1352  		t.Fatalf("err: %v", err)
  1353  	}
  1354  	if !watchFired(ws) {
  1355  		t.Fatalf("bad")
  1356  	}
  1357  
  1358  	ws = memdb.NewWatchSet()
  1359  	out, err := state.JobByID(ws, job.Namespace, job.ID)
  1360  	if err != nil {
  1361  		t.Fatalf("err: %v", err)
  1362  	}
  1363  
  1364  	if !reflect.DeepEqual(job, out) {
  1365  		t.Fatalf("bad: %#v %#v", job, out)
  1366  	}
  1367  
  1368  	index, err := state.Index("jobs")
  1369  	if err != nil {
  1370  		t.Fatalf("err: %v", err)
  1371  	}
  1372  	if index != 1000 {
  1373  		t.Fatalf("bad: %d", index)
  1374  	}
  1375  
  1376  	summary, err := state.JobSummaryByID(ws, job.Namespace, job.ID)
  1377  	if err != nil {
  1378  		t.Fatalf("err: %v", err)
  1379  	}
  1380  	if summary == nil {
  1381  		t.Fatalf("nil summary")
  1382  	}
  1383  	if summary.JobID != job.ID {
  1384  		t.Fatalf("bad summary id: %v", summary.JobID)
  1385  	}
  1386  	_, ok := summary.Summary["web"]
  1387  	if !ok {
  1388  		t.Fatalf("nil summary for task group")
  1389  	}
  1390  	if watchFired(ws) {
  1391  		t.Fatalf("bad")
  1392  	}
  1393  
  1394  	// Check the job versions
  1395  	allVersions, err := state.JobVersionsByID(ws, job.Namespace, job.ID)
  1396  	if err != nil {
  1397  		t.Fatalf("err: %v", err)
  1398  	}
  1399  	if len(allVersions) != 1 {
  1400  		t.Fatalf("got %d; want 1", len(allVersions))
  1401  	}
  1402  
  1403  	if a := allVersions[0]; a.ID != job.ID || a.Version != 0 {
  1404  		t.Fatalf("bad: %v", a)
  1405  	}
  1406  
  1407  	// Test the looking up the job by version returns the same results
  1408  	vout, err := state.JobByIDAndVersion(ws, job.Namespace, job.ID, 0)
  1409  	if err != nil {
  1410  		t.Fatalf("err: %v", err)
  1411  	}
  1412  
  1413  	if !reflect.DeepEqual(out, vout) {
  1414  		t.Fatalf("bad: %#v %#v", out, vout)
  1415  	}
  1416  }
  1417  
  1418  func TestStateStore_UpdateUpsertJob_Job(t *testing.T) {
  1419  	state := testStateStore(t)
  1420  	job := mock.Job()
  1421  
  1422  	// Create a watchset so we can test that upsert fires the watch
  1423  	ws := memdb.NewWatchSet()
  1424  	_, err := state.JobByID(ws, job.Namespace, job.ID)
  1425  	if err != nil {
  1426  		t.Fatalf("bad: %v", err)
  1427  	}
  1428  
  1429  	if err := state.UpsertJob(1000, job); err != nil {
  1430  		t.Fatalf("err: %v", err)
  1431  	}
  1432  
  1433  	job2 := mock.Job()
  1434  	job2.ID = job.ID
  1435  	job2.AllAtOnce = true
  1436  	err = state.UpsertJob(1001, job2)
  1437  	if err != nil {
  1438  		t.Fatalf("err: %v", err)
  1439  	}
  1440  
  1441  	if !watchFired(ws) {
  1442  		t.Fatalf("bad")
  1443  	}
  1444  
  1445  	ws = memdb.NewWatchSet()
  1446  	out, err := state.JobByID(ws, job.Namespace, job.ID)
  1447  	if err != nil {
  1448  		t.Fatalf("err: %v", err)
  1449  	}
  1450  
  1451  	if !reflect.DeepEqual(job2, out) {
  1452  		t.Fatalf("bad: %#v %#v", job2, out)
  1453  	}
  1454  
  1455  	if out.CreateIndex != 1000 {
  1456  		t.Fatalf("bad: %#v", out)
  1457  	}
  1458  	if out.ModifyIndex != 1001 {
  1459  		t.Fatalf("bad: %#v", out)
  1460  	}
  1461  	if out.Version != 1 {
  1462  		t.Fatalf("bad: %#v", out)
  1463  	}
  1464  
  1465  	index, err := state.Index("jobs")
  1466  	if err != nil {
  1467  		t.Fatalf("err: %v", err)
  1468  	}
  1469  	if index != 1001 {
  1470  		t.Fatalf("bad: %d", index)
  1471  	}
  1472  
  1473  	// Test the looking up the job by version returns the same results
  1474  	vout, err := state.JobByIDAndVersion(ws, job.Namespace, job.ID, 1)
  1475  	if err != nil {
  1476  		t.Fatalf("err: %v", err)
  1477  	}
  1478  
  1479  	if !reflect.DeepEqual(out, vout) {
  1480  		t.Fatalf("bad: %#v %#v", out, vout)
  1481  	}
  1482  
  1483  	// Test that the job summary remains the same if the job is updated but
  1484  	// count remains same
  1485  	summary, err := state.JobSummaryByID(ws, job.Namespace, job.ID)
  1486  	if err != nil {
  1487  		t.Fatalf("err: %v", err)
  1488  	}
  1489  	if summary == nil {
  1490  		t.Fatalf("nil summary")
  1491  	}
  1492  	if summary.JobID != job.ID {
  1493  		t.Fatalf("bad summary id: %v", summary.JobID)
  1494  	}
  1495  	_, ok := summary.Summary["web"]
  1496  	if !ok {
  1497  		t.Fatalf("nil summary for task group")
  1498  	}
  1499  
  1500  	// Check the job versions
  1501  	allVersions, err := state.JobVersionsByID(ws, job.Namespace, job.ID)
  1502  	if err != nil {
  1503  		t.Fatalf("err: %v", err)
  1504  	}
  1505  	if len(allVersions) != 2 {
  1506  		t.Fatalf("got %d; want 1", len(allVersions))
  1507  	}
  1508  
  1509  	if a := allVersions[0]; a.ID != job.ID || a.Version != 1 || !a.AllAtOnce {
  1510  		t.Fatalf("bad: %+v", a)
  1511  	}
  1512  	if a := allVersions[1]; a.ID != job.ID || a.Version != 0 || a.AllAtOnce {
  1513  		t.Fatalf("bad: %+v", a)
  1514  	}
  1515  
  1516  	if watchFired(ws) {
  1517  		t.Fatalf("bad")
  1518  	}
  1519  }
  1520  
  1521  func TestStateStore_UpdateUpsertJob_PeriodicJob(t *testing.T) {
  1522  	state := testStateStore(t)
  1523  	job := mock.PeriodicJob()
  1524  
  1525  	// Create a watchset so we can test that upsert fires the watch
  1526  	ws := memdb.NewWatchSet()
  1527  	_, err := state.JobByID(ws, job.Namespace, job.ID)
  1528  	if err != nil {
  1529  		t.Fatalf("bad: %v", err)
  1530  	}
  1531  
  1532  	if err := state.UpsertJob(1000, job); err != nil {
  1533  		t.Fatalf("err: %v", err)
  1534  	}
  1535  
  1536  	// Create a child and an evaluation
  1537  	job2 := job.Copy()
  1538  	job2.Periodic = nil
  1539  	job2.ID = fmt.Sprintf("%v/%s-1490635020", job.ID, structs.PeriodicLaunchSuffix)
  1540  	err = state.UpsertJob(1001, job2)
  1541  	if err != nil {
  1542  		t.Fatalf("err: %v", err)
  1543  	}
  1544  
  1545  	eval := mock.Eval()
  1546  	eval.JobID = job2.ID
  1547  	err = state.UpsertEvals(1002, []*structs.Evaluation{eval})
  1548  	if err != nil {
  1549  		t.Fatalf("err: %v", err)
  1550  	}
  1551  
  1552  	job3 := job.Copy()
  1553  	job3.TaskGroups[0].Tasks[0].Name = "new name"
  1554  	err = state.UpsertJob(1003, job3)
  1555  	if err != nil {
  1556  		t.Fatalf("err: %v", err)
  1557  	}
  1558  
  1559  	if !watchFired(ws) {
  1560  		t.Fatalf("bad")
  1561  	}
  1562  
  1563  	ws = memdb.NewWatchSet()
  1564  	out, err := state.JobByID(ws, job.Namespace, job.ID)
  1565  	if err != nil {
  1566  		t.Fatalf("err: %v", err)
  1567  	}
  1568  
  1569  	if s, e := out.Status, structs.JobStatusRunning; s != e {
  1570  		t.Fatalf("got status %v; want %v", s, e)
  1571  	}
  1572  
  1573  }
  1574  
  1575  func TestStateStore_UpsertJob_BadNamespace(t *testing.T) {
  1576  	assert := assert.New(t)
  1577  	state := testStateStore(t)
  1578  	job := mock.Job()
  1579  	job.Namespace = "foo"
  1580  
  1581  	err := state.UpsertJob(1000, job)
  1582  	assert.Contains(err.Error(), "nonexistent namespace")
  1583  
  1584  	ws := memdb.NewWatchSet()
  1585  	out, err := state.JobByID(ws, job.Namespace, job.ID)
  1586  	assert.Nil(err)
  1587  	assert.Nil(out)
  1588  }
  1589  
  1590  // Upsert a job that is the child of a parent job and ensures its summary gets
  1591  // updated.
  1592  func TestStateStore_UpsertJob_ChildJob(t *testing.T) {
  1593  	state := testStateStore(t)
  1594  
  1595  	// Create a watchset so we can test that upsert fires the watch
  1596  	parent := mock.Job()
  1597  	ws := memdb.NewWatchSet()
  1598  	_, err := state.JobByID(ws, parent.Namespace, parent.ID)
  1599  	if err != nil {
  1600  		t.Fatalf("bad: %v", err)
  1601  	}
  1602  
  1603  	if err := state.UpsertJob(1000, parent); err != nil {
  1604  		t.Fatalf("err: %v", err)
  1605  	}
  1606  
  1607  	child := mock.Job()
  1608  	child.ParentID = parent.ID
  1609  	if err := state.UpsertJob(1001, child); err != nil {
  1610  		t.Fatalf("err: %v", err)
  1611  	}
  1612  
  1613  	summary, err := state.JobSummaryByID(ws, parent.Namespace, parent.ID)
  1614  	if err != nil {
  1615  		t.Fatalf("err: %v", err)
  1616  	}
  1617  	if summary == nil {
  1618  		t.Fatalf("nil summary")
  1619  	}
  1620  	if summary.JobID != parent.ID {
  1621  		t.Fatalf("bad summary id: %v", parent.ID)
  1622  	}
  1623  	if summary.Children == nil {
  1624  		t.Fatalf("nil children summary")
  1625  	}
  1626  	if summary.Children.Pending != 1 || summary.Children.Running != 0 || summary.Children.Dead != 0 {
  1627  		t.Fatalf("bad children summary: %v", summary.Children)
  1628  	}
  1629  	if !watchFired(ws) {
  1630  		t.Fatalf("bad")
  1631  	}
  1632  }
  1633  
  1634  func TestStateStore_UpdateUpsertJob_JobVersion(t *testing.T) {
  1635  	state := testStateStore(t)
  1636  
  1637  	// Create a job and mark it as stable
  1638  	job := mock.Job()
  1639  	job.Stable = true
  1640  	job.Name = "0"
  1641  
  1642  	// Create a watchset so we can test that upsert fires the watch
  1643  	ws := memdb.NewWatchSet()
  1644  	_, err := state.JobVersionsByID(ws, job.Namespace, job.ID)
  1645  	if err != nil {
  1646  		t.Fatalf("bad: %v", err)
  1647  	}
  1648  
  1649  	if err := state.UpsertJob(1000, job); err != nil {
  1650  		t.Fatalf("err: %v", err)
  1651  	}
  1652  
  1653  	if !watchFired(ws) {
  1654  		t.Fatalf("bad")
  1655  	}
  1656  
  1657  	var finalJob *structs.Job
  1658  	for i := 1; i < 300; i++ {
  1659  		finalJob = mock.Job()
  1660  		finalJob.ID = job.ID
  1661  		finalJob.Name = fmt.Sprintf("%d", i)
  1662  		err = state.UpsertJob(uint64(1000+i), finalJob)
  1663  		if err != nil {
  1664  			t.Fatalf("err: %v", err)
  1665  		}
  1666  	}
  1667  
  1668  	ws = memdb.NewWatchSet()
  1669  	out, err := state.JobByID(ws, job.Namespace, job.ID)
  1670  	if err != nil {
  1671  		t.Fatalf("err: %v", err)
  1672  	}
  1673  
  1674  	if !reflect.DeepEqual(finalJob, out) {
  1675  		t.Fatalf("bad: %#v %#v", finalJob, out)
  1676  	}
  1677  
  1678  	if out.CreateIndex != 1000 {
  1679  		t.Fatalf("bad: %#v", out)
  1680  	}
  1681  	if out.ModifyIndex != 1299 {
  1682  		t.Fatalf("bad: %#v", out)
  1683  	}
  1684  	if out.Version != 299 {
  1685  		t.Fatalf("bad: %#v", out)
  1686  	}
  1687  
  1688  	index, err := state.Index("job_version")
  1689  	if err != nil {
  1690  		t.Fatalf("err: %v", err)
  1691  	}
  1692  	if index != 1299 {
  1693  		t.Fatalf("bad: %d", index)
  1694  	}
  1695  
  1696  	// Check the job versions
  1697  	allVersions, err := state.JobVersionsByID(ws, job.Namespace, job.ID)
  1698  	if err != nil {
  1699  		t.Fatalf("err: %v", err)
  1700  	}
  1701  	if len(allVersions) != structs.JobTrackedVersions {
  1702  		t.Fatalf("got %d; want %d", len(allVersions), structs.JobTrackedVersions)
  1703  	}
  1704  
  1705  	if a := allVersions[0]; a.ID != job.ID || a.Version != 299 || a.Name != "299" {
  1706  		t.Fatalf("bad: %+v", a)
  1707  	}
  1708  	if a := allVersions[1]; a.ID != job.ID || a.Version != 298 || a.Name != "298" {
  1709  		t.Fatalf("bad: %+v", a)
  1710  	}
  1711  
  1712  	// Ensure we didn't delete the stable job
  1713  	if a := allVersions[structs.JobTrackedVersions-1]; a.ID != job.ID ||
  1714  		a.Version != 0 || a.Name != "0" || !a.Stable {
  1715  		t.Fatalf("bad: %+v", a)
  1716  	}
  1717  
  1718  	if watchFired(ws) {
  1719  		t.Fatalf("bad")
  1720  	}
  1721  }
  1722  
  1723  func TestStateStore_DeleteJob_Job(t *testing.T) {
  1724  	state := testStateStore(t)
  1725  	job := mock.Job()
  1726  
  1727  	err := state.UpsertJob(1000, job)
  1728  	if err != nil {
  1729  		t.Fatalf("err: %v", err)
  1730  	}
  1731  
  1732  	// Create a watchset so we can test that delete fires the watch
  1733  	ws := memdb.NewWatchSet()
  1734  	if _, err := state.JobByID(ws, job.Namespace, job.ID); err != nil {
  1735  		t.Fatalf("bad: %v", err)
  1736  	}
  1737  
  1738  	err = state.DeleteJob(1001, job.Namespace, job.ID)
  1739  	if err != nil {
  1740  		t.Fatalf("err: %v", err)
  1741  	}
  1742  
  1743  	if !watchFired(ws) {
  1744  		t.Fatalf("bad")
  1745  	}
  1746  
  1747  	ws = memdb.NewWatchSet()
  1748  	out, err := state.JobByID(ws, job.Namespace, job.ID)
  1749  	if err != nil {
  1750  		t.Fatalf("err: %v", err)
  1751  	}
  1752  
  1753  	if out != nil {
  1754  		t.Fatalf("bad: %#v %#v", job, out)
  1755  	}
  1756  
  1757  	index, err := state.Index("jobs")
  1758  	if err != nil {
  1759  		t.Fatalf("err: %v", err)
  1760  	}
  1761  	if index != 1001 {
  1762  		t.Fatalf("bad: %d", index)
  1763  	}
  1764  
  1765  	summary, err := state.JobSummaryByID(ws, job.Namespace, job.ID)
  1766  	if err != nil {
  1767  		t.Fatalf("err: %v", err)
  1768  	}
  1769  	if summary != nil {
  1770  		t.Fatalf("expected summary to be nil, but got: %v", summary)
  1771  	}
  1772  
  1773  	index, err = state.Index("job_summary")
  1774  	if err != nil {
  1775  		t.Fatalf("err: %v", err)
  1776  	}
  1777  	if index != 1001 {
  1778  		t.Fatalf("bad: %d", index)
  1779  	}
  1780  
  1781  	versions, err := state.JobVersionsByID(ws, job.Namespace, job.ID)
  1782  	if err != nil {
  1783  		t.Fatalf("err: %v", err)
  1784  	}
  1785  	if len(versions) != 0 {
  1786  		t.Fatalf("expected no job versions")
  1787  	}
  1788  
  1789  	index, err = state.Index("job_summary")
  1790  	if err != nil {
  1791  		t.Fatalf("err: %v", err)
  1792  	}
  1793  	if index != 1001 {
  1794  		t.Fatalf("bad: %d", index)
  1795  	}
  1796  
  1797  	if watchFired(ws) {
  1798  		t.Fatalf("bad")
  1799  	}
  1800  }
  1801  
  1802  func TestStateStore_DeleteJobTxn_BatchDeletes(t *testing.T) {
  1803  	state := testStateStore(t)
  1804  
  1805  	const testJobCount = 10
  1806  	const jobVersionCount = 4
  1807  
  1808  	stateIndex := uint64(1000)
  1809  
  1810  	jobs := make([]*structs.Job, testJobCount)
  1811  	for i := 0; i < testJobCount; i++ {
  1812  		stateIndex++
  1813  		job := mock.BatchJob()
  1814  
  1815  		err := state.UpsertJob(stateIndex, job)
  1816  		require.NoError(t, err)
  1817  
  1818  		jobs[i] = job
  1819  
  1820  		// Create some versions
  1821  		for vi := 1; vi < jobVersionCount; vi++ {
  1822  			stateIndex++
  1823  
  1824  			job := job.Copy()
  1825  			job.TaskGroups[0].Tasks[0].Env = map[string]string{
  1826  				"Version": fmt.Sprintf("%d", vi),
  1827  			}
  1828  
  1829  			require.NoError(t, state.UpsertJob(stateIndex, job))
  1830  		}
  1831  	}
  1832  
  1833  	ws := memdb.NewWatchSet()
  1834  
  1835  	// Sanity check that jobs are present in DB
  1836  	job, err := state.JobByID(ws, jobs[0].Namespace, jobs[0].ID)
  1837  	require.NoError(t, err)
  1838  	require.Equal(t, jobs[0].ID, job.ID)
  1839  
  1840  	jobVersions, err := state.JobVersionsByID(ws, jobs[0].Namespace, jobs[0].ID)
  1841  	require.NoError(t, err)
  1842  	require.Equal(t, jobVersionCount, len(jobVersions))
  1843  
  1844  	// Actually delete
  1845  	const deletionIndex = uint64(10001)
  1846  	err = state.WithWriteTransaction(func(txn Txn) error {
  1847  		for i, job := range jobs {
  1848  			err := state.DeleteJobTxn(deletionIndex, job.Namespace, job.ID, txn)
  1849  			require.NoError(t, err, "failed at %d %e", i, err)
  1850  		}
  1851  		return nil
  1852  	})
  1853  	assert.NoError(t, err)
  1854  
  1855  	assert.True(t, watchFired(ws))
  1856  
  1857  	ws = memdb.NewWatchSet()
  1858  	out, err := state.JobByID(ws, jobs[0].Namespace, jobs[0].ID)
  1859  	require.NoError(t, err)
  1860  	require.Nil(t, out)
  1861  
  1862  	jobVersions, err = state.JobVersionsByID(ws, jobs[0].Namespace, jobs[0].ID)
  1863  	require.NoError(t, err)
  1864  	require.Empty(t, jobVersions)
  1865  
  1866  	index, err := state.Index("jobs")
  1867  	require.NoError(t, err)
  1868  	require.Equal(t, deletionIndex, index)
  1869  }
  1870  
  1871  func TestStateStore_DeleteJob_MultipleVersions(t *testing.T) {
  1872  	state := testStateStore(t)
  1873  	assert := assert.New(t)
  1874  
  1875  	// Create a job and mark it as stable
  1876  	job := mock.Job()
  1877  	job.Stable = true
  1878  	job.Priority = 0
  1879  
  1880  	// Create a watchset so we can test that upsert fires the watch
  1881  	ws := memdb.NewWatchSet()
  1882  	_, err := state.JobVersionsByID(ws, job.Namespace, job.ID)
  1883  	assert.Nil(err)
  1884  	assert.Nil(state.UpsertJob(1000, job))
  1885  	assert.True(watchFired(ws))
  1886  
  1887  	var finalJob *structs.Job
  1888  	for i := 1; i < 20; i++ {
  1889  		finalJob = mock.Job()
  1890  		finalJob.ID = job.ID
  1891  		finalJob.Priority = i
  1892  		assert.Nil(state.UpsertJob(uint64(1000+i), finalJob))
  1893  	}
  1894  
  1895  	assert.Nil(state.DeleteJob(1020, job.Namespace, job.ID))
  1896  	assert.True(watchFired(ws))
  1897  
  1898  	ws = memdb.NewWatchSet()
  1899  	out, err := state.JobByID(ws, job.Namespace, job.ID)
  1900  	assert.Nil(err)
  1901  	assert.Nil(out)
  1902  
  1903  	index, err := state.Index("jobs")
  1904  	assert.Nil(err)
  1905  	assert.EqualValues(1020, index)
  1906  
  1907  	summary, err := state.JobSummaryByID(ws, job.Namespace, job.ID)
  1908  	assert.Nil(err)
  1909  	assert.Nil(summary)
  1910  
  1911  	index, err = state.Index("job_version")
  1912  	assert.Nil(err)
  1913  	assert.EqualValues(1020, index)
  1914  
  1915  	versions, err := state.JobVersionsByID(ws, job.Namespace, job.ID)
  1916  	assert.Nil(err)
  1917  	assert.Len(versions, 0)
  1918  
  1919  	index, err = state.Index("job_summary")
  1920  	assert.Nil(err)
  1921  	assert.EqualValues(1020, index)
  1922  
  1923  	assert.False(watchFired(ws))
  1924  }
  1925  
  1926  func TestStateStore_DeleteJob_ChildJob(t *testing.T) {
  1927  	state := testStateStore(t)
  1928  
  1929  	parent := mock.Job()
  1930  	if err := state.UpsertJob(998, parent); err != nil {
  1931  		t.Fatalf("err: %v", err)
  1932  	}
  1933  
  1934  	child := mock.Job()
  1935  	child.ParentID = parent.ID
  1936  
  1937  	if err := state.UpsertJob(999, child); err != nil {
  1938  		t.Fatalf("err: %v", err)
  1939  	}
  1940  
  1941  	// Create a watchset so we can test that delete fires the watch
  1942  	ws := memdb.NewWatchSet()
  1943  	if _, err := state.JobSummaryByID(ws, parent.Namespace, parent.ID); err != nil {
  1944  		t.Fatalf("bad: %v", err)
  1945  	}
  1946  
  1947  	err := state.DeleteJob(1001, child.Namespace, child.ID)
  1948  	if err != nil {
  1949  		t.Fatalf("err: %v", err)
  1950  	}
  1951  	if !watchFired(ws) {
  1952  		t.Fatalf("bad")
  1953  	}
  1954  
  1955  	ws = memdb.NewWatchSet()
  1956  	summary, err := state.JobSummaryByID(ws, parent.Namespace, parent.ID)
  1957  	if err != nil {
  1958  		t.Fatalf("err: %v", err)
  1959  	}
  1960  	if summary == nil {
  1961  		t.Fatalf("nil summary")
  1962  	}
  1963  	if summary.JobID != parent.ID {
  1964  		t.Fatalf("bad summary id: %v", parent.ID)
  1965  	}
  1966  	if summary.Children == nil {
  1967  		t.Fatalf("nil children summary")
  1968  	}
  1969  	if summary.Children.Pending != 0 || summary.Children.Running != 0 || summary.Children.Dead != 1 {
  1970  		t.Fatalf("bad children summary: %v", summary.Children)
  1971  	}
  1972  	if watchFired(ws) {
  1973  		t.Fatalf("bad")
  1974  	}
  1975  }
  1976  
  1977  func TestStateStore_Jobs(t *testing.T) {
  1978  	state := testStateStore(t)
  1979  	var jobs []*structs.Job
  1980  
  1981  	for i := 0; i < 10; i++ {
  1982  		job := mock.Job()
  1983  		jobs = append(jobs, job)
  1984  
  1985  		err := state.UpsertJob(1000+uint64(i), job)
  1986  		if err != nil {
  1987  			t.Fatalf("err: %v", err)
  1988  		}
  1989  	}
  1990  
  1991  	ws := memdb.NewWatchSet()
  1992  	iter, err := state.Jobs(ws)
  1993  	if err != nil {
  1994  		t.Fatalf("err: %v", err)
  1995  	}
  1996  
  1997  	var out []*structs.Job
  1998  	for {
  1999  		raw := iter.Next()
  2000  		if raw == nil {
  2001  			break
  2002  		}
  2003  		out = append(out, raw.(*structs.Job))
  2004  	}
  2005  
  2006  	sort.Sort(JobIDSort(jobs))
  2007  	sort.Sort(JobIDSort(out))
  2008  
  2009  	if !reflect.DeepEqual(jobs, out) {
  2010  		t.Fatalf("bad: %#v %#v", jobs, out)
  2011  	}
  2012  	if watchFired(ws) {
  2013  		t.Fatalf("bad")
  2014  	}
  2015  }
  2016  
  2017  func TestStateStore_JobVersions(t *testing.T) {
  2018  	state := testStateStore(t)
  2019  	var jobs []*structs.Job
  2020  
  2021  	for i := 0; i < 10; i++ {
  2022  		job := mock.Job()
  2023  		jobs = append(jobs, job)
  2024  
  2025  		err := state.UpsertJob(1000+uint64(i), job)
  2026  		if err != nil {
  2027  			t.Fatalf("err: %v", err)
  2028  		}
  2029  	}
  2030  
  2031  	ws := memdb.NewWatchSet()
  2032  	iter, err := state.JobVersions(ws)
  2033  	if err != nil {
  2034  		t.Fatalf("err: %v", err)
  2035  	}
  2036  
  2037  	var out []*structs.Job
  2038  	for {
  2039  		raw := iter.Next()
  2040  		if raw == nil {
  2041  			break
  2042  		}
  2043  		out = append(out, raw.(*structs.Job))
  2044  	}
  2045  
  2046  	sort.Sort(JobIDSort(jobs))
  2047  	sort.Sort(JobIDSort(out))
  2048  
  2049  	if !reflect.DeepEqual(jobs, out) {
  2050  		t.Fatalf("bad: %#v %#v", jobs, out)
  2051  	}
  2052  	if watchFired(ws) {
  2053  		t.Fatalf("bad")
  2054  	}
  2055  }
  2056  
  2057  func TestStateStore_JobsByIDPrefix(t *testing.T) {
  2058  	state := testStateStore(t)
  2059  	job := mock.Job()
  2060  
  2061  	job.ID = "redis"
  2062  	err := state.UpsertJob(1000, job)
  2063  	if err != nil {
  2064  		t.Fatalf("err: %v", err)
  2065  	}
  2066  
  2067  	ws := memdb.NewWatchSet()
  2068  	iter, err := state.JobsByIDPrefix(ws, job.Namespace, job.ID)
  2069  	if err != nil {
  2070  		t.Fatalf("err: %v", err)
  2071  	}
  2072  
  2073  	gatherJobs := func(iter memdb.ResultIterator) []*structs.Job {
  2074  		var jobs []*structs.Job
  2075  		for {
  2076  			raw := iter.Next()
  2077  			if raw == nil {
  2078  				break
  2079  			}
  2080  			jobs = append(jobs, raw.(*structs.Job))
  2081  		}
  2082  		return jobs
  2083  	}
  2084  
  2085  	jobs := gatherJobs(iter)
  2086  	if len(jobs) != 1 {
  2087  		t.Fatalf("err: %v", err)
  2088  	}
  2089  
  2090  	iter, err = state.JobsByIDPrefix(ws, job.Namespace, "re")
  2091  	if err != nil {
  2092  		t.Fatalf("err: %v", err)
  2093  	}
  2094  
  2095  	jobs = gatherJobs(iter)
  2096  	if len(jobs) != 1 {
  2097  		t.Fatalf("err: %v", err)
  2098  	}
  2099  	if watchFired(ws) {
  2100  		t.Fatalf("bad")
  2101  	}
  2102  
  2103  	job = mock.Job()
  2104  	job.ID = "riak"
  2105  	err = state.UpsertJob(1001, job)
  2106  	if err != nil {
  2107  		t.Fatalf("err: %v", err)
  2108  	}
  2109  
  2110  	if !watchFired(ws) {
  2111  		t.Fatalf("bad")
  2112  	}
  2113  
  2114  	ws = memdb.NewWatchSet()
  2115  	iter, err = state.JobsByIDPrefix(ws, job.Namespace, "r")
  2116  	if err != nil {
  2117  		t.Fatalf("err: %v", err)
  2118  	}
  2119  
  2120  	jobs = gatherJobs(iter)
  2121  	if len(jobs) != 2 {
  2122  		t.Fatalf("err: %v", err)
  2123  	}
  2124  
  2125  	iter, err = state.JobsByIDPrefix(ws, job.Namespace, "ri")
  2126  	if err != nil {
  2127  		t.Fatalf("err: %v", err)
  2128  	}
  2129  
  2130  	jobs = gatherJobs(iter)
  2131  	if len(jobs) != 1 {
  2132  		t.Fatalf("err: %v", err)
  2133  	}
  2134  	if watchFired(ws) {
  2135  		t.Fatalf("bad")
  2136  	}
  2137  }
  2138  
  2139  func TestStateStore_JobsByPeriodic(t *testing.T) {
  2140  	state := testStateStore(t)
  2141  	var periodic, nonPeriodic []*structs.Job
  2142  
  2143  	for i := 0; i < 10; i++ {
  2144  		job := mock.Job()
  2145  		nonPeriodic = append(nonPeriodic, job)
  2146  
  2147  		err := state.UpsertJob(1000+uint64(i), job)
  2148  		if err != nil {
  2149  			t.Fatalf("err: %v", err)
  2150  		}
  2151  	}
  2152  
  2153  	for i := 0; i < 10; i++ {
  2154  		job := mock.PeriodicJob()
  2155  		periodic = append(periodic, job)
  2156  
  2157  		err := state.UpsertJob(2000+uint64(i), job)
  2158  		if err != nil {
  2159  			t.Fatalf("err: %v", err)
  2160  		}
  2161  	}
  2162  
  2163  	ws := memdb.NewWatchSet()
  2164  	iter, err := state.JobsByPeriodic(ws, true)
  2165  	if err != nil {
  2166  		t.Fatalf("err: %v", err)
  2167  	}
  2168  
  2169  	var outPeriodic []*structs.Job
  2170  	for {
  2171  		raw := iter.Next()
  2172  		if raw == nil {
  2173  			break
  2174  		}
  2175  		outPeriodic = append(outPeriodic, raw.(*structs.Job))
  2176  	}
  2177  
  2178  	iter, err = state.JobsByPeriodic(ws, false)
  2179  	if err != nil {
  2180  		t.Fatalf("err: %v", err)
  2181  	}
  2182  
  2183  	var outNonPeriodic []*structs.Job
  2184  	for {
  2185  		raw := iter.Next()
  2186  		if raw == nil {
  2187  			break
  2188  		}
  2189  		outNonPeriodic = append(outNonPeriodic, raw.(*structs.Job))
  2190  	}
  2191  
  2192  	sort.Sort(JobIDSort(periodic))
  2193  	sort.Sort(JobIDSort(nonPeriodic))
  2194  	sort.Sort(JobIDSort(outPeriodic))
  2195  	sort.Sort(JobIDSort(outNonPeriodic))
  2196  
  2197  	if !reflect.DeepEqual(periodic, outPeriodic) {
  2198  		t.Fatalf("bad: %#v %#v", periodic, outPeriodic)
  2199  	}
  2200  
  2201  	if !reflect.DeepEqual(nonPeriodic, outNonPeriodic) {
  2202  		t.Fatalf("bad: %#v %#v", nonPeriodic, outNonPeriodic)
  2203  	}
  2204  	if watchFired(ws) {
  2205  		t.Fatalf("bad")
  2206  	}
  2207  }
  2208  
  2209  func TestStateStore_JobsByScheduler(t *testing.T) {
  2210  	state := testStateStore(t)
  2211  	var serviceJobs []*structs.Job
  2212  	var sysJobs []*structs.Job
  2213  
  2214  	for i := 0; i < 10; i++ {
  2215  		job := mock.Job()
  2216  		serviceJobs = append(serviceJobs, job)
  2217  
  2218  		err := state.UpsertJob(1000+uint64(i), job)
  2219  		if err != nil {
  2220  			t.Fatalf("err: %v", err)
  2221  		}
  2222  	}
  2223  
  2224  	for i := 0; i < 10; i++ {
  2225  		job := mock.SystemJob()
  2226  		job.Status = structs.JobStatusRunning
  2227  		sysJobs = append(sysJobs, job)
  2228  
  2229  		err := state.UpsertJob(2000+uint64(i), job)
  2230  		if err != nil {
  2231  			t.Fatalf("err: %v", err)
  2232  		}
  2233  	}
  2234  
  2235  	ws := memdb.NewWatchSet()
  2236  	iter, err := state.JobsByScheduler(ws, "service")
  2237  	if err != nil {
  2238  		t.Fatalf("err: %v", err)
  2239  	}
  2240  
  2241  	var outService []*structs.Job
  2242  	for {
  2243  		raw := iter.Next()
  2244  		if raw == nil {
  2245  			break
  2246  		}
  2247  		outService = append(outService, raw.(*structs.Job))
  2248  	}
  2249  
  2250  	iter, err = state.JobsByScheduler(ws, "system")
  2251  	if err != nil {
  2252  		t.Fatalf("err: %v", err)
  2253  	}
  2254  
  2255  	var outSystem []*structs.Job
  2256  	for {
  2257  		raw := iter.Next()
  2258  		if raw == nil {
  2259  			break
  2260  		}
  2261  		outSystem = append(outSystem, raw.(*structs.Job))
  2262  	}
  2263  
  2264  	sort.Sort(JobIDSort(serviceJobs))
  2265  	sort.Sort(JobIDSort(sysJobs))
  2266  	sort.Sort(JobIDSort(outService))
  2267  	sort.Sort(JobIDSort(outSystem))
  2268  
  2269  	if !reflect.DeepEqual(serviceJobs, outService) {
  2270  		t.Fatalf("bad: %#v %#v", serviceJobs, outService)
  2271  	}
  2272  
  2273  	if !reflect.DeepEqual(sysJobs, outSystem) {
  2274  		t.Fatalf("bad: %#v %#v", sysJobs, outSystem)
  2275  	}
  2276  	if watchFired(ws) {
  2277  		t.Fatalf("bad")
  2278  	}
  2279  }
  2280  
  2281  func TestStateStore_JobsByGC(t *testing.T) {
  2282  	state := testStateStore(t)
  2283  	gc, nonGc := make(map[string]struct{}), make(map[string]struct{})
  2284  
  2285  	for i := 0; i < 20; i++ {
  2286  		var job *structs.Job
  2287  		if i%2 == 0 {
  2288  			job = mock.Job()
  2289  		} else {
  2290  			job = mock.PeriodicJob()
  2291  		}
  2292  		nonGc[job.ID] = struct{}{}
  2293  
  2294  		if err := state.UpsertJob(1000+uint64(i), job); err != nil {
  2295  			t.Fatalf("err: %v", err)
  2296  		}
  2297  	}
  2298  
  2299  	for i := 0; i < 20; i += 2 {
  2300  		job := mock.Job()
  2301  		job.Type = structs.JobTypeBatch
  2302  		gc[job.ID] = struct{}{}
  2303  
  2304  		if err := state.UpsertJob(2000+uint64(i), job); err != nil {
  2305  			t.Fatalf("err: %v", err)
  2306  		}
  2307  
  2308  		// Create an eval for it
  2309  		eval := mock.Eval()
  2310  		eval.JobID = job.ID
  2311  		eval.Status = structs.EvalStatusComplete
  2312  		if err := state.UpsertEvals(2000+uint64(i+1), []*structs.Evaluation{eval}); err != nil {
  2313  			t.Fatalf("err: %v", err)
  2314  		}
  2315  
  2316  	}
  2317  
  2318  	ws := memdb.NewWatchSet()
  2319  	iter, err := state.JobsByGC(ws, true)
  2320  	if err != nil {
  2321  		t.Fatalf("err: %v", err)
  2322  	}
  2323  
  2324  	outGc := make(map[string]struct{})
  2325  	for i := iter.Next(); i != nil; i = iter.Next() {
  2326  		j := i.(*structs.Job)
  2327  		outGc[j.ID] = struct{}{}
  2328  	}
  2329  
  2330  	iter, err = state.JobsByGC(ws, false)
  2331  	if err != nil {
  2332  		t.Fatalf("err: %v", err)
  2333  	}
  2334  
  2335  	outNonGc := make(map[string]struct{})
  2336  	for i := iter.Next(); i != nil; i = iter.Next() {
  2337  		j := i.(*structs.Job)
  2338  		outNonGc[j.ID] = struct{}{}
  2339  	}
  2340  
  2341  	if !reflect.DeepEqual(gc, outGc) {
  2342  		t.Fatalf("bad: %#v %#v", gc, outGc)
  2343  	}
  2344  
  2345  	if !reflect.DeepEqual(nonGc, outNonGc) {
  2346  		t.Fatalf("bad: %#v %#v", nonGc, outNonGc)
  2347  	}
  2348  	if watchFired(ws) {
  2349  		t.Fatalf("bad")
  2350  	}
  2351  }
  2352  
  2353  func TestStateStore_RestoreJob(t *testing.T) {
  2354  	state := testStateStore(t)
  2355  	job := mock.Job()
  2356  
  2357  	restore, err := state.Restore()
  2358  	if err != nil {
  2359  		t.Fatalf("err: %v", err)
  2360  	}
  2361  
  2362  	err = restore.JobRestore(job)
  2363  	if err != nil {
  2364  		t.Fatalf("err: %v", err)
  2365  	}
  2366  	restore.Commit()
  2367  
  2368  	ws := memdb.NewWatchSet()
  2369  	out, err := state.JobByID(ws, job.Namespace, job.ID)
  2370  	if err != nil {
  2371  		t.Fatalf("err: %v", err)
  2372  	}
  2373  
  2374  	if !reflect.DeepEqual(out, job) {
  2375  		t.Fatalf("Bad: %#v %#v", out, job)
  2376  	}
  2377  }
  2378  
  2379  func TestStateStore_UpsertPeriodicLaunch(t *testing.T) {
  2380  	state := testStateStore(t)
  2381  	job := mock.Job()
  2382  	launch := &structs.PeriodicLaunch{
  2383  		ID:        job.ID,
  2384  		Namespace: job.Namespace,
  2385  		Launch:    time.Now(),
  2386  	}
  2387  
  2388  	// Create a watchset so we can test that upsert fires the watch
  2389  	ws := memdb.NewWatchSet()
  2390  	if _, err := state.PeriodicLaunchByID(ws, job.Namespace, launch.ID); err != nil {
  2391  		t.Fatalf("bad: %v", err)
  2392  	}
  2393  
  2394  	err := state.UpsertPeriodicLaunch(1000, launch)
  2395  	if err != nil {
  2396  		t.Fatalf("err: %v", err)
  2397  	}
  2398  
  2399  	if !watchFired(ws) {
  2400  		t.Fatalf("bad")
  2401  	}
  2402  
  2403  	ws = memdb.NewWatchSet()
  2404  	out, err := state.PeriodicLaunchByID(ws, job.Namespace, job.ID)
  2405  	if err != nil {
  2406  		t.Fatalf("err: %v", err)
  2407  	}
  2408  	if out.CreateIndex != 1000 {
  2409  		t.Fatalf("bad: %#v", out)
  2410  	}
  2411  	if out.ModifyIndex != 1000 {
  2412  		t.Fatalf("bad: %#v", out)
  2413  	}
  2414  
  2415  	if !reflect.DeepEqual(launch, out) {
  2416  		t.Fatalf("bad: %#v %#v", job, out)
  2417  	}
  2418  
  2419  	index, err := state.Index("periodic_launch")
  2420  	if err != nil {
  2421  		t.Fatalf("err: %v", err)
  2422  	}
  2423  	if index != 1000 {
  2424  		t.Fatalf("bad: %d", index)
  2425  	}
  2426  
  2427  	if watchFired(ws) {
  2428  		t.Fatalf("bad")
  2429  	}
  2430  }
  2431  
  2432  func TestStateStore_UpdateUpsertPeriodicLaunch(t *testing.T) {
  2433  	state := testStateStore(t)
  2434  	job := mock.Job()
  2435  	launch := &structs.PeriodicLaunch{
  2436  		ID:        job.ID,
  2437  		Namespace: job.Namespace,
  2438  		Launch:    time.Now(),
  2439  	}
  2440  
  2441  	err := state.UpsertPeriodicLaunch(1000, launch)
  2442  	if err != nil {
  2443  		t.Fatalf("err: %v", err)
  2444  	}
  2445  
  2446  	// Create a watchset so we can test that upsert fires the watch
  2447  	ws := memdb.NewWatchSet()
  2448  	if _, err := state.PeriodicLaunchByID(ws, job.Namespace, launch.ID); err != nil {
  2449  		t.Fatalf("bad: %v", err)
  2450  	}
  2451  
  2452  	launch2 := &structs.PeriodicLaunch{
  2453  		ID:        job.ID,
  2454  		Namespace: job.Namespace,
  2455  		Launch:    launch.Launch.Add(1 * time.Second),
  2456  	}
  2457  	err = state.UpsertPeriodicLaunch(1001, launch2)
  2458  	if err != nil {
  2459  		t.Fatalf("err: %v", err)
  2460  	}
  2461  
  2462  	if !watchFired(ws) {
  2463  		t.Fatalf("bad")
  2464  	}
  2465  
  2466  	ws = memdb.NewWatchSet()
  2467  	out, err := state.PeriodicLaunchByID(ws, job.Namespace, job.ID)
  2468  	if err != nil {
  2469  		t.Fatalf("err: %v", err)
  2470  	}
  2471  	if out.CreateIndex != 1000 {
  2472  		t.Fatalf("bad: %#v", out)
  2473  	}
  2474  	if out.ModifyIndex != 1001 {
  2475  		t.Fatalf("bad: %#v", out)
  2476  	}
  2477  
  2478  	if !reflect.DeepEqual(launch2, out) {
  2479  		t.Fatalf("bad: %#v %#v", launch2, out)
  2480  	}
  2481  
  2482  	index, err := state.Index("periodic_launch")
  2483  	if err != nil {
  2484  		t.Fatalf("err: %v", err)
  2485  	}
  2486  	if index != 1001 {
  2487  		t.Fatalf("bad: %d", index)
  2488  	}
  2489  
  2490  	if watchFired(ws) {
  2491  		t.Fatalf("bad")
  2492  	}
  2493  }
  2494  
  2495  func TestStateStore_DeletePeriodicLaunch(t *testing.T) {
  2496  	state := testStateStore(t)
  2497  	job := mock.Job()
  2498  	launch := &structs.PeriodicLaunch{
  2499  		ID:        job.ID,
  2500  		Namespace: job.Namespace,
  2501  		Launch:    time.Now(),
  2502  	}
  2503  
  2504  	err := state.UpsertPeriodicLaunch(1000, launch)
  2505  	if err != nil {
  2506  		t.Fatalf("err: %v", err)
  2507  	}
  2508  
  2509  	// Create a watchset so we can test that delete fires the watch
  2510  	ws := memdb.NewWatchSet()
  2511  	if _, err := state.PeriodicLaunchByID(ws, job.Namespace, launch.ID); err != nil {
  2512  		t.Fatalf("bad: %v", err)
  2513  	}
  2514  
  2515  	err = state.DeletePeriodicLaunch(1001, launch.Namespace, launch.ID)
  2516  	if err != nil {
  2517  		t.Fatalf("err: %v", err)
  2518  	}
  2519  
  2520  	if !watchFired(ws) {
  2521  		t.Fatalf("bad")
  2522  	}
  2523  
  2524  	ws = memdb.NewWatchSet()
  2525  	out, err := state.PeriodicLaunchByID(ws, job.Namespace, job.ID)
  2526  	if err != nil {
  2527  		t.Fatalf("err: %v", err)
  2528  	}
  2529  
  2530  	if out != nil {
  2531  		t.Fatalf("bad: %#v %#v", job, out)
  2532  	}
  2533  
  2534  	index, err := state.Index("periodic_launch")
  2535  	if err != nil {
  2536  		t.Fatalf("err: %v", err)
  2537  	}
  2538  	if index != 1001 {
  2539  		t.Fatalf("bad: %d", index)
  2540  	}
  2541  
  2542  	if watchFired(ws) {
  2543  		t.Fatalf("bad")
  2544  	}
  2545  }
  2546  
  2547  func TestStateStore_PeriodicLaunches(t *testing.T) {
  2548  	state := testStateStore(t)
  2549  	var launches []*structs.PeriodicLaunch
  2550  
  2551  	for i := 0; i < 10; i++ {
  2552  		job := mock.Job()
  2553  		launch := &structs.PeriodicLaunch{
  2554  			ID:        job.ID,
  2555  			Namespace: job.Namespace,
  2556  			Launch:    time.Now(),
  2557  		}
  2558  		launches = append(launches, launch)
  2559  
  2560  		err := state.UpsertPeriodicLaunch(1000+uint64(i), launch)
  2561  		if err != nil {
  2562  			t.Fatalf("err: %v", err)
  2563  		}
  2564  	}
  2565  
  2566  	ws := memdb.NewWatchSet()
  2567  	iter, err := state.PeriodicLaunches(ws)
  2568  	if err != nil {
  2569  		t.Fatalf("err: %v", err)
  2570  	}
  2571  
  2572  	out := make(map[string]*structs.PeriodicLaunch, 10)
  2573  	for {
  2574  		raw := iter.Next()
  2575  		if raw == nil {
  2576  			break
  2577  		}
  2578  		launch := raw.(*structs.PeriodicLaunch)
  2579  		if _, ok := out[launch.ID]; ok {
  2580  			t.Fatalf("duplicate: %v", launch.ID)
  2581  		}
  2582  
  2583  		out[launch.ID] = launch
  2584  	}
  2585  
  2586  	for _, launch := range launches {
  2587  		l, ok := out[launch.ID]
  2588  		if !ok {
  2589  			t.Fatalf("bad %v", launch.ID)
  2590  		}
  2591  
  2592  		if !reflect.DeepEqual(launch, l) {
  2593  			t.Fatalf("bad: %#v %#v", launch, l)
  2594  		}
  2595  
  2596  		delete(out, launch.ID)
  2597  	}
  2598  
  2599  	if len(out) != 0 {
  2600  		t.Fatalf("leftover: %#v", out)
  2601  	}
  2602  
  2603  	if watchFired(ws) {
  2604  		t.Fatalf("bad")
  2605  	}
  2606  }
  2607  
  2608  func TestStateStore_RestorePeriodicLaunch(t *testing.T) {
  2609  	state := testStateStore(t)
  2610  	job := mock.Job()
  2611  	launch := &structs.PeriodicLaunch{
  2612  		ID:        job.ID,
  2613  		Namespace: job.Namespace,
  2614  		Launch:    time.Now(),
  2615  	}
  2616  
  2617  	restore, err := state.Restore()
  2618  	if err != nil {
  2619  		t.Fatalf("err: %v", err)
  2620  	}
  2621  
  2622  	err = restore.PeriodicLaunchRestore(launch)
  2623  	if err != nil {
  2624  		t.Fatalf("err: %v", err)
  2625  	}
  2626  	restore.Commit()
  2627  
  2628  	ws := memdb.NewWatchSet()
  2629  	out, err := state.PeriodicLaunchByID(ws, job.Namespace, job.ID)
  2630  	if err != nil {
  2631  		t.Fatalf("err: %v", err)
  2632  	}
  2633  
  2634  	if !reflect.DeepEqual(out, launch) {
  2635  		t.Fatalf("Bad: %#v %#v", out, job)
  2636  	}
  2637  
  2638  	if watchFired(ws) {
  2639  		t.Fatalf("bad")
  2640  	}
  2641  }
  2642  
  2643  func TestStateStore_RestoreJobVersion(t *testing.T) {
  2644  	state := testStateStore(t)
  2645  	job := mock.Job()
  2646  
  2647  	restore, err := state.Restore()
  2648  	if err != nil {
  2649  		t.Fatalf("err: %v", err)
  2650  	}
  2651  
  2652  	err = restore.JobVersionRestore(job)
  2653  	if err != nil {
  2654  		t.Fatalf("err: %v", err)
  2655  	}
  2656  	restore.Commit()
  2657  
  2658  	ws := memdb.NewWatchSet()
  2659  	out, err := state.JobByIDAndVersion(ws, job.Namespace, job.ID, job.Version)
  2660  	if err != nil {
  2661  		t.Fatalf("err: %v", err)
  2662  	}
  2663  
  2664  	if !reflect.DeepEqual(out, job) {
  2665  		t.Fatalf("Bad: %#v %#v", out, job)
  2666  	}
  2667  
  2668  	if watchFired(ws) {
  2669  		t.Fatalf("bad")
  2670  	}
  2671  }
  2672  
  2673  func TestStateStore_RestoreDeployment(t *testing.T) {
  2674  	state := testStateStore(t)
  2675  	d := mock.Deployment()
  2676  
  2677  	restore, err := state.Restore()
  2678  	if err != nil {
  2679  		t.Fatalf("err: %v", err)
  2680  	}
  2681  
  2682  	err = restore.DeploymentRestore(d)
  2683  	if err != nil {
  2684  		t.Fatalf("err: %v", err)
  2685  	}
  2686  	restore.Commit()
  2687  
  2688  	ws := memdb.NewWatchSet()
  2689  	out, err := state.DeploymentByID(ws, d.ID)
  2690  	if err != nil {
  2691  		t.Fatalf("err: %v", err)
  2692  	}
  2693  
  2694  	if !reflect.DeepEqual(out, d) {
  2695  		t.Fatalf("Bad: %#v %#v", out, d)
  2696  	}
  2697  
  2698  	if watchFired(ws) {
  2699  		t.Fatalf("bad")
  2700  	}
  2701  }
  2702  
  2703  func TestStateStore_RestoreJobSummary(t *testing.T) {
  2704  	state := testStateStore(t)
  2705  	job := mock.Job()
  2706  	jobSummary := &structs.JobSummary{
  2707  		JobID:     job.ID,
  2708  		Namespace: job.Namespace,
  2709  		Summary: map[string]structs.TaskGroupSummary{
  2710  			"web": {
  2711  				Starting: 10,
  2712  			},
  2713  		},
  2714  	}
  2715  	restore, err := state.Restore()
  2716  	if err != nil {
  2717  		t.Fatalf("err: %v", err)
  2718  	}
  2719  
  2720  	err = restore.JobSummaryRestore(jobSummary)
  2721  	if err != nil {
  2722  		t.Fatalf("err: %v", err)
  2723  	}
  2724  	restore.Commit()
  2725  
  2726  	ws := memdb.NewWatchSet()
  2727  	out, err := state.JobSummaryByID(ws, job.Namespace, job.ID)
  2728  	if err != nil {
  2729  		t.Fatalf("err: %v", err)
  2730  	}
  2731  
  2732  	if !reflect.DeepEqual(out, jobSummary) {
  2733  		t.Fatalf("Bad: %#v %#v", out, jobSummary)
  2734  	}
  2735  }
  2736  
  2737  func TestStateStore_Indexes(t *testing.T) {
  2738  	state := testStateStore(t)
  2739  	node := mock.Node()
  2740  
  2741  	err := state.UpsertNode(1000, node)
  2742  	if err != nil {
  2743  		t.Fatalf("err: %v", err)
  2744  	}
  2745  
  2746  	iter, err := state.Indexes()
  2747  	if err != nil {
  2748  		t.Fatalf("err: %v", err)
  2749  	}
  2750  
  2751  	var out []*IndexEntry
  2752  	for {
  2753  		raw := iter.Next()
  2754  		if raw == nil {
  2755  			break
  2756  		}
  2757  		out = append(out, raw.(*IndexEntry))
  2758  	}
  2759  
  2760  	expect := &IndexEntry{"nodes", 1000}
  2761  	if l := len(out); l != 1 && l != 2 {
  2762  		t.Fatalf("unexpected number of index entries: %v", out)
  2763  	}
  2764  
  2765  	for _, index := range out {
  2766  		if index.Key != expect.Key {
  2767  			continue
  2768  		}
  2769  		if index.Value != expect.Value {
  2770  			t.Fatalf("bad index; got %d; want %d", index.Value, expect.Value)
  2771  		}
  2772  
  2773  		// We matched
  2774  		return
  2775  	}
  2776  
  2777  	t.Fatal("did not find expected index entry")
  2778  }
  2779  
  2780  func TestStateStore_LatestIndex(t *testing.T) {
  2781  	state := testStateStore(t)
  2782  
  2783  	if err := state.UpsertNode(1000, mock.Node()); err != nil {
  2784  		t.Fatalf("err: %v", err)
  2785  	}
  2786  
  2787  	exp := uint64(2000)
  2788  	if err := state.UpsertJob(exp, mock.Job()); err != nil {
  2789  		t.Fatalf("err: %v", err)
  2790  	}
  2791  
  2792  	latest, err := state.LatestIndex()
  2793  	if err != nil {
  2794  		t.Fatalf("err: %v", err)
  2795  	}
  2796  
  2797  	if latest != exp {
  2798  		t.Fatalf("LatestIndex() returned %d; want %d", latest, exp)
  2799  	}
  2800  }
  2801  
  2802  func TestStateStore_RestoreIndex(t *testing.T) {
  2803  	state := testStateStore(t)
  2804  
  2805  	restore, err := state.Restore()
  2806  	if err != nil {
  2807  		t.Fatalf("err: %v", err)
  2808  	}
  2809  
  2810  	index := &IndexEntry{"jobs", 1000}
  2811  	err = restore.IndexRestore(index)
  2812  	if err != nil {
  2813  		t.Fatalf("err: %v", err)
  2814  	}
  2815  
  2816  	restore.Commit()
  2817  
  2818  	out, err := state.Index("jobs")
  2819  	if err != nil {
  2820  		t.Fatalf("err: %v", err)
  2821  	}
  2822  
  2823  	if out != 1000 {
  2824  		t.Fatalf("Bad: %#v %#v", out, 1000)
  2825  	}
  2826  }
  2827  
  2828  func TestStateStore_UpsertEvals_Eval(t *testing.T) {
  2829  	state := testStateStore(t)
  2830  	eval := mock.Eval()
  2831  
  2832  	// Create a watchset so we can test that upsert fires the watch
  2833  	ws := memdb.NewWatchSet()
  2834  	if _, err := state.EvalByID(ws, eval.ID); err != nil {
  2835  		t.Fatalf("bad: %v", err)
  2836  	}
  2837  
  2838  	err := state.UpsertEvals(1000, []*structs.Evaluation{eval})
  2839  	if err != nil {
  2840  		t.Fatalf("err: %v", err)
  2841  	}
  2842  
  2843  	if !watchFired(ws) {
  2844  		t.Fatalf("bad")
  2845  	}
  2846  
  2847  	ws = memdb.NewWatchSet()
  2848  	out, err := state.EvalByID(ws, eval.ID)
  2849  	if err != nil {
  2850  		t.Fatalf("err: %v", err)
  2851  	}
  2852  
  2853  	if !reflect.DeepEqual(eval, out) {
  2854  		t.Fatalf("bad: %#v %#v", eval, out)
  2855  	}
  2856  
  2857  	index, err := state.Index("evals")
  2858  	if err != nil {
  2859  		t.Fatalf("err: %v", err)
  2860  	}
  2861  	if index != 1000 {
  2862  		t.Fatalf("bad: %d", index)
  2863  	}
  2864  
  2865  	if watchFired(ws) {
  2866  		t.Fatalf("bad")
  2867  	}
  2868  }
  2869  
  2870  func TestStateStore_UpsertEvals_CancelBlocked(t *testing.T) {
  2871  	state := testStateStore(t)
  2872  
  2873  	// Create two blocked evals for the same job
  2874  	j := "test-job"
  2875  	b1, b2 := mock.Eval(), mock.Eval()
  2876  	b1.JobID = j
  2877  	b1.Status = structs.EvalStatusBlocked
  2878  	b2.JobID = j
  2879  	b2.Status = structs.EvalStatusBlocked
  2880  
  2881  	err := state.UpsertEvals(999, []*structs.Evaluation{b1, b2})
  2882  	if err != nil {
  2883  		t.Fatalf("err: %v", err)
  2884  	}
  2885  
  2886  	// Create one complete and successful eval for the job
  2887  	eval := mock.Eval()
  2888  	eval.JobID = j
  2889  	eval.Status = structs.EvalStatusComplete
  2890  
  2891  	// Create a watchset so we can test that the upsert of the complete eval
  2892  	// fires the watch
  2893  	ws := memdb.NewWatchSet()
  2894  	if _, err := state.EvalByID(ws, b1.ID); err != nil {
  2895  		t.Fatalf("bad: %v", err)
  2896  	}
  2897  	if _, err := state.EvalByID(ws, b2.ID); err != nil {
  2898  		t.Fatalf("bad: %v", err)
  2899  	}
  2900  
  2901  	if err := state.UpsertEvals(1000, []*structs.Evaluation{eval}); err != nil {
  2902  		t.Fatalf("err: %v", err)
  2903  	}
  2904  
  2905  	if !watchFired(ws) {
  2906  		t.Fatalf("bad")
  2907  	}
  2908  
  2909  	ws = memdb.NewWatchSet()
  2910  	out, err := state.EvalByID(ws, eval.ID)
  2911  	if err != nil {
  2912  		t.Fatalf("err: %v", err)
  2913  	}
  2914  
  2915  	if !reflect.DeepEqual(eval, out) {
  2916  		t.Fatalf("bad: %#v %#v", eval, out)
  2917  	}
  2918  
  2919  	index, err := state.Index("evals")
  2920  	if err != nil {
  2921  		t.Fatalf("err: %v", err)
  2922  	}
  2923  	if index != 1000 {
  2924  		t.Fatalf("bad: %d", index)
  2925  	}
  2926  
  2927  	// Get b1/b2 and check they are cancelled
  2928  	out1, err := state.EvalByID(ws, b1.ID)
  2929  	if err != nil {
  2930  		t.Fatalf("err: %v", err)
  2931  	}
  2932  
  2933  	out2, err := state.EvalByID(ws, b2.ID)
  2934  	if err != nil {
  2935  		t.Fatalf("err: %v", err)
  2936  	}
  2937  
  2938  	if out1.Status != structs.EvalStatusCancelled || out2.Status != structs.EvalStatusCancelled {
  2939  		t.Fatalf("bad: %#v %#v", out1, out2)
  2940  	}
  2941  
  2942  	if watchFired(ws) {
  2943  		t.Fatalf("bad")
  2944  	}
  2945  }
  2946  
  2947  func TestStateStore_Update_UpsertEvals_Eval(t *testing.T) {
  2948  	state := testStateStore(t)
  2949  	eval := mock.Eval()
  2950  
  2951  	err := state.UpsertEvals(1000, []*structs.Evaluation{eval})
  2952  	if err != nil {
  2953  		t.Fatalf("err: %v", err)
  2954  	}
  2955  
  2956  	// Create a watchset so we can test that delete fires the watch
  2957  	ws := memdb.NewWatchSet()
  2958  	ws2 := memdb.NewWatchSet()
  2959  	if _, err := state.EvalByID(ws, eval.ID); err != nil {
  2960  		t.Fatalf("bad: %v", err)
  2961  	}
  2962  
  2963  	if _, err := state.EvalsByJob(ws2, eval.Namespace, eval.JobID); err != nil {
  2964  		t.Fatalf("bad: %v", err)
  2965  	}
  2966  
  2967  	eval2 := mock.Eval()
  2968  	eval2.ID = eval.ID
  2969  	eval2.JobID = eval.JobID
  2970  	err = state.UpsertEvals(1001, []*structs.Evaluation{eval2})
  2971  	if err != nil {
  2972  		t.Fatalf("err: %v", err)
  2973  	}
  2974  
  2975  	if !watchFired(ws) {
  2976  		t.Fatalf("bad")
  2977  	}
  2978  	if !watchFired(ws2) {
  2979  		t.Fatalf("bad")
  2980  	}
  2981  
  2982  	ws = memdb.NewWatchSet()
  2983  	out, err := state.EvalByID(ws, eval.ID)
  2984  	if err != nil {
  2985  		t.Fatalf("err: %v", err)
  2986  	}
  2987  
  2988  	if !reflect.DeepEqual(eval2, out) {
  2989  		t.Fatalf("bad: %#v %#v", eval2, out)
  2990  	}
  2991  
  2992  	if out.CreateIndex != 1000 {
  2993  		t.Fatalf("bad: %#v", out)
  2994  	}
  2995  	if out.ModifyIndex != 1001 {
  2996  		t.Fatalf("bad: %#v", out)
  2997  	}
  2998  
  2999  	index, err := state.Index("evals")
  3000  	if err != nil {
  3001  		t.Fatalf("err: %v", err)
  3002  	}
  3003  	if index != 1001 {
  3004  		t.Fatalf("bad: %d", index)
  3005  	}
  3006  
  3007  	if watchFired(ws) {
  3008  		t.Fatalf("bad")
  3009  	}
  3010  }
  3011  
  3012  func TestStateStore_UpsertEvals_Eval_ChildJob(t *testing.T) {
  3013  	state := testStateStore(t)
  3014  
  3015  	parent := mock.Job()
  3016  	if err := state.UpsertJob(998, parent); err != nil {
  3017  		t.Fatalf("err: %v", err)
  3018  	}
  3019  
  3020  	child := mock.Job()
  3021  	child.ParentID = parent.ID
  3022  
  3023  	if err := state.UpsertJob(999, child); err != nil {
  3024  		t.Fatalf("err: %v", err)
  3025  	}
  3026  
  3027  	eval := mock.Eval()
  3028  	eval.Status = structs.EvalStatusComplete
  3029  	eval.JobID = child.ID
  3030  
  3031  	// Create watchsets so we can test that upsert fires the watch
  3032  	ws := memdb.NewWatchSet()
  3033  	ws2 := memdb.NewWatchSet()
  3034  	ws3 := memdb.NewWatchSet()
  3035  	if _, err := state.JobSummaryByID(ws, parent.Namespace, parent.ID); err != nil {
  3036  		t.Fatalf("bad: %v", err)
  3037  	}
  3038  	if _, err := state.EvalByID(ws2, eval.ID); err != nil {
  3039  		t.Fatalf("bad: %v", err)
  3040  	}
  3041  	if _, err := state.EvalsByJob(ws3, eval.Namespace, eval.JobID); err != nil {
  3042  		t.Fatalf("bad: %v", err)
  3043  	}
  3044  
  3045  	err := state.UpsertEvals(1000, []*structs.Evaluation{eval})
  3046  	if err != nil {
  3047  		t.Fatalf("err: %v", err)
  3048  	}
  3049  
  3050  	if !watchFired(ws) {
  3051  		t.Fatalf("bad")
  3052  	}
  3053  	if !watchFired(ws2) {
  3054  		t.Fatalf("bad")
  3055  	}
  3056  	if !watchFired(ws3) {
  3057  		t.Fatalf("bad")
  3058  	}
  3059  
  3060  	ws = memdb.NewWatchSet()
  3061  	out, err := state.EvalByID(ws, eval.ID)
  3062  	if err != nil {
  3063  		t.Fatalf("err: %v", err)
  3064  	}
  3065  
  3066  	if !reflect.DeepEqual(eval, out) {
  3067  		t.Fatalf("bad: %#v %#v", eval, out)
  3068  	}
  3069  
  3070  	index, err := state.Index("evals")
  3071  	if err != nil {
  3072  		t.Fatalf("err: %v", err)
  3073  	}
  3074  	if index != 1000 {
  3075  		t.Fatalf("bad: %d", index)
  3076  	}
  3077  
  3078  	summary, err := state.JobSummaryByID(ws, parent.Namespace, parent.ID)
  3079  	if err != nil {
  3080  		t.Fatalf("err: %v", err)
  3081  	}
  3082  	if summary == nil {
  3083  		t.Fatalf("nil summary")
  3084  	}
  3085  	if summary.JobID != parent.ID {
  3086  		t.Fatalf("bad summary id: %v", parent.ID)
  3087  	}
  3088  	if summary.Children == nil {
  3089  		t.Fatalf("nil children summary")
  3090  	}
  3091  	if summary.Children.Pending != 0 || summary.Children.Running != 0 || summary.Children.Dead != 1 {
  3092  		t.Fatalf("bad children summary: %v", summary.Children)
  3093  	}
  3094  
  3095  	if watchFired(ws) {
  3096  		t.Fatalf("bad")
  3097  	}
  3098  }
  3099  
  3100  func TestStateStore_DeleteEval_Eval(t *testing.T) {
  3101  	state := testStateStore(t)
  3102  	eval1 := mock.Eval()
  3103  	eval2 := mock.Eval()
  3104  	alloc1 := mock.Alloc()
  3105  	alloc2 := mock.Alloc()
  3106  
  3107  	// Create watchsets so we can test that upsert fires the watch
  3108  	watches := make([]memdb.WatchSet, 12)
  3109  	for i := 0; i < 12; i++ {
  3110  		watches[i] = memdb.NewWatchSet()
  3111  	}
  3112  	if _, err := state.EvalByID(watches[0], eval1.ID); err != nil {
  3113  		t.Fatalf("bad: %v", err)
  3114  	}
  3115  	if _, err := state.EvalByID(watches[1], eval2.ID); err != nil {
  3116  		t.Fatalf("bad: %v", err)
  3117  	}
  3118  	if _, err := state.EvalsByJob(watches[2], eval1.Namespace, eval1.JobID); err != nil {
  3119  		t.Fatalf("bad: %v", err)
  3120  	}
  3121  	if _, err := state.EvalsByJob(watches[3], eval2.Namespace, eval2.JobID); err != nil {
  3122  		t.Fatalf("bad: %v", err)
  3123  	}
  3124  	if _, err := state.AllocByID(watches[4], alloc1.ID); err != nil {
  3125  		t.Fatalf("bad: %v", err)
  3126  	}
  3127  	if _, err := state.AllocByID(watches[5], alloc2.ID); err != nil {
  3128  		t.Fatalf("bad: %v", err)
  3129  	}
  3130  	if _, err := state.AllocsByEval(watches[6], alloc1.EvalID); err != nil {
  3131  		t.Fatalf("bad: %v", err)
  3132  	}
  3133  	if _, err := state.AllocsByEval(watches[7], alloc2.EvalID); err != nil {
  3134  		t.Fatalf("bad: %v", err)
  3135  	}
  3136  	if _, err := state.AllocsByJob(watches[8], alloc1.Namespace, alloc1.JobID, false); err != nil {
  3137  		t.Fatalf("bad: %v", err)
  3138  	}
  3139  	if _, err := state.AllocsByJob(watches[9], alloc2.Namespace, alloc2.JobID, false); err != nil {
  3140  		t.Fatalf("bad: %v", err)
  3141  	}
  3142  	if _, err := state.AllocsByNode(watches[10], alloc1.NodeID); err != nil {
  3143  		t.Fatalf("bad: %v", err)
  3144  	}
  3145  	if _, err := state.AllocsByNode(watches[11], alloc2.NodeID); err != nil {
  3146  		t.Fatalf("bad: %v", err)
  3147  	}
  3148  
  3149  	state.UpsertJobSummary(900, mock.JobSummary(eval1.JobID))
  3150  	state.UpsertJobSummary(901, mock.JobSummary(eval2.JobID))
  3151  	state.UpsertJobSummary(902, mock.JobSummary(alloc1.JobID))
  3152  	state.UpsertJobSummary(903, mock.JobSummary(alloc2.JobID))
  3153  	err := state.UpsertEvals(1000, []*structs.Evaluation{eval1, eval2})
  3154  	if err != nil {
  3155  		t.Fatalf("err: %v", err)
  3156  	}
  3157  
  3158  	err = state.UpsertAllocs(1001, []*structs.Allocation{alloc1, alloc2})
  3159  	if err != nil {
  3160  		t.Fatalf("err: %v", err)
  3161  	}
  3162  
  3163  	err = state.DeleteEval(1002, []string{eval1.ID, eval2.ID}, []string{alloc1.ID, alloc2.ID})
  3164  	if err != nil {
  3165  		t.Fatalf("err: %v", err)
  3166  	}
  3167  
  3168  	for i, ws := range watches {
  3169  		if !watchFired(ws) {
  3170  			t.Fatalf("bad %d", i)
  3171  		}
  3172  	}
  3173  
  3174  	ws := memdb.NewWatchSet()
  3175  	out, err := state.EvalByID(ws, eval1.ID)
  3176  	if err != nil {
  3177  		t.Fatalf("err: %v", err)
  3178  	}
  3179  
  3180  	if out != nil {
  3181  		t.Fatalf("bad: %#v %#v", eval1, out)
  3182  	}
  3183  
  3184  	out, err = state.EvalByID(ws, eval2.ID)
  3185  	if err != nil {
  3186  		t.Fatalf("err: %v", err)
  3187  	}
  3188  
  3189  	if out != nil {
  3190  		t.Fatalf("bad: %#v %#v", eval1, out)
  3191  	}
  3192  
  3193  	outA, err := state.AllocByID(ws, alloc1.ID)
  3194  	if err != nil {
  3195  		t.Fatalf("err: %v", err)
  3196  	}
  3197  
  3198  	if out != nil {
  3199  		t.Fatalf("bad: %#v %#v", alloc1, outA)
  3200  	}
  3201  
  3202  	outA, err = state.AllocByID(ws, alloc2.ID)
  3203  	if err != nil {
  3204  		t.Fatalf("err: %v", err)
  3205  	}
  3206  
  3207  	if out != nil {
  3208  		t.Fatalf("bad: %#v %#v", alloc1, outA)
  3209  	}
  3210  
  3211  	index, err := state.Index("evals")
  3212  	if err != nil {
  3213  		t.Fatalf("err: %v", err)
  3214  	}
  3215  	if index != 1002 {
  3216  		t.Fatalf("bad: %d", index)
  3217  	}
  3218  
  3219  	index, err = state.Index("allocs")
  3220  	if err != nil {
  3221  		t.Fatalf("err: %v", err)
  3222  	}
  3223  	if index != 1002 {
  3224  		t.Fatalf("bad: %d", index)
  3225  	}
  3226  
  3227  	if watchFired(ws) {
  3228  		t.Fatalf("bad")
  3229  	}
  3230  }
  3231  
  3232  func TestStateStore_DeleteEval_ChildJob(t *testing.T) {
  3233  	state := testStateStore(t)
  3234  
  3235  	parent := mock.Job()
  3236  	if err := state.UpsertJob(998, parent); err != nil {
  3237  		t.Fatalf("err: %v", err)
  3238  	}
  3239  
  3240  	child := mock.Job()
  3241  	child.ParentID = parent.ID
  3242  
  3243  	if err := state.UpsertJob(999, child); err != nil {
  3244  		t.Fatalf("err: %v", err)
  3245  	}
  3246  
  3247  	eval1 := mock.Eval()
  3248  	eval1.JobID = child.ID
  3249  	alloc1 := mock.Alloc()
  3250  	alloc1.JobID = child.ID
  3251  
  3252  	err := state.UpsertEvals(1000, []*structs.Evaluation{eval1})
  3253  	if err != nil {
  3254  		t.Fatalf("err: %v", err)
  3255  	}
  3256  
  3257  	err = state.UpsertAllocs(1001, []*structs.Allocation{alloc1})
  3258  	if err != nil {
  3259  		t.Fatalf("err: %v", err)
  3260  	}
  3261  
  3262  	// Create watchsets so we can test that delete fires the watch
  3263  	ws := memdb.NewWatchSet()
  3264  	if _, err := state.JobSummaryByID(ws, parent.Namespace, parent.ID); err != nil {
  3265  		t.Fatalf("bad: %v", err)
  3266  	}
  3267  
  3268  	err = state.DeleteEval(1002, []string{eval1.ID}, []string{alloc1.ID})
  3269  	if err != nil {
  3270  		t.Fatalf("err: %v", err)
  3271  	}
  3272  
  3273  	if !watchFired(ws) {
  3274  		t.Fatalf("bad")
  3275  	}
  3276  
  3277  	ws = memdb.NewWatchSet()
  3278  	summary, err := state.JobSummaryByID(ws, parent.Namespace, parent.ID)
  3279  	if err != nil {
  3280  		t.Fatalf("err: %v", err)
  3281  	}
  3282  	if summary == nil {
  3283  		t.Fatalf("nil summary")
  3284  	}
  3285  	if summary.JobID != parent.ID {
  3286  		t.Fatalf("bad summary id: %v", parent.ID)
  3287  	}
  3288  	if summary.Children == nil {
  3289  		t.Fatalf("nil children summary")
  3290  	}
  3291  	if summary.Children.Pending != 0 || summary.Children.Running != 0 || summary.Children.Dead != 1 {
  3292  		t.Fatalf("bad children summary: %v", summary.Children)
  3293  	}
  3294  
  3295  	if watchFired(ws) {
  3296  		t.Fatalf("bad")
  3297  	}
  3298  }
  3299  
  3300  func TestStateStore_EvalsByJob(t *testing.T) {
  3301  	state := testStateStore(t)
  3302  
  3303  	eval1 := mock.Eval()
  3304  	eval2 := mock.Eval()
  3305  	eval2.JobID = eval1.JobID
  3306  	eval3 := mock.Eval()
  3307  	evals := []*structs.Evaluation{eval1, eval2}
  3308  
  3309  	err := state.UpsertEvals(1000, evals)
  3310  	if err != nil {
  3311  		t.Fatalf("err: %v", err)
  3312  	}
  3313  	err = state.UpsertEvals(1001, []*structs.Evaluation{eval3})
  3314  	if err != nil {
  3315  		t.Fatalf("err: %v", err)
  3316  	}
  3317  
  3318  	ws := memdb.NewWatchSet()
  3319  	out, err := state.EvalsByJob(ws, eval1.Namespace, eval1.JobID)
  3320  	if err != nil {
  3321  		t.Fatalf("err: %v", err)
  3322  	}
  3323  
  3324  	sort.Sort(EvalIDSort(evals))
  3325  	sort.Sort(EvalIDSort(out))
  3326  
  3327  	if !reflect.DeepEqual(evals, out) {
  3328  		t.Fatalf("bad: %#v %#v", evals, out)
  3329  	}
  3330  
  3331  	if watchFired(ws) {
  3332  		t.Fatalf("bad")
  3333  	}
  3334  }
  3335  
  3336  func TestStateStore_Evals(t *testing.T) {
  3337  	state := testStateStore(t)
  3338  	var evals []*structs.Evaluation
  3339  
  3340  	for i := 0; i < 10; i++ {
  3341  		eval := mock.Eval()
  3342  		evals = append(evals, eval)
  3343  
  3344  		err := state.UpsertEvals(1000+uint64(i), []*structs.Evaluation{eval})
  3345  		if err != nil {
  3346  			t.Fatalf("err: %v", err)
  3347  		}
  3348  	}
  3349  
  3350  	ws := memdb.NewWatchSet()
  3351  	iter, err := state.Evals(ws)
  3352  	if err != nil {
  3353  		t.Fatalf("err: %v", err)
  3354  	}
  3355  
  3356  	var out []*structs.Evaluation
  3357  	for {
  3358  		raw := iter.Next()
  3359  		if raw == nil {
  3360  			break
  3361  		}
  3362  		out = append(out, raw.(*structs.Evaluation))
  3363  	}
  3364  
  3365  	sort.Sort(EvalIDSort(evals))
  3366  	sort.Sort(EvalIDSort(out))
  3367  
  3368  	if !reflect.DeepEqual(evals, out) {
  3369  		t.Fatalf("bad: %#v %#v", evals, out)
  3370  	}
  3371  
  3372  	if watchFired(ws) {
  3373  		t.Fatalf("bad")
  3374  	}
  3375  }
  3376  
  3377  func TestStateStore_EvalsByIDPrefix(t *testing.T) {
  3378  	state := testStateStore(t)
  3379  	var evals []*structs.Evaluation
  3380  
  3381  	ids := []string{
  3382  		"aaaaaaaa-7bfb-395d-eb95-0685af2176b2",
  3383  		"aaaaaaab-7bfb-395d-eb95-0685af2176b2",
  3384  		"aaaaaabb-7bfb-395d-eb95-0685af2176b2",
  3385  		"aaaaabbb-7bfb-395d-eb95-0685af2176b2",
  3386  		"aaaabbbb-7bfb-395d-eb95-0685af2176b2",
  3387  		"aaabbbbb-7bfb-395d-eb95-0685af2176b2",
  3388  		"aabbbbbb-7bfb-395d-eb95-0685af2176b2",
  3389  		"abbbbbbb-7bfb-395d-eb95-0685af2176b2",
  3390  		"bbbbbbbb-7bfb-395d-eb95-0685af2176b2",
  3391  	}
  3392  	for i := 0; i < 9; i++ {
  3393  		eval := mock.Eval()
  3394  		eval.ID = ids[i]
  3395  		evals = append(evals, eval)
  3396  	}
  3397  
  3398  	err := state.UpsertEvals(1000, evals)
  3399  	if err != nil {
  3400  		t.Fatalf("err: %v", err)
  3401  	}
  3402  
  3403  	ws := memdb.NewWatchSet()
  3404  	iter, err := state.EvalsByIDPrefix(ws, structs.DefaultNamespace, "aaaa")
  3405  	if err != nil {
  3406  		t.Fatalf("err: %v", err)
  3407  	}
  3408  
  3409  	gatherEvals := func(iter memdb.ResultIterator) []*structs.Evaluation {
  3410  		var evals []*structs.Evaluation
  3411  		for {
  3412  			raw := iter.Next()
  3413  			if raw == nil {
  3414  				break
  3415  			}
  3416  			evals = append(evals, raw.(*structs.Evaluation))
  3417  		}
  3418  		return evals
  3419  	}
  3420  
  3421  	out := gatherEvals(iter)
  3422  	if len(out) != 5 {
  3423  		t.Fatalf("bad: expected five evaluations, got: %#v", out)
  3424  	}
  3425  
  3426  	sort.Sort(EvalIDSort(evals))
  3427  
  3428  	for index, eval := range out {
  3429  		if ids[index] != eval.ID {
  3430  			t.Fatalf("bad: got unexpected id: %s", eval.ID)
  3431  		}
  3432  	}
  3433  
  3434  	iter, err = state.EvalsByIDPrefix(ws, structs.DefaultNamespace, "b-a7bfb")
  3435  	if err != nil {
  3436  		t.Fatalf("err: %v", err)
  3437  	}
  3438  
  3439  	out = gatherEvals(iter)
  3440  	if len(out) != 0 {
  3441  		t.Fatalf("bad: unexpected zero evaluations, got: %#v", out)
  3442  	}
  3443  
  3444  	if watchFired(ws) {
  3445  		t.Fatalf("bad")
  3446  	}
  3447  }
  3448  
  3449  func TestStateStore_RestoreEval(t *testing.T) {
  3450  	state := testStateStore(t)
  3451  	eval := mock.Eval()
  3452  
  3453  	restore, err := state.Restore()
  3454  	if err != nil {
  3455  		t.Fatalf("err: %v", err)
  3456  	}
  3457  
  3458  	err = restore.EvalRestore(eval)
  3459  	if err != nil {
  3460  		t.Fatalf("err: %v", err)
  3461  	}
  3462  	restore.Commit()
  3463  
  3464  	ws := memdb.NewWatchSet()
  3465  	out, err := state.EvalByID(ws, eval.ID)
  3466  	if err != nil {
  3467  		t.Fatalf("err: %v", err)
  3468  	}
  3469  
  3470  	if !reflect.DeepEqual(out, eval) {
  3471  		t.Fatalf("Bad: %#v %#v", out, eval)
  3472  	}
  3473  }
  3474  
  3475  func TestStateStore_UpdateAllocsFromClient(t *testing.T) {
  3476  	state := testStateStore(t)
  3477  	parent := mock.Job()
  3478  	if err := state.UpsertJob(998, parent); err != nil {
  3479  		t.Fatalf("err: %v", err)
  3480  	}
  3481  
  3482  	child := mock.Job()
  3483  	child.ParentID = parent.ID
  3484  	if err := state.UpsertJob(999, child); err != nil {
  3485  		t.Fatalf("err: %v", err)
  3486  	}
  3487  
  3488  	alloc := mock.Alloc()
  3489  	alloc.JobID = child.ID
  3490  	alloc.Job = child
  3491  
  3492  	err := state.UpsertAllocs(1000, []*structs.Allocation{alloc})
  3493  	if err != nil {
  3494  		t.Fatalf("err: %v", err)
  3495  	}
  3496  
  3497  	ws := memdb.NewWatchSet()
  3498  	summary, err := state.JobSummaryByID(ws, parent.Namespace, parent.ID)
  3499  	if err != nil {
  3500  		t.Fatalf("err: %v", err)
  3501  	}
  3502  	if summary == nil {
  3503  		t.Fatalf("nil summary")
  3504  	}
  3505  	if summary.JobID != parent.ID {
  3506  		t.Fatalf("bad summary id: %v", parent.ID)
  3507  	}
  3508  	if summary.Children == nil {
  3509  		t.Fatalf("nil children summary")
  3510  	}
  3511  	if summary.Children.Pending != 0 || summary.Children.Running != 1 || summary.Children.Dead != 0 {
  3512  		t.Fatalf("bad children summary: %v", summary.Children)
  3513  	}
  3514  
  3515  	// Create watchsets so we can test that update fires the watch
  3516  	ws = memdb.NewWatchSet()
  3517  	if _, err := state.JobSummaryByID(ws, parent.Namespace, parent.ID); err != nil {
  3518  		t.Fatalf("bad: %v", err)
  3519  	}
  3520  
  3521  	// Create the delta updates
  3522  	ts := map[string]*structs.TaskState{"web": {State: structs.TaskStateRunning}}
  3523  	update := &structs.Allocation{
  3524  		ID:           alloc.ID,
  3525  		ClientStatus: structs.AllocClientStatusComplete,
  3526  		TaskStates:   ts,
  3527  		JobID:        alloc.JobID,
  3528  		TaskGroup:    alloc.TaskGroup,
  3529  	}
  3530  	err = state.UpdateAllocsFromClient(1001, []*structs.Allocation{update})
  3531  	if err != nil {
  3532  		t.Fatalf("err: %v", err)
  3533  	}
  3534  
  3535  	if !watchFired(ws) {
  3536  		t.Fatalf("bad")
  3537  	}
  3538  
  3539  	ws = memdb.NewWatchSet()
  3540  	summary, err = state.JobSummaryByID(ws, parent.Namespace, parent.ID)
  3541  	if err != nil {
  3542  		t.Fatalf("err: %v", err)
  3543  	}
  3544  	if summary == nil {
  3545  		t.Fatalf("nil summary")
  3546  	}
  3547  	if summary.JobID != parent.ID {
  3548  		t.Fatalf("bad summary id: %v", parent.ID)
  3549  	}
  3550  	if summary.Children == nil {
  3551  		t.Fatalf("nil children summary")
  3552  	}
  3553  	if summary.Children.Pending != 0 || summary.Children.Running != 0 || summary.Children.Dead != 1 {
  3554  		t.Fatalf("bad children summary: %v", summary.Children)
  3555  	}
  3556  
  3557  	if watchFired(ws) {
  3558  		t.Fatalf("bad")
  3559  	}
  3560  }
  3561  
  3562  func TestStateStore_UpdateAllocsFromClient_ChildJob(t *testing.T) {
  3563  	state := testStateStore(t)
  3564  	alloc1 := mock.Alloc()
  3565  	alloc2 := mock.Alloc()
  3566  
  3567  	if err := state.UpsertJob(999, alloc1.Job); err != nil {
  3568  		t.Fatalf("err: %v", err)
  3569  	}
  3570  	if err := state.UpsertJob(999, alloc2.Job); err != nil {
  3571  		t.Fatalf("err: %v", err)
  3572  	}
  3573  
  3574  	err := state.UpsertAllocs(1000, []*structs.Allocation{alloc1, alloc2})
  3575  	if err != nil {
  3576  		t.Fatalf("err: %v", err)
  3577  	}
  3578  
  3579  	// Create watchsets so we can test that update fires the watch
  3580  	watches := make([]memdb.WatchSet, 8)
  3581  	for i := 0; i < 8; i++ {
  3582  		watches[i] = memdb.NewWatchSet()
  3583  	}
  3584  	if _, err := state.AllocByID(watches[0], alloc1.ID); err != nil {
  3585  		t.Fatalf("bad: %v", err)
  3586  	}
  3587  	if _, err := state.AllocByID(watches[1], alloc2.ID); err != nil {
  3588  		t.Fatalf("bad: %v", err)
  3589  	}
  3590  	if _, err := state.AllocsByEval(watches[2], alloc1.EvalID); err != nil {
  3591  		t.Fatalf("bad: %v", err)
  3592  	}
  3593  	if _, err := state.AllocsByEval(watches[3], alloc2.EvalID); err != nil {
  3594  		t.Fatalf("bad: %v", err)
  3595  	}
  3596  	if _, err := state.AllocsByJob(watches[4], alloc1.Namespace, alloc1.JobID, false); err != nil {
  3597  		t.Fatalf("bad: %v", err)
  3598  	}
  3599  	if _, err := state.AllocsByJob(watches[5], alloc2.Namespace, alloc2.JobID, false); err != nil {
  3600  		t.Fatalf("bad: %v", err)
  3601  	}
  3602  	if _, err := state.AllocsByNode(watches[6], alloc1.NodeID); err != nil {
  3603  		t.Fatalf("bad: %v", err)
  3604  	}
  3605  	if _, err := state.AllocsByNode(watches[7], alloc2.NodeID); err != nil {
  3606  		t.Fatalf("bad: %v", err)
  3607  	}
  3608  
  3609  	// Create the delta updates
  3610  	ts := map[string]*structs.TaskState{"web": {State: structs.TaskStatePending}}
  3611  	update := &structs.Allocation{
  3612  		ID:           alloc1.ID,
  3613  		ClientStatus: structs.AllocClientStatusFailed,
  3614  		TaskStates:   ts,
  3615  		JobID:        alloc1.JobID,
  3616  		TaskGroup:    alloc1.TaskGroup,
  3617  	}
  3618  	update2 := &structs.Allocation{
  3619  		ID:           alloc2.ID,
  3620  		ClientStatus: structs.AllocClientStatusRunning,
  3621  		TaskStates:   ts,
  3622  		JobID:        alloc2.JobID,
  3623  		TaskGroup:    alloc2.TaskGroup,
  3624  	}
  3625  
  3626  	err = state.UpdateAllocsFromClient(1001, []*structs.Allocation{update, update2})
  3627  	if err != nil {
  3628  		t.Fatalf("err: %v", err)
  3629  	}
  3630  
  3631  	for i, ws := range watches {
  3632  		if !watchFired(ws) {
  3633  			t.Fatalf("bad %d", i)
  3634  		}
  3635  	}
  3636  
  3637  	ws := memdb.NewWatchSet()
  3638  	out, err := state.AllocByID(ws, alloc1.ID)
  3639  	if err != nil {
  3640  		t.Fatalf("err: %v", err)
  3641  	}
  3642  
  3643  	alloc1.CreateIndex = 1000
  3644  	alloc1.ModifyIndex = 1001
  3645  	alloc1.TaskStates = ts
  3646  	alloc1.ClientStatus = structs.AllocClientStatusFailed
  3647  	if !reflect.DeepEqual(alloc1, out) {
  3648  		t.Fatalf("bad: %#v %#v", alloc1, out)
  3649  	}
  3650  
  3651  	out, err = state.AllocByID(ws, alloc2.ID)
  3652  	if err != nil {
  3653  		t.Fatalf("err: %v", err)
  3654  	}
  3655  
  3656  	alloc2.ModifyIndex = 1000
  3657  	alloc2.ModifyIndex = 1001
  3658  	alloc2.ClientStatus = structs.AllocClientStatusRunning
  3659  	alloc2.TaskStates = ts
  3660  	if !reflect.DeepEqual(alloc2, out) {
  3661  		t.Fatalf("bad: %#v %#v", alloc2, out)
  3662  	}
  3663  
  3664  	index, err := state.Index("allocs")
  3665  	if err != nil {
  3666  		t.Fatalf("err: %v", err)
  3667  	}
  3668  	if index != 1001 {
  3669  		t.Fatalf("bad: %d", index)
  3670  	}
  3671  
  3672  	// Ensure summaries have been updated
  3673  	summary, err := state.JobSummaryByID(ws, alloc1.Namespace, alloc1.JobID)
  3674  	if err != nil {
  3675  		t.Fatalf("err: %v", err)
  3676  	}
  3677  	tgSummary := summary.Summary["web"]
  3678  	if tgSummary.Failed != 1 {
  3679  		t.Fatalf("expected failed: %v, actual: %v, summary: %#v", 1, tgSummary.Failed, tgSummary)
  3680  	}
  3681  
  3682  	summary2, err := state.JobSummaryByID(ws, alloc2.Namespace, alloc2.JobID)
  3683  	if err != nil {
  3684  		t.Fatalf("err: %v", err)
  3685  	}
  3686  	tgSummary2 := summary2.Summary["web"]
  3687  	if tgSummary2.Running != 1 {
  3688  		t.Fatalf("expected running: %v, actual: %v", 1, tgSummary2.Running)
  3689  	}
  3690  
  3691  	if watchFired(ws) {
  3692  		t.Fatalf("bad")
  3693  	}
  3694  }
  3695  
  3696  func TestStateStore_UpdateMultipleAllocsFromClient(t *testing.T) {
  3697  	state := testStateStore(t)
  3698  	alloc := mock.Alloc()
  3699  
  3700  	if err := state.UpsertJob(999, alloc.Job); err != nil {
  3701  		t.Fatalf("err: %v", err)
  3702  	}
  3703  	err := state.UpsertAllocs(1000, []*structs.Allocation{alloc})
  3704  	if err != nil {
  3705  		t.Fatalf("err: %v", err)
  3706  	}
  3707  
  3708  	// Create the delta updates
  3709  	ts := map[string]*structs.TaskState{"web": {State: structs.TaskStatePending}}
  3710  	update := &structs.Allocation{
  3711  		ID:           alloc.ID,
  3712  		ClientStatus: structs.AllocClientStatusRunning,
  3713  		TaskStates:   ts,
  3714  		JobID:        alloc.JobID,
  3715  		TaskGroup:    alloc.TaskGroup,
  3716  	}
  3717  	update2 := &structs.Allocation{
  3718  		ID:           alloc.ID,
  3719  		ClientStatus: structs.AllocClientStatusPending,
  3720  		TaskStates:   ts,
  3721  		JobID:        alloc.JobID,
  3722  		TaskGroup:    alloc.TaskGroup,
  3723  	}
  3724  
  3725  	err = state.UpdateAllocsFromClient(1001, []*structs.Allocation{update, update2})
  3726  	if err != nil {
  3727  		t.Fatalf("err: %v", err)
  3728  	}
  3729  
  3730  	ws := memdb.NewWatchSet()
  3731  	out, err := state.AllocByID(ws, alloc.ID)
  3732  	if err != nil {
  3733  		t.Fatalf("err: %v", err)
  3734  	}
  3735  
  3736  	alloc.CreateIndex = 1000
  3737  	alloc.ModifyIndex = 1001
  3738  	alloc.TaskStates = ts
  3739  	alloc.ClientStatus = structs.AllocClientStatusPending
  3740  	if !reflect.DeepEqual(alloc, out) {
  3741  		t.Fatalf("bad: %#v , actual:%#v", alloc, out)
  3742  	}
  3743  
  3744  	summary, err := state.JobSummaryByID(ws, alloc.Namespace, alloc.JobID)
  3745  	expectedSummary := &structs.JobSummary{
  3746  		JobID:     alloc.JobID,
  3747  		Namespace: alloc.Namespace,
  3748  		Summary: map[string]structs.TaskGroupSummary{
  3749  			"web": {
  3750  				Starting: 1,
  3751  			},
  3752  		},
  3753  		Children:    new(structs.JobChildrenSummary),
  3754  		CreateIndex: 999,
  3755  		ModifyIndex: 1001,
  3756  	}
  3757  	if err != nil {
  3758  		t.Fatalf("err: %v", err)
  3759  	}
  3760  	if !reflect.DeepEqual(summary, expectedSummary) {
  3761  		t.Fatalf("expected: %#v, actual: %#v", expectedSummary, summary)
  3762  	}
  3763  }
  3764  
  3765  func TestStateStore_UpdateAllocsFromClient_Deployment(t *testing.T) {
  3766  	require := require.New(t)
  3767  	state := testStateStore(t)
  3768  
  3769  	alloc := mock.Alloc()
  3770  	now := time.Now()
  3771  	alloc.CreateTime = now.UnixNano()
  3772  	pdeadline := 5 * time.Minute
  3773  	deployment := mock.Deployment()
  3774  	deployment.TaskGroups[alloc.TaskGroup].ProgressDeadline = pdeadline
  3775  	alloc.DeploymentID = deployment.ID
  3776  
  3777  	require.Nil(state.UpsertJob(999, alloc.Job))
  3778  	require.Nil(state.UpsertDeployment(1000, deployment))
  3779  	require.Nil(state.UpsertAllocs(1001, []*structs.Allocation{alloc}))
  3780  
  3781  	healthy := now.Add(time.Second)
  3782  	update := &structs.Allocation{
  3783  		ID:           alloc.ID,
  3784  		ClientStatus: structs.AllocClientStatusRunning,
  3785  		JobID:        alloc.JobID,
  3786  		TaskGroup:    alloc.TaskGroup,
  3787  		DeploymentStatus: &structs.AllocDeploymentStatus{
  3788  			Healthy:   helper.BoolToPtr(true),
  3789  			Timestamp: healthy,
  3790  		},
  3791  	}
  3792  	require.Nil(state.UpdateAllocsFromClient(1001, []*structs.Allocation{update}))
  3793  
  3794  	// Check that the deployment state was updated because the healthy
  3795  	// deployment
  3796  	dout, err := state.DeploymentByID(nil, deployment.ID)
  3797  	require.Nil(err)
  3798  	require.NotNil(dout)
  3799  	require.Len(dout.TaskGroups, 1)
  3800  	dstate := dout.TaskGroups[alloc.TaskGroup]
  3801  	require.NotNil(dstate)
  3802  	require.Equal(1, dstate.PlacedAllocs)
  3803  	require.True(healthy.Add(pdeadline).Equal(dstate.RequireProgressBy))
  3804  }
  3805  
  3806  // This tests that the deployment state is merged correctly
  3807  func TestStateStore_UpdateAllocsFromClient_DeploymentStateMerges(t *testing.T) {
  3808  	require := require.New(t)
  3809  	state := testStateStore(t)
  3810  
  3811  	alloc := mock.Alloc()
  3812  	now := time.Now()
  3813  	alloc.CreateTime = now.UnixNano()
  3814  	pdeadline := 5 * time.Minute
  3815  	deployment := mock.Deployment()
  3816  	deployment.TaskGroups[alloc.TaskGroup].ProgressDeadline = pdeadline
  3817  	alloc.DeploymentID = deployment.ID
  3818  	alloc.DeploymentStatus = &structs.AllocDeploymentStatus{
  3819  		Canary: true,
  3820  	}
  3821  
  3822  	require.Nil(state.UpsertJob(999, alloc.Job))
  3823  	require.Nil(state.UpsertDeployment(1000, deployment))
  3824  	require.Nil(state.UpsertAllocs(1001, []*structs.Allocation{alloc}))
  3825  
  3826  	update := &structs.Allocation{
  3827  		ID:           alloc.ID,
  3828  		ClientStatus: structs.AllocClientStatusRunning,
  3829  		JobID:        alloc.JobID,
  3830  		TaskGroup:    alloc.TaskGroup,
  3831  		DeploymentStatus: &structs.AllocDeploymentStatus{
  3832  			Healthy: helper.BoolToPtr(true),
  3833  			Canary:  false,
  3834  		},
  3835  	}
  3836  	require.Nil(state.UpdateAllocsFromClient(1001, []*structs.Allocation{update}))
  3837  
  3838  	// Check that the merging of the deployment status was correct
  3839  	out, err := state.AllocByID(nil, alloc.ID)
  3840  	require.Nil(err)
  3841  	require.NotNil(out)
  3842  	require.True(out.DeploymentStatus.Canary)
  3843  	require.NotNil(out.DeploymentStatus.Healthy)
  3844  	require.True(*out.DeploymentStatus.Healthy)
  3845  }
  3846  
  3847  func TestStateStore_UpsertAlloc_Alloc(t *testing.T) {
  3848  	state := testStateStore(t)
  3849  	alloc := mock.Alloc()
  3850  
  3851  	if err := state.UpsertJob(999, alloc.Job); err != nil {
  3852  		t.Fatalf("err: %v", err)
  3853  	}
  3854  
  3855  	// Create watchsets so we can test that update fires the watch
  3856  	watches := make([]memdb.WatchSet, 4)
  3857  	for i := 0; i < 4; i++ {
  3858  		watches[i] = memdb.NewWatchSet()
  3859  	}
  3860  	if _, err := state.AllocByID(watches[0], alloc.ID); err != nil {
  3861  		t.Fatalf("bad: %v", err)
  3862  	}
  3863  	if _, err := state.AllocsByEval(watches[1], alloc.EvalID); err != nil {
  3864  		t.Fatalf("bad: %v", err)
  3865  	}
  3866  	if _, err := state.AllocsByJob(watches[2], alloc.Namespace, alloc.JobID, false); err != nil {
  3867  		t.Fatalf("bad: %v", err)
  3868  	}
  3869  	if _, err := state.AllocsByNode(watches[3], alloc.NodeID); err != nil {
  3870  		t.Fatalf("bad: %v", err)
  3871  	}
  3872  
  3873  	err := state.UpsertAllocs(1000, []*structs.Allocation{alloc})
  3874  	if err != nil {
  3875  		t.Fatalf("err: %v", err)
  3876  	}
  3877  
  3878  	for i, ws := range watches {
  3879  		if !watchFired(ws) {
  3880  			t.Fatalf("bad %d", i)
  3881  		}
  3882  	}
  3883  
  3884  	ws := memdb.NewWatchSet()
  3885  	out, err := state.AllocByID(ws, alloc.ID)
  3886  	if err != nil {
  3887  		t.Fatalf("err: %v", err)
  3888  	}
  3889  
  3890  	if !reflect.DeepEqual(alloc, out) {
  3891  		t.Fatalf("bad: %#v %#v", alloc, out)
  3892  	}
  3893  
  3894  	index, err := state.Index("allocs")
  3895  	if err != nil {
  3896  		t.Fatalf("err: %v", err)
  3897  	}
  3898  	if index != 1000 {
  3899  		t.Fatalf("bad: %d", index)
  3900  	}
  3901  
  3902  	summary, err := state.JobSummaryByID(ws, alloc.Namespace, alloc.JobID)
  3903  	if err != nil {
  3904  		t.Fatalf("err: %v", err)
  3905  	}
  3906  
  3907  	tgSummary, ok := summary.Summary["web"]
  3908  	if !ok {
  3909  		t.Fatalf("no summary for task group web")
  3910  	}
  3911  	if tgSummary.Starting != 1 {
  3912  		t.Fatalf("expected queued: %v, actual: %v", 1, tgSummary.Starting)
  3913  	}
  3914  
  3915  	if watchFired(ws) {
  3916  		t.Fatalf("bad")
  3917  	}
  3918  }
  3919  
  3920  func TestStateStore_UpsertAlloc_Deployment(t *testing.T) {
  3921  	require := require.New(t)
  3922  	state := testStateStore(t)
  3923  	alloc := mock.Alloc()
  3924  	now := time.Now()
  3925  	alloc.CreateTime = now.UnixNano()
  3926  	alloc.ModifyTime = now.UnixNano()
  3927  	pdeadline := 5 * time.Minute
  3928  	deployment := mock.Deployment()
  3929  	deployment.TaskGroups[alloc.TaskGroup].ProgressDeadline = pdeadline
  3930  	alloc.DeploymentID = deployment.ID
  3931  
  3932  	require.Nil(state.UpsertJob(999, alloc.Job))
  3933  	require.Nil(state.UpsertDeployment(1000, deployment))
  3934  
  3935  	// Create a watch set so we can test that update fires the watch
  3936  	ws := memdb.NewWatchSet()
  3937  	require.Nil(state.AllocsByDeployment(ws, alloc.DeploymentID))
  3938  
  3939  	err := state.UpsertAllocs(1001, []*structs.Allocation{alloc})
  3940  	require.Nil(err)
  3941  
  3942  	if !watchFired(ws) {
  3943  		t.Fatalf("watch not fired")
  3944  	}
  3945  
  3946  	ws = memdb.NewWatchSet()
  3947  	allocs, err := state.AllocsByDeployment(ws, alloc.DeploymentID)
  3948  	require.Nil(err)
  3949  	require.Len(allocs, 1)
  3950  	require.EqualValues(alloc, allocs[0])
  3951  
  3952  	index, err := state.Index("allocs")
  3953  	require.Nil(err)
  3954  	require.EqualValues(1001, index)
  3955  	if watchFired(ws) {
  3956  		t.Fatalf("bad")
  3957  	}
  3958  
  3959  	// Check that the deployment state was updated
  3960  	dout, err := state.DeploymentByID(nil, deployment.ID)
  3961  	require.Nil(err)
  3962  	require.NotNil(dout)
  3963  	require.Len(dout.TaskGroups, 1)
  3964  	dstate := dout.TaskGroups[alloc.TaskGroup]
  3965  	require.NotNil(dstate)
  3966  	require.Equal(1, dstate.PlacedAllocs)
  3967  	require.True(now.Add(pdeadline).Equal(dstate.RequireProgressBy))
  3968  }
  3969  
  3970  // Testing to ensure we keep issue
  3971  // https://github.com/hashicorp/nomad/issues/2583 fixed
  3972  func TestStateStore_UpsertAlloc_No_Job(t *testing.T) {
  3973  	state := testStateStore(t)
  3974  	alloc := mock.Alloc()
  3975  	alloc.Job = nil
  3976  
  3977  	err := state.UpsertAllocs(999, []*structs.Allocation{alloc})
  3978  	if err == nil || !strings.Contains(err.Error(), "without a job") {
  3979  		t.Fatalf("expect err: %v", err)
  3980  	}
  3981  }
  3982  
  3983  func TestStateStore_UpsertAlloc_ChildJob(t *testing.T) {
  3984  	state := testStateStore(t)
  3985  
  3986  	parent := mock.Job()
  3987  	if err := state.UpsertJob(998, parent); err != nil {
  3988  		t.Fatalf("err: %v", err)
  3989  	}
  3990  
  3991  	child := mock.Job()
  3992  	child.ParentID = parent.ID
  3993  
  3994  	if err := state.UpsertJob(999, child); err != nil {
  3995  		t.Fatalf("err: %v", err)
  3996  	}
  3997  
  3998  	alloc := mock.Alloc()
  3999  	alloc.JobID = child.ID
  4000  	alloc.Job = child
  4001  
  4002  	// Create watchsets so we can test that delete fires the watch
  4003  	ws := memdb.NewWatchSet()
  4004  	if _, err := state.JobSummaryByID(ws, parent.Namespace, parent.ID); err != nil {
  4005  		t.Fatalf("bad: %v", err)
  4006  	}
  4007  
  4008  	err := state.UpsertAllocs(1000, []*structs.Allocation{alloc})
  4009  	if err != nil {
  4010  		t.Fatalf("err: %v", err)
  4011  	}
  4012  
  4013  	if !watchFired(ws) {
  4014  		t.Fatalf("bad")
  4015  	}
  4016  
  4017  	ws = memdb.NewWatchSet()
  4018  	summary, err := state.JobSummaryByID(ws, parent.Namespace, parent.ID)
  4019  	if err != nil {
  4020  		t.Fatalf("err: %v", err)
  4021  	}
  4022  	if summary == nil {
  4023  		t.Fatalf("nil summary")
  4024  	}
  4025  	if summary.JobID != parent.ID {
  4026  		t.Fatalf("bad summary id: %v", parent.ID)
  4027  	}
  4028  	if summary.Children == nil {
  4029  		t.Fatalf("nil children summary")
  4030  	}
  4031  	if summary.Children.Pending != 0 || summary.Children.Running != 1 || summary.Children.Dead != 0 {
  4032  		t.Fatalf("bad children summary: %v", summary.Children)
  4033  	}
  4034  
  4035  	if watchFired(ws) {
  4036  		t.Fatalf("bad")
  4037  	}
  4038  }
  4039  
  4040  func TestStateStore_UpdateAlloc_Alloc(t *testing.T) {
  4041  	state := testStateStore(t)
  4042  	alloc := mock.Alloc()
  4043  
  4044  	if err := state.UpsertJob(999, alloc.Job); err != nil {
  4045  		t.Fatalf("err: %v", err)
  4046  	}
  4047  
  4048  	err := state.UpsertAllocs(1000, []*structs.Allocation{alloc})
  4049  	if err != nil {
  4050  		t.Fatalf("err: %v", err)
  4051  	}
  4052  
  4053  	ws := memdb.NewWatchSet()
  4054  	summary, err := state.JobSummaryByID(ws, alloc.Namespace, alloc.JobID)
  4055  	if err != nil {
  4056  		t.Fatalf("err: %v", err)
  4057  	}
  4058  	tgSummary := summary.Summary["web"]
  4059  	if tgSummary.Starting != 1 {
  4060  		t.Fatalf("expected starting: %v, actual: %v", 1, tgSummary.Starting)
  4061  	}
  4062  
  4063  	alloc2 := mock.Alloc()
  4064  	alloc2.ID = alloc.ID
  4065  	alloc2.NodeID = alloc.NodeID + ".new"
  4066  	state.UpsertJobSummary(1001, mock.JobSummary(alloc2.JobID))
  4067  
  4068  	// Create watchsets so we can test that update fires the watch
  4069  	watches := make([]memdb.WatchSet, 4)
  4070  	for i := 0; i < 4; i++ {
  4071  		watches[i] = memdb.NewWatchSet()
  4072  	}
  4073  	if _, err := state.AllocByID(watches[0], alloc2.ID); err != nil {
  4074  		t.Fatalf("bad: %v", err)
  4075  	}
  4076  	if _, err := state.AllocsByEval(watches[1], alloc2.EvalID); err != nil {
  4077  		t.Fatalf("bad: %v", err)
  4078  	}
  4079  	if _, err := state.AllocsByJob(watches[2], alloc2.Namespace, alloc2.JobID, false); err != nil {
  4080  		t.Fatalf("bad: %v", err)
  4081  	}
  4082  	if _, err := state.AllocsByNode(watches[3], alloc2.NodeID); err != nil {
  4083  		t.Fatalf("bad: %v", err)
  4084  	}
  4085  
  4086  	err = state.UpsertAllocs(1002, []*structs.Allocation{alloc2})
  4087  	if err != nil {
  4088  		t.Fatalf("err: %v", err)
  4089  	}
  4090  
  4091  	for i, ws := range watches {
  4092  		if !watchFired(ws) {
  4093  			t.Fatalf("bad %d", i)
  4094  		}
  4095  	}
  4096  
  4097  	ws = memdb.NewWatchSet()
  4098  	out, err := state.AllocByID(ws, alloc.ID)
  4099  	if err != nil {
  4100  		t.Fatalf("err: %v", err)
  4101  	}
  4102  
  4103  	if !reflect.DeepEqual(alloc2, out) {
  4104  		t.Fatalf("bad: %#v %#v", alloc2, out)
  4105  	}
  4106  
  4107  	if out.CreateIndex != 1000 {
  4108  		t.Fatalf("bad: %#v", out)
  4109  	}
  4110  	if out.ModifyIndex != 1002 {
  4111  		t.Fatalf("bad: %#v", out)
  4112  	}
  4113  
  4114  	index, err := state.Index("allocs")
  4115  	if err != nil {
  4116  		t.Fatalf("err: %v", err)
  4117  	}
  4118  	if index != 1002 {
  4119  		t.Fatalf("bad: %d", index)
  4120  	}
  4121  
  4122  	// Ensure that summary hasb't changed
  4123  	summary, err = state.JobSummaryByID(ws, alloc.Namespace, alloc.JobID)
  4124  	if err != nil {
  4125  		t.Fatalf("err: %v", err)
  4126  	}
  4127  	tgSummary = summary.Summary["web"]
  4128  	if tgSummary.Starting != 1 {
  4129  		t.Fatalf("expected starting: %v, actual: %v", 1, tgSummary.Starting)
  4130  	}
  4131  
  4132  	if watchFired(ws) {
  4133  		t.Fatalf("bad")
  4134  	}
  4135  }
  4136  
  4137  // This test ensures that the state store will mark the clients status as lost
  4138  // when set rather than preferring the existing status.
  4139  func TestStateStore_UpdateAlloc_Lost(t *testing.T) {
  4140  	state := testStateStore(t)
  4141  	alloc := mock.Alloc()
  4142  	alloc.ClientStatus = "foo"
  4143  
  4144  	if err := state.UpsertJob(999, alloc.Job); err != nil {
  4145  		t.Fatalf("err: %v", err)
  4146  	}
  4147  
  4148  	err := state.UpsertAllocs(1000, []*structs.Allocation{alloc})
  4149  	if err != nil {
  4150  		t.Fatalf("err: %v", err)
  4151  	}
  4152  
  4153  	alloc2 := new(structs.Allocation)
  4154  	*alloc2 = *alloc
  4155  	alloc2.ClientStatus = structs.AllocClientStatusLost
  4156  	if err := state.UpsertAllocs(1001, []*structs.Allocation{alloc2}); err != nil {
  4157  		t.Fatalf("err: %v", err)
  4158  	}
  4159  
  4160  	ws := memdb.NewWatchSet()
  4161  	out, err := state.AllocByID(ws, alloc2.ID)
  4162  	if err != nil {
  4163  		t.Fatalf("err: %v", err)
  4164  	}
  4165  
  4166  	if out.ClientStatus != structs.AllocClientStatusLost {
  4167  		t.Fatalf("bad: %#v", out)
  4168  	}
  4169  }
  4170  
  4171  // This test ensures an allocation can be updated when there is no job
  4172  // associated with it. This will happen when a job is stopped by an user which
  4173  // has non-terminal allocations on clients
  4174  func TestStateStore_UpdateAlloc_NoJob(t *testing.T) {
  4175  	state := testStateStore(t)
  4176  	alloc := mock.Alloc()
  4177  
  4178  	// Upsert a job
  4179  	state.UpsertJobSummary(998, mock.JobSummary(alloc.JobID))
  4180  	if err := state.UpsertJob(999, alloc.Job); err != nil {
  4181  		t.Fatalf("err: %v", err)
  4182  	}
  4183  
  4184  	err := state.UpsertAllocs(1000, []*structs.Allocation{alloc})
  4185  	if err != nil {
  4186  		t.Fatalf("err: %v", err)
  4187  	}
  4188  
  4189  	if err := state.DeleteJob(1001, alloc.Namespace, alloc.JobID); err != nil {
  4190  		t.Fatalf("err: %v", err)
  4191  	}
  4192  
  4193  	// Update the desired state of the allocation to stop
  4194  	allocCopy := alloc.Copy()
  4195  	allocCopy.DesiredStatus = structs.AllocDesiredStatusStop
  4196  	if err := state.UpsertAllocs(1002, []*structs.Allocation{allocCopy}); err != nil {
  4197  		t.Fatalf("err: %v", err)
  4198  	}
  4199  
  4200  	// Update the client state of the allocation to complete
  4201  	allocCopy1 := allocCopy.Copy()
  4202  	allocCopy1.ClientStatus = structs.AllocClientStatusComplete
  4203  	if err := state.UpdateAllocsFromClient(1003, []*structs.Allocation{allocCopy1}); err != nil {
  4204  		t.Fatalf("err: %v", err)
  4205  	}
  4206  
  4207  	ws := memdb.NewWatchSet()
  4208  	out, _ := state.AllocByID(ws, alloc.ID)
  4209  	// Update the modify index of the alloc before comparing
  4210  	allocCopy1.ModifyIndex = 1003
  4211  	if !reflect.DeepEqual(out, allocCopy1) {
  4212  		t.Fatalf("expected: %#v \n actual: %#v", allocCopy1, out)
  4213  	}
  4214  }
  4215  
  4216  func TestStateStore_UpdateAllocDesiredTransition(t *testing.T) {
  4217  	t.Parallel()
  4218  	require := require.New(t)
  4219  
  4220  	state := testStateStore(t)
  4221  	alloc := mock.Alloc()
  4222  
  4223  	require.Nil(state.UpsertJob(999, alloc.Job))
  4224  	require.Nil(state.UpsertAllocs(1000, []*structs.Allocation{alloc}))
  4225  
  4226  	t1 := &structs.DesiredTransition{
  4227  		Migrate: helper.BoolToPtr(true),
  4228  	}
  4229  	t2 := &structs.DesiredTransition{
  4230  		Migrate: helper.BoolToPtr(false),
  4231  	}
  4232  	eval := &structs.Evaluation{
  4233  		ID:             uuid.Generate(),
  4234  		Namespace:      alloc.Namespace,
  4235  		Priority:       alloc.Job.Priority,
  4236  		Type:           alloc.Job.Type,
  4237  		TriggeredBy:    structs.EvalTriggerNodeDrain,
  4238  		JobID:          alloc.Job.ID,
  4239  		JobModifyIndex: alloc.Job.ModifyIndex,
  4240  		Status:         structs.EvalStatusPending,
  4241  	}
  4242  	evals := []*structs.Evaluation{eval}
  4243  
  4244  	m := map[string]*structs.DesiredTransition{alloc.ID: t1}
  4245  	require.Nil(state.UpdateAllocsDesiredTransitions(1001, m, evals))
  4246  
  4247  	ws := memdb.NewWatchSet()
  4248  	out, err := state.AllocByID(ws, alloc.ID)
  4249  	require.Nil(err)
  4250  	require.NotNil(out.DesiredTransition.Migrate)
  4251  	require.True(*out.DesiredTransition.Migrate)
  4252  	require.EqualValues(1000, out.CreateIndex)
  4253  	require.EqualValues(1001, out.ModifyIndex)
  4254  
  4255  	index, err := state.Index("allocs")
  4256  	require.Nil(err)
  4257  	require.EqualValues(1001, index)
  4258  
  4259  	// Check the eval is created
  4260  	eout, err := state.EvalByID(nil, eval.ID)
  4261  	require.Nil(err)
  4262  	require.NotNil(eout)
  4263  
  4264  	m = map[string]*structs.DesiredTransition{alloc.ID: t2}
  4265  	require.Nil(state.UpdateAllocsDesiredTransitions(1002, m, evals))
  4266  
  4267  	ws = memdb.NewWatchSet()
  4268  	out, err = state.AllocByID(ws, alloc.ID)
  4269  	require.Nil(err)
  4270  	require.NotNil(out.DesiredTransition.Migrate)
  4271  	require.False(*out.DesiredTransition.Migrate)
  4272  	require.EqualValues(1000, out.CreateIndex)
  4273  	require.EqualValues(1002, out.ModifyIndex)
  4274  
  4275  	index, err = state.Index("allocs")
  4276  	require.Nil(err)
  4277  	require.EqualValues(1002, index)
  4278  
  4279  	// Try with a bogus alloc id
  4280  	m = map[string]*structs.DesiredTransition{uuid.Generate(): t2}
  4281  	require.Nil(state.UpdateAllocsDesiredTransitions(1003, m, evals))
  4282  }
  4283  
  4284  func TestStateStore_JobSummary(t *testing.T) {
  4285  	state := testStateStore(t)
  4286  
  4287  	// Add a job
  4288  	job := mock.Job()
  4289  	state.UpsertJob(900, job)
  4290  
  4291  	// Get the job back
  4292  	ws := memdb.NewWatchSet()
  4293  	outJob, _ := state.JobByID(ws, job.Namespace, job.ID)
  4294  	if outJob.CreateIndex != 900 {
  4295  		t.Fatalf("bad create index: %v", outJob.CreateIndex)
  4296  	}
  4297  	summary, _ := state.JobSummaryByID(ws, job.Namespace, job.ID)
  4298  	if summary.CreateIndex != 900 {
  4299  		t.Fatalf("bad create index: %v", summary.CreateIndex)
  4300  	}
  4301  
  4302  	// Upsert an allocation
  4303  	alloc := mock.Alloc()
  4304  	alloc.JobID = job.ID
  4305  	alloc.Job = job
  4306  	state.UpsertAllocs(910, []*structs.Allocation{alloc})
  4307  
  4308  	// Update the alloc from client
  4309  	alloc1 := alloc.Copy()
  4310  	alloc1.ClientStatus = structs.AllocClientStatusPending
  4311  	alloc1.DesiredStatus = ""
  4312  	state.UpdateAllocsFromClient(920, []*structs.Allocation{alloc})
  4313  
  4314  	alloc3 := alloc.Copy()
  4315  	alloc3.ClientStatus = structs.AllocClientStatusRunning
  4316  	alloc3.DesiredStatus = ""
  4317  	state.UpdateAllocsFromClient(930, []*structs.Allocation{alloc3})
  4318  
  4319  	// Upsert the alloc
  4320  	alloc4 := alloc.Copy()
  4321  	alloc4.ClientStatus = structs.AllocClientStatusPending
  4322  	alloc4.DesiredStatus = structs.AllocDesiredStatusRun
  4323  	state.UpsertAllocs(950, []*structs.Allocation{alloc4})
  4324  
  4325  	// Again upsert the alloc
  4326  	alloc5 := alloc.Copy()
  4327  	alloc5.ClientStatus = structs.AllocClientStatusPending
  4328  	alloc5.DesiredStatus = structs.AllocDesiredStatusRun
  4329  	state.UpsertAllocs(970, []*structs.Allocation{alloc5})
  4330  
  4331  	if !watchFired(ws) {
  4332  		t.Fatalf("bad")
  4333  	}
  4334  
  4335  	expectedSummary := structs.JobSummary{
  4336  		JobID:     job.ID,
  4337  		Namespace: job.Namespace,
  4338  		Summary: map[string]structs.TaskGroupSummary{
  4339  			"web": {
  4340  				Running: 1,
  4341  			},
  4342  		},
  4343  		Children:    new(structs.JobChildrenSummary),
  4344  		CreateIndex: 900,
  4345  		ModifyIndex: 930,
  4346  	}
  4347  
  4348  	summary, _ = state.JobSummaryByID(ws, job.Namespace, job.ID)
  4349  	if !reflect.DeepEqual(&expectedSummary, summary) {
  4350  		t.Fatalf("expected: %#v, actual: %v", expectedSummary, summary)
  4351  	}
  4352  
  4353  	// De-register the job.
  4354  	state.DeleteJob(980, job.Namespace, job.ID)
  4355  
  4356  	// Shouldn't have any effect on the summary
  4357  	alloc6 := alloc.Copy()
  4358  	alloc6.ClientStatus = structs.AllocClientStatusRunning
  4359  	alloc6.DesiredStatus = ""
  4360  	state.UpdateAllocsFromClient(990, []*structs.Allocation{alloc6})
  4361  
  4362  	// We shouldn't have any summary at this point
  4363  	summary, _ = state.JobSummaryByID(ws, job.Namespace, job.ID)
  4364  	if summary != nil {
  4365  		t.Fatalf("expected nil, actual: %#v", summary)
  4366  	}
  4367  
  4368  	// Re-register the same job
  4369  	job1 := mock.Job()
  4370  	job1.ID = job.ID
  4371  	state.UpsertJob(1000, job1)
  4372  	outJob2, _ := state.JobByID(ws, job1.Namespace, job1.ID)
  4373  	if outJob2.CreateIndex != 1000 {
  4374  		t.Fatalf("bad create index: %v", outJob2.CreateIndex)
  4375  	}
  4376  	summary, _ = state.JobSummaryByID(ws, job1.Namespace, job1.ID)
  4377  	if summary.CreateIndex != 1000 {
  4378  		t.Fatalf("bad create index: %v", summary.CreateIndex)
  4379  	}
  4380  
  4381  	// Upsert an allocation
  4382  	alloc7 := alloc.Copy()
  4383  	alloc7.JobID = outJob.ID
  4384  	alloc7.Job = outJob
  4385  	alloc7.ClientStatus = structs.AllocClientStatusComplete
  4386  	alloc7.DesiredStatus = structs.AllocDesiredStatusRun
  4387  	state.UpdateAllocsFromClient(1020, []*structs.Allocation{alloc7})
  4388  
  4389  	expectedSummary = structs.JobSummary{
  4390  		JobID:     job.ID,
  4391  		Namespace: job.Namespace,
  4392  		Summary: map[string]structs.TaskGroupSummary{
  4393  			"web": {},
  4394  		},
  4395  		Children:    new(structs.JobChildrenSummary),
  4396  		CreateIndex: 1000,
  4397  		ModifyIndex: 1000,
  4398  	}
  4399  
  4400  	summary, _ = state.JobSummaryByID(ws, job1.Namespace, job1.ID)
  4401  	if !reflect.DeepEqual(&expectedSummary, summary) {
  4402  		t.Fatalf("expected: %#v, actual: %#v", expectedSummary, summary)
  4403  	}
  4404  }
  4405  
  4406  func TestStateStore_ReconcileJobSummary(t *testing.T) {
  4407  	state := testStateStore(t)
  4408  
  4409  	// Create an alloc
  4410  	alloc := mock.Alloc()
  4411  
  4412  	// Add another task group to the job
  4413  	tg2 := alloc.Job.TaskGroups[0].Copy()
  4414  	tg2.Name = "db"
  4415  	alloc.Job.TaskGroups = append(alloc.Job.TaskGroups, tg2)
  4416  	state.UpsertJob(100, alloc.Job)
  4417  
  4418  	// Create one more alloc for the db task group
  4419  	alloc2 := mock.Alloc()
  4420  	alloc2.TaskGroup = "db"
  4421  	alloc2.JobID = alloc.JobID
  4422  	alloc2.Job = alloc.Job
  4423  
  4424  	// Upserts the alloc
  4425  	state.UpsertAllocs(110, []*structs.Allocation{alloc, alloc2})
  4426  
  4427  	// Change the state of the first alloc to running
  4428  	alloc3 := alloc.Copy()
  4429  	alloc3.ClientStatus = structs.AllocClientStatusRunning
  4430  	state.UpdateAllocsFromClient(120, []*structs.Allocation{alloc3})
  4431  
  4432  	//Add some more allocs to the second tg
  4433  	alloc4 := mock.Alloc()
  4434  	alloc4.JobID = alloc.JobID
  4435  	alloc4.Job = alloc.Job
  4436  	alloc4.TaskGroup = "db"
  4437  	alloc5 := alloc4.Copy()
  4438  	alloc5.ClientStatus = structs.AllocClientStatusRunning
  4439  
  4440  	alloc6 := mock.Alloc()
  4441  	alloc6.JobID = alloc.JobID
  4442  	alloc6.Job = alloc.Job
  4443  	alloc6.TaskGroup = "db"
  4444  	alloc7 := alloc6.Copy()
  4445  	alloc7.ClientStatus = structs.AllocClientStatusComplete
  4446  
  4447  	alloc8 := mock.Alloc()
  4448  	alloc8.JobID = alloc.JobID
  4449  	alloc8.Job = alloc.Job
  4450  	alloc8.TaskGroup = "db"
  4451  	alloc9 := alloc8.Copy()
  4452  	alloc9.ClientStatus = structs.AllocClientStatusFailed
  4453  
  4454  	alloc10 := mock.Alloc()
  4455  	alloc10.JobID = alloc.JobID
  4456  	alloc10.Job = alloc.Job
  4457  	alloc10.TaskGroup = "db"
  4458  	alloc11 := alloc10.Copy()
  4459  	alloc11.ClientStatus = structs.AllocClientStatusLost
  4460  
  4461  	state.UpsertAllocs(130, []*structs.Allocation{alloc4, alloc6, alloc8, alloc10})
  4462  
  4463  	state.UpdateAllocsFromClient(150, []*structs.Allocation{alloc5, alloc7, alloc9, alloc11})
  4464  
  4465  	// DeleteJobSummary is a helper method and doesn't modify the indexes table
  4466  	state.DeleteJobSummary(130, alloc.Namespace, alloc.Job.ID)
  4467  
  4468  	state.ReconcileJobSummaries(120)
  4469  
  4470  	ws := memdb.NewWatchSet()
  4471  	summary, _ := state.JobSummaryByID(ws, alloc.Namespace, alloc.Job.ID)
  4472  	expectedSummary := structs.JobSummary{
  4473  		JobID:     alloc.Job.ID,
  4474  		Namespace: alloc.Namespace,
  4475  		Summary: map[string]structs.TaskGroupSummary{
  4476  			"web": {
  4477  				Running: 1,
  4478  			},
  4479  			"db": {
  4480  				Starting: 1,
  4481  				Running:  1,
  4482  				Failed:   1,
  4483  				Complete: 1,
  4484  				Lost:     1,
  4485  			},
  4486  		},
  4487  		CreateIndex: 100,
  4488  		ModifyIndex: 120,
  4489  	}
  4490  	if !reflect.DeepEqual(&expectedSummary, summary) {
  4491  		t.Fatalf("expected: %v, actual: %v", expectedSummary, summary)
  4492  	}
  4493  }
  4494  
  4495  func TestStateStore_ReconcileParentJobSummary(t *testing.T) {
  4496  	t.Parallel()
  4497  	require := require.New(t)
  4498  	state := testStateStore(t)
  4499  
  4500  	// Add a node
  4501  	node := mock.Node()
  4502  	state.UpsertNode(80, node)
  4503  
  4504  	// Make a parameterized job
  4505  	job1 := mock.BatchJob()
  4506  	job1.ID = "test"
  4507  	job1.ParameterizedJob = &structs.ParameterizedJobConfig{
  4508  		Payload: "random",
  4509  	}
  4510  	job1.TaskGroups[0].Count = 1
  4511  	state.UpsertJob(100, job1)
  4512  
  4513  	// Make a child job
  4514  	childJob := job1.Copy()
  4515  	childJob.ID = job1.ID + "dispatch-23423423"
  4516  	childJob.ParentID = job1.ID
  4517  	childJob.Dispatched = true
  4518  	childJob.Status = structs.JobStatusRunning
  4519  
  4520  	// Make some allocs for child job
  4521  	alloc := mock.Alloc()
  4522  	alloc.NodeID = node.ID
  4523  	alloc.Job = childJob
  4524  	alloc.JobID = childJob.ID
  4525  	alloc.ClientStatus = structs.AllocClientStatusRunning
  4526  
  4527  	alloc2 := mock.Alloc()
  4528  	alloc2.NodeID = node.ID
  4529  	alloc2.Job = childJob
  4530  	alloc2.JobID = childJob.ID
  4531  	alloc2.ClientStatus = structs.AllocClientStatusFailed
  4532  
  4533  	require.Nil(state.UpsertJob(110, childJob))
  4534  	require.Nil(state.UpsertAllocs(111, []*structs.Allocation{alloc, alloc2}))
  4535  
  4536  	// Make the summary incorrect in the state store
  4537  	summary, err := state.JobSummaryByID(nil, job1.Namespace, job1.ID)
  4538  	require.Nil(err)
  4539  
  4540  	summary.Children = nil
  4541  	summary.Summary = make(map[string]structs.TaskGroupSummary)
  4542  	summary.Summary["web"] = structs.TaskGroupSummary{
  4543  		Queued: 1,
  4544  	}
  4545  
  4546  	// Delete the child job summary
  4547  	state.DeleteJobSummary(125, childJob.Namespace, childJob.ID)
  4548  
  4549  	state.ReconcileJobSummaries(120)
  4550  
  4551  	ws := memdb.NewWatchSet()
  4552  
  4553  	// Verify parent summary is corrected
  4554  	summary, _ = state.JobSummaryByID(ws, alloc.Namespace, job1.ID)
  4555  	expectedSummary := structs.JobSummary{
  4556  		JobID:     job1.ID,
  4557  		Namespace: job1.Namespace,
  4558  		Summary:   make(map[string]structs.TaskGroupSummary),
  4559  		Children: &structs.JobChildrenSummary{
  4560  			Running: 1,
  4561  		},
  4562  		CreateIndex: 100,
  4563  		ModifyIndex: 120,
  4564  	}
  4565  	require.Equal(&expectedSummary, summary)
  4566  
  4567  	// Verify child job summary is also correct
  4568  	childSummary, _ := state.JobSummaryByID(ws, childJob.Namespace, childJob.ID)
  4569  	expectedChildSummary := structs.JobSummary{
  4570  		JobID:     childJob.ID,
  4571  		Namespace: childJob.Namespace,
  4572  		Summary: map[string]structs.TaskGroupSummary{
  4573  			"web": {
  4574  				Running: 1,
  4575  				Failed:  1,
  4576  			},
  4577  		},
  4578  		CreateIndex: 110,
  4579  		ModifyIndex: 120,
  4580  	}
  4581  	require.Equal(&expectedChildSummary, childSummary)
  4582  }
  4583  
  4584  func TestStateStore_UpdateAlloc_JobNotPresent(t *testing.T) {
  4585  	state := testStateStore(t)
  4586  
  4587  	alloc := mock.Alloc()
  4588  	state.UpsertJob(100, alloc.Job)
  4589  	state.UpsertAllocs(200, []*structs.Allocation{alloc})
  4590  
  4591  	// Delete the job
  4592  	state.DeleteJob(300, alloc.Namespace, alloc.Job.ID)
  4593  
  4594  	// Update the alloc
  4595  	alloc1 := alloc.Copy()
  4596  	alloc1.ClientStatus = structs.AllocClientStatusRunning
  4597  
  4598  	// Updating allocation should not throw any error
  4599  	if err := state.UpdateAllocsFromClient(400, []*structs.Allocation{alloc1}); err != nil {
  4600  		t.Fatalf("expect err: %v", err)
  4601  	}
  4602  
  4603  	// Re-Register the job
  4604  	state.UpsertJob(500, alloc.Job)
  4605  
  4606  	// Update the alloc again
  4607  	alloc2 := alloc.Copy()
  4608  	alloc2.ClientStatus = structs.AllocClientStatusComplete
  4609  	if err := state.UpdateAllocsFromClient(400, []*structs.Allocation{alloc1}); err != nil {
  4610  		t.Fatalf("expect err: %v", err)
  4611  	}
  4612  
  4613  	// Job Summary of the newly registered job shouldn't account for the
  4614  	// allocation update for the older job
  4615  	expectedSummary := structs.JobSummary{
  4616  		JobID:     alloc1.JobID,
  4617  		Namespace: alloc1.Namespace,
  4618  		Summary: map[string]structs.TaskGroupSummary{
  4619  			"web": {},
  4620  		},
  4621  		Children:    new(structs.JobChildrenSummary),
  4622  		CreateIndex: 500,
  4623  		ModifyIndex: 500,
  4624  	}
  4625  
  4626  	ws := memdb.NewWatchSet()
  4627  	summary, _ := state.JobSummaryByID(ws, alloc.Namespace, alloc.Job.ID)
  4628  	if !reflect.DeepEqual(&expectedSummary, summary) {
  4629  		t.Fatalf("expected: %v, actual: %v", expectedSummary, summary)
  4630  	}
  4631  }
  4632  
  4633  func TestStateStore_EvictAlloc_Alloc(t *testing.T) {
  4634  	state := testStateStore(t)
  4635  	alloc := mock.Alloc()
  4636  
  4637  	state.UpsertJobSummary(999, mock.JobSummary(alloc.JobID))
  4638  	err := state.UpsertAllocs(1000, []*structs.Allocation{alloc})
  4639  	if err != nil {
  4640  		t.Fatalf("err: %v", err)
  4641  	}
  4642  
  4643  	alloc2 := new(structs.Allocation)
  4644  	*alloc2 = *alloc
  4645  	alloc2.DesiredStatus = structs.AllocDesiredStatusEvict
  4646  	err = state.UpsertAllocs(1001, []*structs.Allocation{alloc2})
  4647  	if err != nil {
  4648  		t.Fatalf("err: %v", err)
  4649  	}
  4650  
  4651  	ws := memdb.NewWatchSet()
  4652  	out, err := state.AllocByID(ws, alloc.ID)
  4653  	if err != nil {
  4654  		t.Fatalf("err: %v", err)
  4655  	}
  4656  
  4657  	if out.DesiredStatus != structs.AllocDesiredStatusEvict {
  4658  		t.Fatalf("bad: %#v %#v", alloc, out)
  4659  	}
  4660  
  4661  	index, err := state.Index("allocs")
  4662  	if err != nil {
  4663  		t.Fatalf("err: %v", err)
  4664  	}
  4665  	if index != 1001 {
  4666  		t.Fatalf("bad: %d", index)
  4667  	}
  4668  }
  4669  
  4670  func TestStateStore_AllocsByNode(t *testing.T) {
  4671  	state := testStateStore(t)
  4672  	var allocs []*structs.Allocation
  4673  
  4674  	for i := 0; i < 10; i++ {
  4675  		alloc := mock.Alloc()
  4676  		alloc.NodeID = "foo"
  4677  		allocs = append(allocs, alloc)
  4678  	}
  4679  
  4680  	for idx, alloc := range allocs {
  4681  		state.UpsertJobSummary(uint64(900+idx), mock.JobSummary(alloc.JobID))
  4682  	}
  4683  
  4684  	err := state.UpsertAllocs(1000, allocs)
  4685  	if err != nil {
  4686  		t.Fatalf("err: %v", err)
  4687  	}
  4688  
  4689  	ws := memdb.NewWatchSet()
  4690  	out, err := state.AllocsByNode(ws, "foo")
  4691  	if err != nil {
  4692  		t.Fatalf("err: %v", err)
  4693  	}
  4694  
  4695  	sort.Sort(AllocIDSort(allocs))
  4696  	sort.Sort(AllocIDSort(out))
  4697  
  4698  	if !reflect.DeepEqual(allocs, out) {
  4699  		t.Fatalf("bad: %#v %#v", allocs, out)
  4700  	}
  4701  
  4702  	if watchFired(ws) {
  4703  		t.Fatalf("bad")
  4704  	}
  4705  }
  4706  
  4707  func TestStateStore_AllocsByNodeTerminal(t *testing.T) {
  4708  	state := testStateStore(t)
  4709  	var allocs, term, nonterm []*structs.Allocation
  4710  
  4711  	for i := 0; i < 10; i++ {
  4712  		alloc := mock.Alloc()
  4713  		alloc.NodeID = "foo"
  4714  		if i%2 == 0 {
  4715  			alloc.DesiredStatus = structs.AllocDesiredStatusStop
  4716  			term = append(term, alloc)
  4717  		} else {
  4718  			nonterm = append(nonterm, alloc)
  4719  		}
  4720  		allocs = append(allocs, alloc)
  4721  	}
  4722  
  4723  	for idx, alloc := range allocs {
  4724  		state.UpsertJobSummary(uint64(900+idx), mock.JobSummary(alloc.JobID))
  4725  	}
  4726  
  4727  	err := state.UpsertAllocs(1000, allocs)
  4728  	if err != nil {
  4729  		t.Fatalf("err: %v", err)
  4730  	}
  4731  
  4732  	// Verify the terminal allocs
  4733  	ws := memdb.NewWatchSet()
  4734  	out, err := state.AllocsByNodeTerminal(ws, "foo", true)
  4735  	if err != nil {
  4736  		t.Fatalf("err: %v", err)
  4737  	}
  4738  
  4739  	sort.Sort(AllocIDSort(term))
  4740  	sort.Sort(AllocIDSort(out))
  4741  
  4742  	if !reflect.DeepEqual(term, out) {
  4743  		t.Fatalf("bad: %#v %#v", term, out)
  4744  	}
  4745  
  4746  	// Verify the non-terminal allocs
  4747  	out, err = state.AllocsByNodeTerminal(ws, "foo", false)
  4748  	if err != nil {
  4749  		t.Fatalf("err: %v", err)
  4750  	}
  4751  
  4752  	sort.Sort(AllocIDSort(nonterm))
  4753  	sort.Sort(AllocIDSort(out))
  4754  
  4755  	if !reflect.DeepEqual(nonterm, out) {
  4756  		t.Fatalf("bad: %#v %#v", nonterm, out)
  4757  	}
  4758  
  4759  	if watchFired(ws) {
  4760  		t.Fatalf("bad")
  4761  	}
  4762  }
  4763  
  4764  func TestStateStore_AllocsByJob(t *testing.T) {
  4765  	state := testStateStore(t)
  4766  	var allocs []*structs.Allocation
  4767  
  4768  	for i := 0; i < 10; i++ {
  4769  		alloc := mock.Alloc()
  4770  		alloc.JobID = "foo"
  4771  		allocs = append(allocs, alloc)
  4772  	}
  4773  
  4774  	for i, alloc := range allocs {
  4775  		state.UpsertJobSummary(uint64(900+i), mock.JobSummary(alloc.JobID))
  4776  	}
  4777  
  4778  	err := state.UpsertAllocs(1000, allocs)
  4779  	if err != nil {
  4780  		t.Fatalf("err: %v", err)
  4781  	}
  4782  
  4783  	ws := memdb.NewWatchSet()
  4784  	out, err := state.AllocsByJob(ws, mock.Alloc().Namespace, "foo", false)
  4785  	if err != nil {
  4786  		t.Fatalf("err: %v", err)
  4787  	}
  4788  
  4789  	sort.Sort(AllocIDSort(allocs))
  4790  	sort.Sort(AllocIDSort(out))
  4791  
  4792  	if !reflect.DeepEqual(allocs, out) {
  4793  		t.Fatalf("bad: %#v %#v", allocs, out)
  4794  	}
  4795  
  4796  	if watchFired(ws) {
  4797  		t.Fatalf("bad")
  4798  	}
  4799  }
  4800  
  4801  func TestStateStore_AllocsForRegisteredJob(t *testing.T) {
  4802  	state := testStateStore(t)
  4803  	var allocs []*structs.Allocation
  4804  	var allocs1 []*structs.Allocation
  4805  
  4806  	job := mock.Job()
  4807  	job.ID = "foo"
  4808  	state.UpsertJob(100, job)
  4809  	for i := 0; i < 3; i++ {
  4810  		alloc := mock.Alloc()
  4811  		alloc.Job = job
  4812  		alloc.JobID = job.ID
  4813  		allocs = append(allocs, alloc)
  4814  	}
  4815  	if err := state.UpsertAllocs(200, allocs); err != nil {
  4816  		t.Fatalf("err: %v", err)
  4817  	}
  4818  
  4819  	if err := state.DeleteJob(250, job.Namespace, job.ID); err != nil {
  4820  		t.Fatalf("err: %v", err)
  4821  	}
  4822  
  4823  	job1 := mock.Job()
  4824  	job1.ID = "foo"
  4825  	job1.CreateIndex = 50
  4826  	state.UpsertJob(300, job1)
  4827  	for i := 0; i < 4; i++ {
  4828  		alloc := mock.Alloc()
  4829  		alloc.Job = job1
  4830  		alloc.JobID = job1.ID
  4831  		allocs1 = append(allocs1, alloc)
  4832  	}
  4833  
  4834  	if err := state.UpsertAllocs(1000, allocs1); err != nil {
  4835  		t.Fatalf("err: %v", err)
  4836  	}
  4837  
  4838  	ws := memdb.NewWatchSet()
  4839  	out, err := state.AllocsByJob(ws, job1.Namespace, job1.ID, true)
  4840  	if err != nil {
  4841  		t.Fatalf("err: %v", err)
  4842  	}
  4843  
  4844  	expected := len(allocs) + len(allocs1)
  4845  	if len(out) != expected {
  4846  		t.Fatalf("expected: %v, actual: %v", expected, len(out))
  4847  	}
  4848  
  4849  	out1, err := state.AllocsByJob(ws, job1.Namespace, job1.ID, false)
  4850  	if err != nil {
  4851  		t.Fatalf("bad: %v", err)
  4852  	}
  4853  
  4854  	expected = len(allocs1)
  4855  	if len(out1) != expected {
  4856  		t.Fatalf("expected: %v, actual: %v", expected, len(out1))
  4857  	}
  4858  
  4859  	if watchFired(ws) {
  4860  		t.Fatalf("bad")
  4861  	}
  4862  }
  4863  
  4864  func TestStateStore_AllocsByIDPrefix(t *testing.T) {
  4865  	state := testStateStore(t)
  4866  	var allocs []*structs.Allocation
  4867  
  4868  	ids := []string{
  4869  		"aaaaaaaa-7bfb-395d-eb95-0685af2176b2",
  4870  		"aaaaaaab-7bfb-395d-eb95-0685af2176b2",
  4871  		"aaaaaabb-7bfb-395d-eb95-0685af2176b2",
  4872  		"aaaaabbb-7bfb-395d-eb95-0685af2176b2",
  4873  		"aaaabbbb-7bfb-395d-eb95-0685af2176b2",
  4874  		"aaabbbbb-7bfb-395d-eb95-0685af2176b2",
  4875  		"aabbbbbb-7bfb-395d-eb95-0685af2176b2",
  4876  		"abbbbbbb-7bfb-395d-eb95-0685af2176b2",
  4877  		"bbbbbbbb-7bfb-395d-eb95-0685af2176b2",
  4878  	}
  4879  	for i := 0; i < 9; i++ {
  4880  		alloc := mock.Alloc()
  4881  		alloc.ID = ids[i]
  4882  		allocs = append(allocs, alloc)
  4883  	}
  4884  
  4885  	for i, alloc := range allocs {
  4886  		state.UpsertJobSummary(uint64(900+i), mock.JobSummary(alloc.JobID))
  4887  	}
  4888  
  4889  	err := state.UpsertAllocs(1000, allocs)
  4890  	if err != nil {
  4891  		t.Fatalf("err: %v", err)
  4892  	}
  4893  
  4894  	ws := memdb.NewWatchSet()
  4895  	iter, err := state.AllocsByIDPrefix(ws, structs.DefaultNamespace, "aaaa")
  4896  	if err != nil {
  4897  		t.Fatalf("err: %v", err)
  4898  	}
  4899  
  4900  	gatherAllocs := func(iter memdb.ResultIterator) []*structs.Allocation {
  4901  		var allocs []*structs.Allocation
  4902  		for {
  4903  			raw := iter.Next()
  4904  			if raw == nil {
  4905  				break
  4906  			}
  4907  			allocs = append(allocs, raw.(*structs.Allocation))
  4908  		}
  4909  		return allocs
  4910  	}
  4911  
  4912  	out := gatherAllocs(iter)
  4913  	if len(out) != 5 {
  4914  		t.Fatalf("bad: expected five allocations, got: %#v", out)
  4915  	}
  4916  
  4917  	sort.Sort(AllocIDSort(allocs))
  4918  
  4919  	for index, alloc := range out {
  4920  		if ids[index] != alloc.ID {
  4921  			t.Fatalf("bad: got unexpected id: %s", alloc.ID)
  4922  		}
  4923  	}
  4924  
  4925  	iter, err = state.AllocsByIDPrefix(ws, structs.DefaultNamespace, "b-a7bfb")
  4926  	if err != nil {
  4927  		t.Fatalf("err: %v", err)
  4928  	}
  4929  
  4930  	out = gatherAllocs(iter)
  4931  	if len(out) != 0 {
  4932  		t.Fatalf("bad: unexpected zero allocations, got: %#v", out)
  4933  	}
  4934  
  4935  	if watchFired(ws) {
  4936  		t.Fatalf("bad")
  4937  	}
  4938  }
  4939  
  4940  func TestStateStore_Allocs(t *testing.T) {
  4941  	state := testStateStore(t)
  4942  	var allocs []*structs.Allocation
  4943  
  4944  	for i := 0; i < 10; i++ {
  4945  		alloc := mock.Alloc()
  4946  		allocs = append(allocs, alloc)
  4947  	}
  4948  	for i, alloc := range allocs {
  4949  		state.UpsertJobSummary(uint64(900+i), mock.JobSummary(alloc.JobID))
  4950  	}
  4951  
  4952  	err := state.UpsertAllocs(1000, allocs)
  4953  	if err != nil {
  4954  		t.Fatalf("err: %v", err)
  4955  	}
  4956  
  4957  	ws := memdb.NewWatchSet()
  4958  	iter, err := state.Allocs(ws)
  4959  	if err != nil {
  4960  		t.Fatalf("err: %v", err)
  4961  	}
  4962  
  4963  	var out []*structs.Allocation
  4964  	for {
  4965  		raw := iter.Next()
  4966  		if raw == nil {
  4967  			break
  4968  		}
  4969  		out = append(out, raw.(*structs.Allocation))
  4970  	}
  4971  
  4972  	sort.Sort(AllocIDSort(allocs))
  4973  	sort.Sort(AllocIDSort(out))
  4974  
  4975  	if !reflect.DeepEqual(allocs, out) {
  4976  		t.Fatalf("bad: %#v %#v", allocs, out)
  4977  	}
  4978  
  4979  	if watchFired(ws) {
  4980  		t.Fatalf("bad")
  4981  	}
  4982  }
  4983  
  4984  func TestStateStore_Allocs_PrevAlloc(t *testing.T) {
  4985  	state := testStateStore(t)
  4986  	var allocs []*structs.Allocation
  4987  
  4988  	require := require.New(t)
  4989  	for i := 0; i < 5; i++ {
  4990  		alloc := mock.Alloc()
  4991  		allocs = append(allocs, alloc)
  4992  	}
  4993  	for i, alloc := range allocs {
  4994  		state.UpsertJobSummary(uint64(900+i), mock.JobSummary(alloc.JobID))
  4995  	}
  4996  	// Set some previous alloc ids
  4997  	allocs[1].PreviousAllocation = allocs[0].ID
  4998  	allocs[2].PreviousAllocation = allocs[1].ID
  4999  
  5000  	err := state.UpsertAllocs(1000, allocs)
  5001  	require.Nil(err)
  5002  
  5003  	ws := memdb.NewWatchSet()
  5004  	iter, err := state.Allocs(ws)
  5005  	require.Nil(err)
  5006  
  5007  	var out []*structs.Allocation
  5008  	for {
  5009  		raw := iter.Next()
  5010  		if raw == nil {
  5011  			break
  5012  		}
  5013  		out = append(out, raw.(*structs.Allocation))
  5014  	}
  5015  
  5016  	// Set expected NextAllocation fields
  5017  	allocs[0].NextAllocation = allocs[1].ID
  5018  	allocs[1].NextAllocation = allocs[2].ID
  5019  
  5020  	sort.Sort(AllocIDSort(allocs))
  5021  	sort.Sort(AllocIDSort(out))
  5022  
  5023  	require.Equal(allocs, out)
  5024  	require.False(watchFired(ws))
  5025  
  5026  	// Insert another alloc, verify index of previous alloc also got updated
  5027  	alloc := mock.Alloc()
  5028  	alloc.PreviousAllocation = allocs[0].ID
  5029  	err = state.UpsertAllocs(1001, []*structs.Allocation{alloc})
  5030  	require.Nil(err)
  5031  	alloc0, err := state.AllocByID(nil, allocs[0].ID)
  5032  	require.Nil(err)
  5033  	require.Equal(alloc0.ModifyIndex, uint64(1001))
  5034  }
  5035  
  5036  func TestStateStore_RestoreAlloc(t *testing.T) {
  5037  	state := testStateStore(t)
  5038  	alloc := mock.Alloc()
  5039  
  5040  	restore, err := state.Restore()
  5041  	if err != nil {
  5042  		t.Fatalf("err: %v", err)
  5043  	}
  5044  
  5045  	err = restore.AllocRestore(alloc)
  5046  	if err != nil {
  5047  		t.Fatalf("err: %v", err)
  5048  	}
  5049  
  5050  	restore.Commit()
  5051  
  5052  	ws := memdb.NewWatchSet()
  5053  	out, err := state.AllocByID(ws, alloc.ID)
  5054  	if err != nil {
  5055  		t.Fatalf("err: %v", err)
  5056  	}
  5057  
  5058  	if !reflect.DeepEqual(out, alloc) {
  5059  		t.Fatalf("Bad: %#v %#v", out, alloc)
  5060  	}
  5061  
  5062  	if watchFired(ws) {
  5063  		t.Fatalf("bad")
  5064  	}
  5065  }
  5066  
  5067  func TestStateStore_SetJobStatus_ForceStatus(t *testing.T) {
  5068  	state := testStateStore(t)
  5069  	txn := state.db.Txn(true)
  5070  
  5071  	// Create and insert a mock job.
  5072  	job := mock.Job()
  5073  	job.Status = ""
  5074  	job.ModifyIndex = 0
  5075  	if err := txn.Insert("jobs", job); err != nil {
  5076  		t.Fatalf("job insert failed: %v", err)
  5077  	}
  5078  
  5079  	exp := "foobar"
  5080  	index := uint64(1000)
  5081  	if err := state.setJobStatus(index, txn, job, false, exp); err != nil {
  5082  		t.Fatalf("setJobStatus() failed: %v", err)
  5083  	}
  5084  
  5085  	i, err := txn.First("jobs", "id", job.Namespace, job.ID)
  5086  	if err != nil {
  5087  		t.Fatalf("job lookup failed: %v", err)
  5088  	}
  5089  	updated := i.(*structs.Job)
  5090  
  5091  	if updated.Status != exp {
  5092  		t.Fatalf("setJobStatus() set %v; expected %v", updated.Status, exp)
  5093  	}
  5094  
  5095  	if updated.ModifyIndex != index {
  5096  		t.Fatalf("setJobStatus() set %d; expected %d", updated.ModifyIndex, index)
  5097  	}
  5098  }
  5099  
  5100  func TestStateStore_SetJobStatus_NoOp(t *testing.T) {
  5101  	state := testStateStore(t)
  5102  	txn := state.db.Txn(true)
  5103  
  5104  	// Create and insert a mock job that should be pending.
  5105  	job := mock.Job()
  5106  	job.Status = structs.JobStatusPending
  5107  	job.ModifyIndex = 10
  5108  	if err := txn.Insert("jobs", job); err != nil {
  5109  		t.Fatalf("job insert failed: %v", err)
  5110  	}
  5111  
  5112  	index := uint64(1000)
  5113  	if err := state.setJobStatus(index, txn, job, false, ""); err != nil {
  5114  		t.Fatalf("setJobStatus() failed: %v", err)
  5115  	}
  5116  
  5117  	i, err := txn.First("jobs", "id", job.Namespace, job.ID)
  5118  	if err != nil {
  5119  		t.Fatalf("job lookup failed: %v", err)
  5120  	}
  5121  	updated := i.(*structs.Job)
  5122  
  5123  	if updated.ModifyIndex == index {
  5124  		t.Fatalf("setJobStatus() should have been a no-op")
  5125  	}
  5126  }
  5127  
  5128  func TestStateStore_SetJobStatus(t *testing.T) {
  5129  	state := testStateStore(t)
  5130  	txn := state.db.Txn(true)
  5131  
  5132  	// Create and insert a mock job that should be pending but has an incorrect
  5133  	// status.
  5134  	job := mock.Job()
  5135  	job.Status = "foobar"
  5136  	job.ModifyIndex = 10
  5137  	if err := txn.Insert("jobs", job); err != nil {
  5138  		t.Fatalf("job insert failed: %v", err)
  5139  	}
  5140  
  5141  	index := uint64(1000)
  5142  	if err := state.setJobStatus(index, txn, job, false, ""); err != nil {
  5143  		t.Fatalf("setJobStatus() failed: %v", err)
  5144  	}
  5145  
  5146  	i, err := txn.First("jobs", "id", job.Namespace, job.ID)
  5147  	if err != nil {
  5148  		t.Fatalf("job lookup failed: %v", err)
  5149  	}
  5150  	updated := i.(*structs.Job)
  5151  
  5152  	if updated.Status != structs.JobStatusPending {
  5153  		t.Fatalf("setJobStatus() set %v; expected %v", updated.Status, structs.JobStatusPending)
  5154  	}
  5155  
  5156  	if updated.ModifyIndex != index {
  5157  		t.Fatalf("setJobStatus() set %d; expected %d", updated.ModifyIndex, index)
  5158  	}
  5159  }
  5160  
  5161  func TestStateStore_GetJobStatus_NoEvalsOrAllocs(t *testing.T) {
  5162  	job := mock.Job()
  5163  	state := testStateStore(t)
  5164  	txn := state.db.Txn(false)
  5165  	status, err := state.getJobStatus(txn, job, false)
  5166  	if err != nil {
  5167  		t.Fatalf("getJobStatus() failed: %v", err)
  5168  	}
  5169  
  5170  	if status != structs.JobStatusPending {
  5171  		t.Fatalf("getJobStatus() returned %v; expected %v", status, structs.JobStatusPending)
  5172  	}
  5173  }
  5174  
  5175  func TestStateStore_GetJobStatus_NoEvalsOrAllocs_Periodic(t *testing.T) {
  5176  	job := mock.PeriodicJob()
  5177  	state := testStateStore(t)
  5178  	txn := state.db.Txn(false)
  5179  	status, err := state.getJobStatus(txn, job, false)
  5180  	if err != nil {
  5181  		t.Fatalf("getJobStatus() failed: %v", err)
  5182  	}
  5183  
  5184  	if status != structs.JobStatusRunning {
  5185  		t.Fatalf("getJobStatus() returned %v; expected %v", status, structs.JobStatusRunning)
  5186  	}
  5187  }
  5188  
  5189  func TestStateStore_GetJobStatus_NoEvalsOrAllocs_EvalDelete(t *testing.T) {
  5190  	job := mock.Job()
  5191  	state := testStateStore(t)
  5192  	txn := state.db.Txn(false)
  5193  	status, err := state.getJobStatus(txn, job, true)
  5194  	if err != nil {
  5195  		t.Fatalf("getJobStatus() failed: %v", err)
  5196  	}
  5197  
  5198  	if status != structs.JobStatusDead {
  5199  		t.Fatalf("getJobStatus() returned %v; expected %v", status, structs.JobStatusDead)
  5200  	}
  5201  }
  5202  
  5203  func TestStateStore_GetJobStatus_DeadEvalsAndAllocs(t *testing.T) {
  5204  	state := testStateStore(t)
  5205  	job := mock.Job()
  5206  
  5207  	// Create a mock alloc that is dead.
  5208  	alloc := mock.Alloc()
  5209  	alloc.JobID = job.ID
  5210  	alloc.DesiredStatus = structs.AllocDesiredStatusStop
  5211  	state.UpsertJobSummary(999, mock.JobSummary(alloc.JobID))
  5212  	if err := state.UpsertAllocs(1000, []*structs.Allocation{alloc}); err != nil {
  5213  		t.Fatalf("err: %v", err)
  5214  	}
  5215  
  5216  	// Create a mock eval that is complete
  5217  	eval := mock.Eval()
  5218  	eval.JobID = job.ID
  5219  	eval.Status = structs.EvalStatusComplete
  5220  	if err := state.UpsertEvals(1001, []*structs.Evaluation{eval}); err != nil {
  5221  		t.Fatalf("err: %v", err)
  5222  	}
  5223  
  5224  	txn := state.db.Txn(false)
  5225  	status, err := state.getJobStatus(txn, job, false)
  5226  	if err != nil {
  5227  		t.Fatalf("getJobStatus() failed: %v", err)
  5228  	}
  5229  
  5230  	if status != structs.JobStatusDead {
  5231  		t.Fatalf("getJobStatus() returned %v; expected %v", status, structs.JobStatusDead)
  5232  	}
  5233  }
  5234  
  5235  func TestStateStore_GetJobStatus_RunningAlloc(t *testing.T) {
  5236  	state := testStateStore(t)
  5237  	job := mock.Job()
  5238  
  5239  	// Create a mock alloc that is running.
  5240  	alloc := mock.Alloc()
  5241  	alloc.JobID = job.ID
  5242  	alloc.DesiredStatus = structs.AllocDesiredStatusRun
  5243  	state.UpsertJobSummary(999, mock.JobSummary(alloc.JobID))
  5244  	if err := state.UpsertAllocs(1000, []*structs.Allocation{alloc}); err != nil {
  5245  		t.Fatalf("err: %v", err)
  5246  	}
  5247  
  5248  	txn := state.db.Txn(false)
  5249  	status, err := state.getJobStatus(txn, job, true)
  5250  	if err != nil {
  5251  		t.Fatalf("getJobStatus() failed: %v", err)
  5252  	}
  5253  
  5254  	if status != structs.JobStatusRunning {
  5255  		t.Fatalf("getJobStatus() returned %v; expected %v", status, structs.JobStatusRunning)
  5256  	}
  5257  }
  5258  
  5259  func TestStateStore_GetJobStatus_PeriodicJob(t *testing.T) {
  5260  	state := testStateStore(t)
  5261  	job := mock.PeriodicJob()
  5262  
  5263  	txn := state.db.Txn(false)
  5264  	status, err := state.getJobStatus(txn, job, false)
  5265  	if err != nil {
  5266  		t.Fatalf("getJobStatus() failed: %v", err)
  5267  	}
  5268  
  5269  	if status != structs.JobStatusRunning {
  5270  		t.Fatalf("getJobStatus() returned %v; expected %v", status, structs.JobStatusRunning)
  5271  	}
  5272  
  5273  	// Mark it as stopped
  5274  	job.Stop = true
  5275  	status, err = state.getJobStatus(txn, job, false)
  5276  	if err != nil {
  5277  		t.Fatalf("getJobStatus() failed: %v", err)
  5278  	}
  5279  
  5280  	if status != structs.JobStatusDead {
  5281  		t.Fatalf("getJobStatus() returned %v; expected %v", status, structs.JobStatusDead)
  5282  	}
  5283  }
  5284  
  5285  func TestStateStore_GetJobStatus_ParameterizedJob(t *testing.T) {
  5286  	state := testStateStore(t)
  5287  	job := mock.Job()
  5288  	job.ParameterizedJob = &structs.ParameterizedJobConfig{}
  5289  
  5290  	txn := state.db.Txn(false)
  5291  	status, err := state.getJobStatus(txn, job, false)
  5292  	if err != nil {
  5293  		t.Fatalf("getJobStatus() failed: %v", err)
  5294  	}
  5295  
  5296  	if status != structs.JobStatusRunning {
  5297  		t.Fatalf("getJobStatus() returned %v; expected %v", status, structs.JobStatusRunning)
  5298  	}
  5299  
  5300  	// Mark it as stopped
  5301  	job.Stop = true
  5302  	status, err = state.getJobStatus(txn, job, false)
  5303  	if err != nil {
  5304  		t.Fatalf("getJobStatus() failed: %v", err)
  5305  	}
  5306  
  5307  	if status != structs.JobStatusDead {
  5308  		t.Fatalf("getJobStatus() returned %v; expected %v", status, structs.JobStatusDead)
  5309  	}
  5310  }
  5311  
  5312  func TestStateStore_SetJobStatus_PendingEval(t *testing.T) {
  5313  	state := testStateStore(t)
  5314  	job := mock.Job()
  5315  
  5316  	// Create a mock eval that is pending.
  5317  	eval := mock.Eval()
  5318  	eval.JobID = job.ID
  5319  	eval.Status = structs.EvalStatusPending
  5320  	if err := state.UpsertEvals(1000, []*structs.Evaluation{eval}); err != nil {
  5321  		t.Fatalf("err: %v", err)
  5322  	}
  5323  
  5324  	txn := state.db.Txn(false)
  5325  	status, err := state.getJobStatus(txn, job, true)
  5326  	if err != nil {
  5327  		t.Fatalf("getJobStatus() failed: %v", err)
  5328  	}
  5329  
  5330  	if status != structs.JobStatusPending {
  5331  		t.Fatalf("getJobStatus() returned %v; expected %v", status, structs.JobStatusPending)
  5332  	}
  5333  }
  5334  
  5335  // TestStateStore_SetJobStatus_SystemJob asserts that system jobs are still
  5336  // considered running until explicitly stopped.
  5337  func TestStateStore_SetJobStatus_SystemJob(t *testing.T) {
  5338  	state := testStateStore(t)
  5339  	job := mock.SystemJob()
  5340  
  5341  	// Create a mock eval that is pending.
  5342  	eval := mock.Eval()
  5343  	eval.JobID = job.ID
  5344  	eval.Type = job.Type
  5345  	eval.Status = structs.EvalStatusComplete
  5346  	if err := state.UpsertEvals(1000, []*structs.Evaluation{eval}); err != nil {
  5347  		t.Fatalf("err: %v", err)
  5348  	}
  5349  
  5350  	txn := state.db.Txn(false)
  5351  	status, err := state.getJobStatus(txn, job, true)
  5352  	if err != nil {
  5353  		t.Fatalf("getJobStatus() failed: %v", err)
  5354  	}
  5355  
  5356  	if expected := structs.JobStatusRunning; status != expected {
  5357  		t.Fatalf("getJobStatus() returned %v; expected %v", status, expected)
  5358  	}
  5359  
  5360  	// Stop the job
  5361  	job.Stop = true
  5362  	status, err = state.getJobStatus(txn, job, true)
  5363  	if err != nil {
  5364  		t.Fatalf("getJobStatus() failed: %v", err)
  5365  	}
  5366  
  5367  	if expected := structs.JobStatusDead; status != expected {
  5368  		t.Fatalf("getJobStatus() returned %v; expected %v", status, expected)
  5369  	}
  5370  }
  5371  
  5372  func TestStateJobSummary_UpdateJobCount(t *testing.T) {
  5373  	state := testStateStore(t)
  5374  	alloc := mock.Alloc()
  5375  	job := alloc.Job
  5376  	job.TaskGroups[0].Count = 3
  5377  
  5378  	// Create watchsets so we can test that upsert fires the watch
  5379  	ws := memdb.NewWatchSet()
  5380  	if _, err := state.JobSummaryByID(ws, job.Namespace, job.ID); err != nil {
  5381  		t.Fatalf("bad: %v", err)
  5382  	}
  5383  
  5384  	if err := state.UpsertJob(1000, job); err != nil {
  5385  		t.Fatalf("err: %v", err)
  5386  	}
  5387  
  5388  	if err := state.UpsertAllocs(1001, []*structs.Allocation{alloc}); err != nil {
  5389  		t.Fatalf("err: %v", err)
  5390  	}
  5391  
  5392  	if !watchFired(ws) {
  5393  		t.Fatalf("bad")
  5394  	}
  5395  
  5396  	ws = memdb.NewWatchSet()
  5397  	summary, _ := state.JobSummaryByID(ws, job.Namespace, job.ID)
  5398  	expectedSummary := structs.JobSummary{
  5399  		JobID:     job.ID,
  5400  		Namespace: job.Namespace,
  5401  		Summary: map[string]structs.TaskGroupSummary{
  5402  			"web": {
  5403  				Starting: 1,
  5404  			},
  5405  		},
  5406  		Children:    new(structs.JobChildrenSummary),
  5407  		CreateIndex: 1000,
  5408  		ModifyIndex: 1001,
  5409  	}
  5410  	if !reflect.DeepEqual(summary, &expectedSummary) {
  5411  		t.Fatalf("expected: %v, actual: %v", expectedSummary, summary)
  5412  	}
  5413  
  5414  	// Create watchsets so we can test that upsert fires the watch
  5415  	ws2 := memdb.NewWatchSet()
  5416  	if _, err := state.JobSummaryByID(ws2, job.Namespace, job.ID); err != nil {
  5417  		t.Fatalf("bad: %v", err)
  5418  	}
  5419  
  5420  	alloc2 := mock.Alloc()
  5421  	alloc2.Job = job
  5422  	alloc2.JobID = job.ID
  5423  
  5424  	alloc3 := mock.Alloc()
  5425  	alloc3.Job = job
  5426  	alloc3.JobID = job.ID
  5427  
  5428  	if err := state.UpsertAllocs(1002, []*structs.Allocation{alloc2, alloc3}); err != nil {
  5429  		t.Fatalf("err: %v", err)
  5430  	}
  5431  
  5432  	if !watchFired(ws2) {
  5433  		t.Fatalf("bad")
  5434  	}
  5435  
  5436  	outA, _ := state.AllocByID(ws, alloc3.ID)
  5437  
  5438  	summary, _ = state.JobSummaryByID(ws, job.Namespace, job.ID)
  5439  	expectedSummary = structs.JobSummary{
  5440  		JobID:     job.ID,
  5441  		Namespace: job.Namespace,
  5442  		Summary: map[string]structs.TaskGroupSummary{
  5443  			"web": {
  5444  				Starting: 3,
  5445  			},
  5446  		},
  5447  		Children:    new(structs.JobChildrenSummary),
  5448  		CreateIndex: job.CreateIndex,
  5449  		ModifyIndex: outA.ModifyIndex,
  5450  	}
  5451  	if !reflect.DeepEqual(summary, &expectedSummary) {
  5452  		t.Fatalf("expected summary: %v, actual: %v", expectedSummary, summary)
  5453  	}
  5454  
  5455  	// Create watchsets so we can test that upsert fires the watch
  5456  	ws3 := memdb.NewWatchSet()
  5457  	if _, err := state.JobSummaryByID(ws3, job.Namespace, job.ID); err != nil {
  5458  		t.Fatalf("bad: %v", err)
  5459  	}
  5460  
  5461  	alloc4 := mock.Alloc()
  5462  	alloc4.ID = alloc2.ID
  5463  	alloc4.Job = alloc2.Job
  5464  	alloc4.JobID = alloc2.JobID
  5465  	alloc4.ClientStatus = structs.AllocClientStatusComplete
  5466  
  5467  	alloc5 := mock.Alloc()
  5468  	alloc5.ID = alloc3.ID
  5469  	alloc5.Job = alloc3.Job
  5470  	alloc5.JobID = alloc3.JobID
  5471  	alloc5.ClientStatus = structs.AllocClientStatusComplete
  5472  
  5473  	if err := state.UpdateAllocsFromClient(1004, []*structs.Allocation{alloc4, alloc5}); err != nil {
  5474  		t.Fatalf("err: %v", err)
  5475  	}
  5476  
  5477  	if !watchFired(ws2) {
  5478  		t.Fatalf("bad")
  5479  	}
  5480  
  5481  	outA, _ = state.AllocByID(ws, alloc5.ID)
  5482  	summary, _ = state.JobSummaryByID(ws, job.Namespace, job.ID)
  5483  	expectedSummary = structs.JobSummary{
  5484  		JobID:     job.ID,
  5485  		Namespace: job.Namespace,
  5486  		Summary: map[string]structs.TaskGroupSummary{
  5487  			"web": {
  5488  				Complete: 2,
  5489  				Starting: 1,
  5490  			},
  5491  		},
  5492  		Children:    new(structs.JobChildrenSummary),
  5493  		CreateIndex: job.CreateIndex,
  5494  		ModifyIndex: outA.ModifyIndex,
  5495  	}
  5496  	if !reflect.DeepEqual(summary, &expectedSummary) {
  5497  		t.Fatalf("expected: %v, actual: %v", expectedSummary, summary)
  5498  	}
  5499  }
  5500  
  5501  func TestJobSummary_UpdateClientStatus(t *testing.T) {
  5502  	state := testStateStore(t)
  5503  	alloc := mock.Alloc()
  5504  	job := alloc.Job
  5505  	job.TaskGroups[0].Count = 3
  5506  
  5507  	alloc2 := mock.Alloc()
  5508  	alloc2.Job = job
  5509  	alloc2.JobID = job.ID
  5510  
  5511  	alloc3 := mock.Alloc()
  5512  	alloc3.Job = job
  5513  	alloc3.JobID = job.ID
  5514  
  5515  	err := state.UpsertJob(1000, job)
  5516  	if err != nil {
  5517  		t.Fatalf("err: %v", err)
  5518  	}
  5519  
  5520  	if err := state.UpsertAllocs(1001, []*structs.Allocation{alloc, alloc2, alloc3}); err != nil {
  5521  		t.Fatalf("err: %v", err)
  5522  	}
  5523  
  5524  	ws := memdb.NewWatchSet()
  5525  	summary, _ := state.JobSummaryByID(ws, job.Namespace, job.ID)
  5526  	if summary.Summary["web"].Starting != 3 {
  5527  		t.Fatalf("bad job summary: %v", summary)
  5528  	}
  5529  
  5530  	alloc4 := mock.Alloc()
  5531  	alloc4.ID = alloc2.ID
  5532  	alloc4.Job = alloc2.Job
  5533  	alloc4.JobID = alloc2.JobID
  5534  	alloc4.ClientStatus = structs.AllocClientStatusComplete
  5535  
  5536  	alloc5 := mock.Alloc()
  5537  	alloc5.ID = alloc3.ID
  5538  	alloc5.Job = alloc3.Job
  5539  	alloc5.JobID = alloc3.JobID
  5540  	alloc5.ClientStatus = structs.AllocClientStatusFailed
  5541  
  5542  	alloc6 := mock.Alloc()
  5543  	alloc6.ID = alloc.ID
  5544  	alloc6.Job = alloc.Job
  5545  	alloc6.JobID = alloc.JobID
  5546  	alloc6.ClientStatus = structs.AllocClientStatusRunning
  5547  
  5548  	if err := state.UpdateAllocsFromClient(1002, []*structs.Allocation{alloc4, alloc5, alloc6}); err != nil {
  5549  		t.Fatalf("err: %v", err)
  5550  	}
  5551  
  5552  	if !watchFired(ws) {
  5553  		t.Fatalf("bad")
  5554  	}
  5555  
  5556  	summary, _ = state.JobSummaryByID(ws, job.Namespace, job.ID)
  5557  	if summary.Summary["web"].Running != 1 || summary.Summary["web"].Failed != 1 || summary.Summary["web"].Complete != 1 {
  5558  		t.Fatalf("bad job summary: %v", summary)
  5559  	}
  5560  
  5561  	alloc7 := mock.Alloc()
  5562  	alloc7.Job = alloc.Job
  5563  	alloc7.JobID = alloc.JobID
  5564  
  5565  	if err := state.UpsertAllocs(1003, []*structs.Allocation{alloc7}); err != nil {
  5566  		t.Fatalf("err: %v", err)
  5567  	}
  5568  	summary, _ = state.JobSummaryByID(ws, job.Namespace, job.ID)
  5569  	if summary.Summary["web"].Starting != 1 || summary.Summary["web"].Running != 1 || summary.Summary["web"].Failed != 1 || summary.Summary["web"].Complete != 1 {
  5570  		t.Fatalf("bad job summary: %v", summary)
  5571  	}
  5572  }
  5573  
  5574  // Test that nonexistent deployment can't be updated
  5575  func TestStateStore_UpsertDeploymentStatusUpdate_Nonexistent(t *testing.T) {
  5576  	state := testStateStore(t)
  5577  
  5578  	// Update the nonexistent deployment
  5579  	req := &structs.DeploymentStatusUpdateRequest{
  5580  		DeploymentUpdate: &structs.DeploymentStatusUpdate{
  5581  			DeploymentID: uuid.Generate(),
  5582  			Status:       structs.DeploymentStatusRunning,
  5583  		},
  5584  	}
  5585  	err := state.UpdateDeploymentStatus(2, req)
  5586  	if err == nil || !strings.Contains(err.Error(), "does not exist") {
  5587  		t.Fatalf("expected error updating the status because the deployment doesn't exist")
  5588  	}
  5589  }
  5590  
  5591  // Test that terminal deployment can't be updated
  5592  func TestStateStore_UpsertDeploymentStatusUpdate_Terminal(t *testing.T) {
  5593  	state := testStateStore(t)
  5594  
  5595  	// Insert a terminal deployment
  5596  	d := mock.Deployment()
  5597  	d.Status = structs.DeploymentStatusFailed
  5598  
  5599  	if err := state.UpsertDeployment(1, d); err != nil {
  5600  		t.Fatalf("bad: %v", err)
  5601  	}
  5602  
  5603  	// Update the deployment
  5604  	req := &structs.DeploymentStatusUpdateRequest{
  5605  		DeploymentUpdate: &structs.DeploymentStatusUpdate{
  5606  			DeploymentID: d.ID,
  5607  			Status:       structs.DeploymentStatusRunning,
  5608  		},
  5609  	}
  5610  	err := state.UpdateDeploymentStatus(2, req)
  5611  	if err == nil || !strings.Contains(err.Error(), "has terminal status") {
  5612  		t.Fatalf("expected error updating the status because the deployment is terminal")
  5613  	}
  5614  }
  5615  
  5616  // Test that a non terminal deployment is updated and that a job and eval are
  5617  // created.
  5618  func TestStateStore_UpsertDeploymentStatusUpdate_NonTerminal(t *testing.T) {
  5619  	state := testStateStore(t)
  5620  
  5621  	// Insert a deployment
  5622  	d := mock.Deployment()
  5623  	if err := state.UpsertDeployment(1, d); err != nil {
  5624  		t.Fatalf("bad: %v", err)
  5625  	}
  5626  
  5627  	// Create an eval and a job
  5628  	e := mock.Eval()
  5629  	j := mock.Job()
  5630  
  5631  	// Update the deployment
  5632  	status, desc := structs.DeploymentStatusFailed, "foo"
  5633  	req := &structs.DeploymentStatusUpdateRequest{
  5634  		DeploymentUpdate: &structs.DeploymentStatusUpdate{
  5635  			DeploymentID:      d.ID,
  5636  			Status:            status,
  5637  			StatusDescription: desc,
  5638  		},
  5639  		Job:  j,
  5640  		Eval: e,
  5641  	}
  5642  	err := state.UpdateDeploymentStatus(2, req)
  5643  	if err != nil {
  5644  		t.Fatalf("bad: %v", err)
  5645  	}
  5646  
  5647  	// Check that the status was updated properly
  5648  	ws := memdb.NewWatchSet()
  5649  	dout, err := state.DeploymentByID(ws, d.ID)
  5650  	if err != nil {
  5651  		t.Fatalf("bad: %v", err)
  5652  	}
  5653  	if dout.Status != status || dout.StatusDescription != desc {
  5654  		t.Fatalf("bad: %#v", dout)
  5655  	}
  5656  
  5657  	// Check that the evaluation was created
  5658  	eout, _ := state.EvalByID(ws, e.ID)
  5659  	if err != nil {
  5660  		t.Fatalf("bad: %v", err)
  5661  	}
  5662  	if eout == nil {
  5663  		t.Fatalf("bad: %#v", eout)
  5664  	}
  5665  
  5666  	// Check that the job was created
  5667  	jout, _ := state.JobByID(ws, j.Namespace, j.ID)
  5668  	if err != nil {
  5669  		t.Fatalf("bad: %v", err)
  5670  	}
  5671  	if jout == nil {
  5672  		t.Fatalf("bad: %#v", jout)
  5673  	}
  5674  }
  5675  
  5676  // Test that when a deployment is updated to successful the job is updated to
  5677  // stable
  5678  func TestStateStore_UpsertDeploymentStatusUpdate_Successful(t *testing.T) {
  5679  	state := testStateStore(t)
  5680  
  5681  	// Insert a job
  5682  	job := mock.Job()
  5683  	if err := state.UpsertJob(1, job); err != nil {
  5684  		t.Fatalf("bad: %v", err)
  5685  	}
  5686  
  5687  	// Insert a deployment
  5688  	d := structs.NewDeployment(job)
  5689  	if err := state.UpsertDeployment(2, d); err != nil {
  5690  		t.Fatalf("bad: %v", err)
  5691  	}
  5692  
  5693  	// Update the deployment
  5694  	req := &structs.DeploymentStatusUpdateRequest{
  5695  		DeploymentUpdate: &structs.DeploymentStatusUpdate{
  5696  			DeploymentID:      d.ID,
  5697  			Status:            structs.DeploymentStatusSuccessful,
  5698  			StatusDescription: structs.DeploymentStatusDescriptionSuccessful,
  5699  		},
  5700  	}
  5701  	err := state.UpdateDeploymentStatus(3, req)
  5702  	if err != nil {
  5703  		t.Fatalf("bad: %v", err)
  5704  	}
  5705  
  5706  	// Check that the status was updated properly
  5707  	ws := memdb.NewWatchSet()
  5708  	dout, err := state.DeploymentByID(ws, d.ID)
  5709  	if err != nil {
  5710  		t.Fatalf("bad: %v", err)
  5711  	}
  5712  	if dout.Status != structs.DeploymentStatusSuccessful ||
  5713  		dout.StatusDescription != structs.DeploymentStatusDescriptionSuccessful {
  5714  		t.Fatalf("bad: %#v", dout)
  5715  	}
  5716  
  5717  	// Check that the job was created
  5718  	jout, _ := state.JobByID(ws, job.Namespace, job.ID)
  5719  	if err != nil {
  5720  		t.Fatalf("bad: %v", err)
  5721  	}
  5722  	if jout == nil {
  5723  		t.Fatalf("bad: %#v", jout)
  5724  	}
  5725  	if !jout.Stable {
  5726  		t.Fatalf("job not marked stable %#v", jout)
  5727  	}
  5728  	if jout.Version != d.JobVersion {
  5729  		t.Fatalf("job version changed; got %d; want %d", jout.Version, d.JobVersion)
  5730  	}
  5731  }
  5732  
  5733  func TestStateStore_UpdateJobStability(t *testing.T) {
  5734  	state := testStateStore(t)
  5735  
  5736  	// Insert a job twice to get two versions
  5737  	job := mock.Job()
  5738  	if err := state.UpsertJob(1, job); err != nil {
  5739  		t.Fatalf("bad: %v", err)
  5740  	}
  5741  
  5742  	if err := state.UpsertJob(2, job); err != nil {
  5743  		t.Fatalf("bad: %v", err)
  5744  	}
  5745  
  5746  	// Update the stability to true
  5747  	err := state.UpdateJobStability(3, job.Namespace, job.ID, 0, true)
  5748  	if err != nil {
  5749  		t.Fatalf("bad: %v", err)
  5750  	}
  5751  
  5752  	// Check that the job was updated properly
  5753  	ws := memdb.NewWatchSet()
  5754  	jout, _ := state.JobByIDAndVersion(ws, job.Namespace, job.ID, 0)
  5755  	if err != nil {
  5756  		t.Fatalf("bad: %v", err)
  5757  	}
  5758  	if jout == nil {
  5759  		t.Fatalf("bad: %#v", jout)
  5760  	}
  5761  	if !jout.Stable {
  5762  		t.Fatalf("job not marked stable %#v", jout)
  5763  	}
  5764  
  5765  	// Update the stability to false
  5766  	err = state.UpdateJobStability(3, job.Namespace, job.ID, 0, false)
  5767  	if err != nil {
  5768  		t.Fatalf("bad: %v", err)
  5769  	}
  5770  
  5771  	// Check that the job was updated properly
  5772  	jout, _ = state.JobByIDAndVersion(ws, job.Namespace, job.ID, 0)
  5773  	if err != nil {
  5774  		t.Fatalf("bad: %v", err)
  5775  	}
  5776  	if jout == nil {
  5777  		t.Fatalf("bad: %#v", jout)
  5778  	}
  5779  	if jout.Stable {
  5780  		t.Fatalf("job marked stable %#v", jout)
  5781  	}
  5782  }
  5783  
  5784  // Test that nonexistent deployment can't be promoted
  5785  func TestStateStore_UpsertDeploymentPromotion_Nonexistent(t *testing.T) {
  5786  	state := testStateStore(t)
  5787  
  5788  	// Promote the nonexistent deployment
  5789  	req := &structs.ApplyDeploymentPromoteRequest{
  5790  		DeploymentPromoteRequest: structs.DeploymentPromoteRequest{
  5791  			DeploymentID: uuid.Generate(),
  5792  			All:          true,
  5793  		},
  5794  	}
  5795  	err := state.UpdateDeploymentPromotion(2, req)
  5796  	if err == nil || !strings.Contains(err.Error(), "does not exist") {
  5797  		t.Fatalf("expected error promoting because the deployment doesn't exist")
  5798  	}
  5799  }
  5800  
  5801  // Test that terminal deployment can't be updated
  5802  func TestStateStore_UpsertDeploymentPromotion_Terminal(t *testing.T) {
  5803  	state := testStateStore(t)
  5804  
  5805  	// Insert a terminal deployment
  5806  	d := mock.Deployment()
  5807  	d.Status = structs.DeploymentStatusFailed
  5808  
  5809  	if err := state.UpsertDeployment(1, d); err != nil {
  5810  		t.Fatalf("bad: %v", err)
  5811  	}
  5812  
  5813  	// Promote the deployment
  5814  	req := &structs.ApplyDeploymentPromoteRequest{
  5815  		DeploymentPromoteRequest: structs.DeploymentPromoteRequest{
  5816  			DeploymentID: d.ID,
  5817  			All:          true,
  5818  		},
  5819  	}
  5820  	err := state.UpdateDeploymentPromotion(2, req)
  5821  	if err == nil || !strings.Contains(err.Error(), "has terminal status") {
  5822  		t.Fatalf("expected error updating the status because the deployment is terminal: %v", err)
  5823  	}
  5824  }
  5825  
  5826  // Test promoting unhealthy canaries in a deployment.
  5827  func TestStateStore_UpsertDeploymentPromotion_Unhealthy(t *testing.T) {
  5828  	state := testStateStore(t)
  5829  	require := require.New(t)
  5830  
  5831  	// Create a job
  5832  	j := mock.Job()
  5833  	require.Nil(state.UpsertJob(1, j))
  5834  
  5835  	// Create a deployment
  5836  	d := mock.Deployment()
  5837  	d.JobID = j.ID
  5838  	d.TaskGroups["web"].DesiredCanaries = 2
  5839  	require.Nil(state.UpsertDeployment(2, d))
  5840  
  5841  	// Create a set of allocations
  5842  	c1 := mock.Alloc()
  5843  	c1.JobID = j.ID
  5844  	c1.DeploymentID = d.ID
  5845  	d.TaskGroups[c1.TaskGroup].PlacedCanaries = append(d.TaskGroups[c1.TaskGroup].PlacedCanaries, c1.ID)
  5846  	c2 := mock.Alloc()
  5847  	c2.JobID = j.ID
  5848  	c2.DeploymentID = d.ID
  5849  	d.TaskGroups[c2.TaskGroup].PlacedCanaries = append(d.TaskGroups[c2.TaskGroup].PlacedCanaries, c2.ID)
  5850  
  5851  	// Create a healthy but terminal alloc
  5852  	c3 := mock.Alloc()
  5853  	c3.JobID = j.ID
  5854  	c3.DeploymentID = d.ID
  5855  	c3.DesiredStatus = structs.AllocDesiredStatusStop
  5856  	c3.DeploymentStatus = &structs.AllocDeploymentStatus{Healthy: helper.BoolToPtr(true)}
  5857  	d.TaskGroups[c3.TaskGroup].PlacedCanaries = append(d.TaskGroups[c3.TaskGroup].PlacedCanaries, c3.ID)
  5858  
  5859  	require.Nil(state.UpsertAllocs(3, []*structs.Allocation{c1, c2, c3}))
  5860  
  5861  	// Promote the canaries
  5862  	req := &structs.ApplyDeploymentPromoteRequest{
  5863  		DeploymentPromoteRequest: structs.DeploymentPromoteRequest{
  5864  			DeploymentID: d.ID,
  5865  			All:          true,
  5866  		},
  5867  	}
  5868  	err := state.UpdateDeploymentPromotion(4, req)
  5869  	require.NotNil(err)
  5870  	require.Contains(err.Error(), `Task group "web" has 0/2 healthy allocations`)
  5871  }
  5872  
  5873  // Test promoting a deployment with no canaries
  5874  func TestStateStore_UpsertDeploymentPromotion_NoCanaries(t *testing.T) {
  5875  	state := testStateStore(t)
  5876  	require := require.New(t)
  5877  
  5878  	// Create a job
  5879  	j := mock.Job()
  5880  	require.Nil(state.UpsertJob(1, j))
  5881  
  5882  	// Create a deployment
  5883  	d := mock.Deployment()
  5884  	d.TaskGroups["web"].DesiredCanaries = 2
  5885  	d.JobID = j.ID
  5886  	require.Nil(state.UpsertDeployment(2, d))
  5887  
  5888  	// Promote the canaries
  5889  	req := &structs.ApplyDeploymentPromoteRequest{
  5890  		DeploymentPromoteRequest: structs.DeploymentPromoteRequest{
  5891  			DeploymentID: d.ID,
  5892  			All:          true,
  5893  		},
  5894  	}
  5895  	err := state.UpdateDeploymentPromotion(4, req)
  5896  	require.NotNil(err)
  5897  	require.Contains(err.Error(), `Task group "web" has 0/2 healthy allocations`)
  5898  }
  5899  
  5900  // Test promoting all canaries in a deployment.
  5901  func TestStateStore_UpsertDeploymentPromotion_All(t *testing.T) {
  5902  	state := testStateStore(t)
  5903  
  5904  	// Create a job with two task groups
  5905  	j := mock.Job()
  5906  	tg1 := j.TaskGroups[0]
  5907  	tg2 := tg1.Copy()
  5908  	tg2.Name = "foo"
  5909  	j.TaskGroups = append(j.TaskGroups, tg2)
  5910  	if err := state.UpsertJob(1, j); err != nil {
  5911  		t.Fatalf("bad: %v", err)
  5912  	}
  5913  
  5914  	// Create a deployment
  5915  	d := mock.Deployment()
  5916  	d.StatusDescription = structs.DeploymentStatusDescriptionRunningNeedsPromotion
  5917  	d.JobID = j.ID
  5918  	d.TaskGroups = map[string]*structs.DeploymentState{
  5919  		"web": {
  5920  			DesiredTotal:    10,
  5921  			DesiredCanaries: 1,
  5922  		},
  5923  		"foo": {
  5924  			DesiredTotal:    10,
  5925  			DesiredCanaries: 1,
  5926  		},
  5927  	}
  5928  	if err := state.UpsertDeployment(2, d); err != nil {
  5929  		t.Fatalf("bad: %v", err)
  5930  	}
  5931  
  5932  	// Create a set of allocations
  5933  	c1 := mock.Alloc()
  5934  	c1.JobID = j.ID
  5935  	c1.DeploymentID = d.ID
  5936  	d.TaskGroups[c1.TaskGroup].PlacedCanaries = append(d.TaskGroups[c1.TaskGroup].PlacedCanaries, c1.ID)
  5937  	c1.DeploymentStatus = &structs.AllocDeploymentStatus{
  5938  		Healthy: helper.BoolToPtr(true),
  5939  	}
  5940  	c2 := mock.Alloc()
  5941  	c2.JobID = j.ID
  5942  	c2.DeploymentID = d.ID
  5943  	d.TaskGroups[c2.TaskGroup].PlacedCanaries = append(d.TaskGroups[c2.TaskGroup].PlacedCanaries, c2.ID)
  5944  	c2.TaskGroup = tg2.Name
  5945  	c2.DeploymentStatus = &structs.AllocDeploymentStatus{
  5946  		Healthy: helper.BoolToPtr(true),
  5947  	}
  5948  
  5949  	if err := state.UpsertAllocs(3, []*structs.Allocation{c1, c2}); err != nil {
  5950  		t.Fatalf("err: %v", err)
  5951  	}
  5952  
  5953  	// Create an eval
  5954  	e := mock.Eval()
  5955  
  5956  	// Promote the canaries
  5957  	req := &structs.ApplyDeploymentPromoteRequest{
  5958  		DeploymentPromoteRequest: structs.DeploymentPromoteRequest{
  5959  			DeploymentID: d.ID,
  5960  			All:          true,
  5961  		},
  5962  		Eval: e,
  5963  	}
  5964  	err := state.UpdateDeploymentPromotion(4, req)
  5965  	if err != nil {
  5966  		t.Fatalf("bad: %v", err)
  5967  	}
  5968  
  5969  	// Check that the status per task group was updated properly
  5970  	ws := memdb.NewWatchSet()
  5971  	dout, err := state.DeploymentByID(ws, d.ID)
  5972  	if err != nil {
  5973  		t.Fatalf("bad: %v", err)
  5974  	}
  5975  	if dout.StatusDescription != structs.DeploymentStatusDescriptionRunning {
  5976  		t.Fatalf("status description not updated: got %v; want %v", dout.StatusDescription, structs.DeploymentStatusDescriptionRunning)
  5977  	}
  5978  	if len(dout.TaskGroups) != 2 {
  5979  		t.Fatalf("bad: %#v", dout.TaskGroups)
  5980  	}
  5981  	for tg, state := range dout.TaskGroups {
  5982  		if !state.Promoted {
  5983  			t.Fatalf("bad: group %q not promoted %#v", tg, state)
  5984  		}
  5985  	}
  5986  
  5987  	// Check that the evaluation was created
  5988  	eout, _ := state.EvalByID(ws, e.ID)
  5989  	if err != nil {
  5990  		t.Fatalf("bad: %v", err)
  5991  	}
  5992  	if eout == nil {
  5993  		t.Fatalf("bad: %#v", eout)
  5994  	}
  5995  }
  5996  
  5997  // Test promoting a subset of canaries in a deployment.
  5998  func TestStateStore_UpsertDeploymentPromotion_Subset(t *testing.T) {
  5999  	state := testStateStore(t)
  6000  	require := require.New(t)
  6001  
  6002  	// Create a job with two task groups
  6003  	j := mock.Job()
  6004  	tg1 := j.TaskGroups[0]
  6005  	tg2 := tg1.Copy()
  6006  	tg2.Name = "foo"
  6007  	j.TaskGroups = append(j.TaskGroups, tg2)
  6008  	require.Nil(state.UpsertJob(1, j))
  6009  
  6010  	// Create a deployment
  6011  	d := mock.Deployment()
  6012  	d.JobID = j.ID
  6013  	d.TaskGroups = map[string]*structs.DeploymentState{
  6014  		"web": {
  6015  			DesiredTotal:    10,
  6016  			DesiredCanaries: 1,
  6017  		},
  6018  		"foo": {
  6019  			DesiredTotal:    10,
  6020  			DesiredCanaries: 1,
  6021  		},
  6022  	}
  6023  	require.Nil(state.UpsertDeployment(2, d))
  6024  
  6025  	// Create a set of allocations for both groups, including an unhealthy one
  6026  	c1 := mock.Alloc()
  6027  	c1.JobID = j.ID
  6028  	c1.DeploymentID = d.ID
  6029  	d.TaskGroups[c1.TaskGroup].PlacedCanaries = append(d.TaskGroups[c1.TaskGroup].PlacedCanaries, c1.ID)
  6030  	c1.DeploymentStatus = &structs.AllocDeploymentStatus{
  6031  		Healthy: helper.BoolToPtr(true),
  6032  		Canary:  true,
  6033  	}
  6034  
  6035  	// Should still be a canary
  6036  	c2 := mock.Alloc()
  6037  	c2.JobID = j.ID
  6038  	c2.DeploymentID = d.ID
  6039  	d.TaskGroups[c2.TaskGroup].PlacedCanaries = append(d.TaskGroups[c2.TaskGroup].PlacedCanaries, c2.ID)
  6040  	c2.TaskGroup = tg2.Name
  6041  	c2.DeploymentStatus = &structs.AllocDeploymentStatus{
  6042  		Healthy: helper.BoolToPtr(true),
  6043  		Canary:  true,
  6044  	}
  6045  
  6046  	c3 := mock.Alloc()
  6047  	c3.JobID = j.ID
  6048  	c3.DeploymentID = d.ID
  6049  	d.TaskGroups[c3.TaskGroup].PlacedCanaries = append(d.TaskGroups[c3.TaskGroup].PlacedCanaries, c3.ID)
  6050  	c3.DeploymentStatus = &structs.AllocDeploymentStatus{
  6051  		Healthy: helper.BoolToPtr(false),
  6052  		Canary:  true,
  6053  	}
  6054  
  6055  	require.Nil(state.UpsertAllocs(3, []*structs.Allocation{c1, c2, c3}))
  6056  
  6057  	// Create an eval
  6058  	e := mock.Eval()
  6059  
  6060  	// Promote the canaries
  6061  	req := &structs.ApplyDeploymentPromoteRequest{
  6062  		DeploymentPromoteRequest: structs.DeploymentPromoteRequest{
  6063  			DeploymentID: d.ID,
  6064  			Groups:       []string{"web"},
  6065  		},
  6066  		Eval: e,
  6067  	}
  6068  	require.Nil(state.UpdateDeploymentPromotion(4, req))
  6069  
  6070  	// Check that the status per task group was updated properly
  6071  	ws := memdb.NewWatchSet()
  6072  	dout, err := state.DeploymentByID(ws, d.ID)
  6073  	require.Nil(err)
  6074  	require.Len(dout.TaskGroups, 2)
  6075  	require.Contains(dout.TaskGroups, "web")
  6076  	require.True(dout.TaskGroups["web"].Promoted)
  6077  
  6078  	// Check that the evaluation was created
  6079  	eout, err := state.EvalByID(ws, e.ID)
  6080  	require.Nil(err)
  6081  	require.NotNil(eout)
  6082  
  6083  	// Check the canary field was set properly
  6084  	aout1, err1 := state.AllocByID(ws, c1.ID)
  6085  	aout2, err2 := state.AllocByID(ws, c2.ID)
  6086  	aout3, err3 := state.AllocByID(ws, c3.ID)
  6087  	require.Nil(err1)
  6088  	require.Nil(err2)
  6089  	require.Nil(err3)
  6090  	require.NotNil(aout1)
  6091  	require.NotNil(aout2)
  6092  	require.NotNil(aout3)
  6093  	require.False(aout1.DeploymentStatus.Canary)
  6094  	require.True(aout2.DeploymentStatus.Canary)
  6095  	require.True(aout3.DeploymentStatus.Canary)
  6096  }
  6097  
  6098  // Test that allocation health can't be set against a nonexistent deployment
  6099  func TestStateStore_UpsertDeploymentAllocHealth_Nonexistent(t *testing.T) {
  6100  	state := testStateStore(t)
  6101  
  6102  	// Set health against the nonexistent deployment
  6103  	req := &structs.ApplyDeploymentAllocHealthRequest{
  6104  		DeploymentAllocHealthRequest: structs.DeploymentAllocHealthRequest{
  6105  			DeploymentID:         uuid.Generate(),
  6106  			HealthyAllocationIDs: []string{uuid.Generate()},
  6107  		},
  6108  	}
  6109  	err := state.UpdateDeploymentAllocHealth(2, req)
  6110  	if err == nil || !strings.Contains(err.Error(), "does not exist") {
  6111  		t.Fatalf("expected error because the deployment doesn't exist: %v", err)
  6112  	}
  6113  }
  6114  
  6115  // Test that allocation health can't be set against a terminal deployment
  6116  func TestStateStore_UpsertDeploymentAllocHealth_Terminal(t *testing.T) {
  6117  	state := testStateStore(t)
  6118  
  6119  	// Insert a terminal deployment
  6120  	d := mock.Deployment()
  6121  	d.Status = structs.DeploymentStatusFailed
  6122  
  6123  	if err := state.UpsertDeployment(1, d); err != nil {
  6124  		t.Fatalf("bad: %v", err)
  6125  	}
  6126  
  6127  	// Set health against the terminal deployment
  6128  	req := &structs.ApplyDeploymentAllocHealthRequest{
  6129  		DeploymentAllocHealthRequest: structs.DeploymentAllocHealthRequest{
  6130  			DeploymentID:         d.ID,
  6131  			HealthyAllocationIDs: []string{uuid.Generate()},
  6132  		},
  6133  	}
  6134  	err := state.UpdateDeploymentAllocHealth(2, req)
  6135  	if err == nil || !strings.Contains(err.Error(), "has terminal status") {
  6136  		t.Fatalf("expected error because the deployment is terminal: %v", err)
  6137  	}
  6138  }
  6139  
  6140  // Test that allocation health can't be set against a nonexistent alloc
  6141  func TestStateStore_UpsertDeploymentAllocHealth_BadAlloc_Nonexistent(t *testing.T) {
  6142  	state := testStateStore(t)
  6143  
  6144  	// Insert a deployment
  6145  	d := mock.Deployment()
  6146  	if err := state.UpsertDeployment(1, d); err != nil {
  6147  		t.Fatalf("bad: %v", err)
  6148  	}
  6149  
  6150  	// Set health against the terminal deployment
  6151  	req := &structs.ApplyDeploymentAllocHealthRequest{
  6152  		DeploymentAllocHealthRequest: structs.DeploymentAllocHealthRequest{
  6153  			DeploymentID:         d.ID,
  6154  			HealthyAllocationIDs: []string{uuid.Generate()},
  6155  		},
  6156  	}
  6157  	err := state.UpdateDeploymentAllocHealth(2, req)
  6158  	if err == nil || !strings.Contains(err.Error(), "unknown alloc") {
  6159  		t.Fatalf("expected error because the alloc doesn't exist: %v", err)
  6160  	}
  6161  }
  6162  
  6163  // Test that allocation health can't be set for an alloc with mismatched
  6164  // deployment ids
  6165  func TestStateStore_UpsertDeploymentAllocHealth_BadAlloc_MismatchDeployment(t *testing.T) {
  6166  	state := testStateStore(t)
  6167  
  6168  	// Insert two  deployment
  6169  	d1 := mock.Deployment()
  6170  	d2 := mock.Deployment()
  6171  	if err := state.UpsertDeployment(1, d1); err != nil {
  6172  		t.Fatalf("bad: %v", err)
  6173  	}
  6174  	if err := state.UpsertDeployment(2, d2); err != nil {
  6175  		t.Fatalf("bad: %v", err)
  6176  	}
  6177  
  6178  	// Insert an alloc for a random deployment
  6179  	a := mock.Alloc()
  6180  	a.DeploymentID = d1.ID
  6181  	if err := state.UpsertAllocs(3, []*structs.Allocation{a}); err != nil {
  6182  		t.Fatalf("bad: %v", err)
  6183  	}
  6184  
  6185  	// Set health against the terminal deployment
  6186  	req := &structs.ApplyDeploymentAllocHealthRequest{
  6187  		DeploymentAllocHealthRequest: structs.DeploymentAllocHealthRequest{
  6188  			DeploymentID:         d2.ID,
  6189  			HealthyAllocationIDs: []string{a.ID},
  6190  		},
  6191  	}
  6192  	err := state.UpdateDeploymentAllocHealth(4, req)
  6193  	if err == nil || !strings.Contains(err.Error(), "not part of deployment") {
  6194  		t.Fatalf("expected error because the alloc isn't part of the deployment: %v", err)
  6195  	}
  6196  }
  6197  
  6198  // Test that allocation health is properly set
  6199  func TestStateStore_UpsertDeploymentAllocHealth(t *testing.T) {
  6200  	state := testStateStore(t)
  6201  
  6202  	// Insert a deployment
  6203  	d := mock.Deployment()
  6204  	d.TaskGroups["web"].ProgressDeadline = 5 * time.Minute
  6205  	if err := state.UpsertDeployment(1, d); err != nil {
  6206  		t.Fatalf("bad: %v", err)
  6207  	}
  6208  
  6209  	// Insert two allocations
  6210  	a1 := mock.Alloc()
  6211  	a1.DeploymentID = d.ID
  6212  	a2 := mock.Alloc()
  6213  	a2.DeploymentID = d.ID
  6214  	if err := state.UpsertAllocs(2, []*structs.Allocation{a1, a2}); err != nil {
  6215  		t.Fatalf("bad: %v", err)
  6216  	}
  6217  
  6218  	// Create a job to roll back to
  6219  	j := mock.Job()
  6220  
  6221  	// Create an eval that should be upserted
  6222  	e := mock.Eval()
  6223  
  6224  	// Create a status update for the deployment
  6225  	status, desc := structs.DeploymentStatusFailed, "foo"
  6226  	u := &structs.DeploymentStatusUpdate{
  6227  		DeploymentID:      d.ID,
  6228  		Status:            status,
  6229  		StatusDescription: desc,
  6230  	}
  6231  
  6232  	// Capture the time for the update
  6233  	ts := time.Now()
  6234  
  6235  	// Set health against the deployment
  6236  	req := &structs.ApplyDeploymentAllocHealthRequest{
  6237  		DeploymentAllocHealthRequest: structs.DeploymentAllocHealthRequest{
  6238  			DeploymentID:           d.ID,
  6239  			HealthyAllocationIDs:   []string{a1.ID},
  6240  			UnhealthyAllocationIDs: []string{a2.ID},
  6241  		},
  6242  		Job:              j,
  6243  		Eval:             e,
  6244  		DeploymentUpdate: u,
  6245  		Timestamp:        ts,
  6246  	}
  6247  	err := state.UpdateDeploymentAllocHealth(3, req)
  6248  	if err != nil {
  6249  		t.Fatalf("bad: %v", err)
  6250  	}
  6251  
  6252  	// Check that the status was updated properly
  6253  	ws := memdb.NewWatchSet()
  6254  	dout, err := state.DeploymentByID(ws, d.ID)
  6255  	if err != nil {
  6256  		t.Fatalf("bad: %v", err)
  6257  	}
  6258  	if dout.Status != status || dout.StatusDescription != desc {
  6259  		t.Fatalf("bad: %#v", dout)
  6260  	}
  6261  
  6262  	// Check that the evaluation was created
  6263  	eout, _ := state.EvalByID(ws, e.ID)
  6264  	if err != nil {
  6265  		t.Fatalf("bad: %v", err)
  6266  	}
  6267  	if eout == nil {
  6268  		t.Fatalf("bad: %#v", eout)
  6269  	}
  6270  
  6271  	// Check that the job was created
  6272  	jout, _ := state.JobByID(ws, j.Namespace, j.ID)
  6273  	if err != nil {
  6274  		t.Fatalf("bad: %v", err)
  6275  	}
  6276  	if jout == nil {
  6277  		t.Fatalf("bad: %#v", jout)
  6278  	}
  6279  
  6280  	// Check the status of the allocs
  6281  	out1, err := state.AllocByID(ws, a1.ID)
  6282  	if err != nil {
  6283  		t.Fatalf("err: %v", err)
  6284  	}
  6285  	out2, err := state.AllocByID(ws, a2.ID)
  6286  	if err != nil {
  6287  		t.Fatalf("err: %v", err)
  6288  	}
  6289  
  6290  	if !out1.DeploymentStatus.IsHealthy() {
  6291  		t.Fatalf("bad: alloc %q not healthy", out1.ID)
  6292  	}
  6293  	if !out2.DeploymentStatus.IsUnhealthy() {
  6294  		t.Fatalf("bad: alloc %q not unhealthy", out2.ID)
  6295  	}
  6296  
  6297  	if !out1.DeploymentStatus.Timestamp.Equal(ts) {
  6298  		t.Fatalf("bad: alloc %q had timestamp %v; want %v", out1.ID, out1.DeploymentStatus.Timestamp, ts)
  6299  	}
  6300  	if !out2.DeploymentStatus.Timestamp.Equal(ts) {
  6301  		t.Fatalf("bad: alloc %q had timestamp %v; want %v", out2.ID, out2.DeploymentStatus.Timestamp, ts)
  6302  	}
  6303  }
  6304  
  6305  func TestStateStore_UpsertVaultAccessors(t *testing.T) {
  6306  	state := testStateStore(t)
  6307  	a := mock.VaultAccessor()
  6308  	a2 := mock.VaultAccessor()
  6309  
  6310  	ws := memdb.NewWatchSet()
  6311  	if _, err := state.VaultAccessor(ws, a.Accessor); err != nil {
  6312  		t.Fatalf("err: %v", err)
  6313  	}
  6314  
  6315  	if _, err := state.VaultAccessor(ws, a2.Accessor); err != nil {
  6316  		t.Fatalf("err: %v", err)
  6317  	}
  6318  
  6319  	err := state.UpsertVaultAccessor(1000, []*structs.VaultAccessor{a, a2})
  6320  	if err != nil {
  6321  		t.Fatalf("err: %v", err)
  6322  	}
  6323  
  6324  	if !watchFired(ws) {
  6325  		t.Fatalf("bad")
  6326  	}
  6327  
  6328  	ws = memdb.NewWatchSet()
  6329  	out, err := state.VaultAccessor(ws, a.Accessor)
  6330  	if err != nil {
  6331  		t.Fatalf("err: %v", err)
  6332  	}
  6333  
  6334  	if !reflect.DeepEqual(a, out) {
  6335  		t.Fatalf("bad: %#v %#v", a, out)
  6336  	}
  6337  
  6338  	out, err = state.VaultAccessor(ws, a2.Accessor)
  6339  	if err != nil {
  6340  		t.Fatalf("err: %v", err)
  6341  	}
  6342  
  6343  	if !reflect.DeepEqual(a2, out) {
  6344  		t.Fatalf("bad: %#v %#v", a2, out)
  6345  	}
  6346  
  6347  	iter, err := state.VaultAccessors(ws)
  6348  	if err != nil {
  6349  		t.Fatalf("err: %v", err)
  6350  	}
  6351  
  6352  	count := 0
  6353  	for {
  6354  		raw := iter.Next()
  6355  		if raw == nil {
  6356  			break
  6357  		}
  6358  
  6359  		count++
  6360  		accessor := raw.(*structs.VaultAccessor)
  6361  
  6362  		if !reflect.DeepEqual(accessor, a) && !reflect.DeepEqual(accessor, a2) {
  6363  			t.Fatalf("bad: %#v", accessor)
  6364  		}
  6365  	}
  6366  
  6367  	if count != 2 {
  6368  		t.Fatalf("bad: %d", count)
  6369  	}
  6370  
  6371  	index, err := state.Index("vault_accessors")
  6372  	if err != nil {
  6373  		t.Fatalf("err: %v", err)
  6374  	}
  6375  	if index != 1000 {
  6376  		t.Fatalf("bad: %d", index)
  6377  	}
  6378  
  6379  	if watchFired(ws) {
  6380  		t.Fatalf("bad")
  6381  	}
  6382  }
  6383  
  6384  func TestStateStore_DeleteVaultAccessors(t *testing.T) {
  6385  	state := testStateStore(t)
  6386  	a1 := mock.VaultAccessor()
  6387  	a2 := mock.VaultAccessor()
  6388  	accessors := []*structs.VaultAccessor{a1, a2}
  6389  
  6390  	err := state.UpsertVaultAccessor(1000, accessors)
  6391  	if err != nil {
  6392  		t.Fatalf("err: %v", err)
  6393  	}
  6394  
  6395  	ws := memdb.NewWatchSet()
  6396  	if _, err := state.VaultAccessor(ws, a1.Accessor); err != nil {
  6397  		t.Fatalf("err: %v", err)
  6398  	}
  6399  
  6400  	err = state.DeleteVaultAccessors(1001, accessors)
  6401  	if err != nil {
  6402  		t.Fatalf("err: %v", err)
  6403  	}
  6404  
  6405  	if !watchFired(ws) {
  6406  		t.Fatalf("bad")
  6407  	}
  6408  
  6409  	ws = memdb.NewWatchSet()
  6410  	out, err := state.VaultAccessor(ws, a1.Accessor)
  6411  	if err != nil {
  6412  		t.Fatalf("err: %v", err)
  6413  	}
  6414  	if out != nil {
  6415  		t.Fatalf("bad: %#v %#v", a1, out)
  6416  	}
  6417  	out, err = state.VaultAccessor(ws, a2.Accessor)
  6418  	if err != nil {
  6419  		t.Fatalf("err: %v", err)
  6420  	}
  6421  	if out != nil {
  6422  		t.Fatalf("bad: %#v %#v", a2, out)
  6423  	}
  6424  
  6425  	index, err := state.Index("vault_accessors")
  6426  	if err != nil {
  6427  		t.Fatalf("err: %v", err)
  6428  	}
  6429  	if index != 1001 {
  6430  		t.Fatalf("bad: %d", index)
  6431  	}
  6432  
  6433  	if watchFired(ws) {
  6434  		t.Fatalf("bad")
  6435  	}
  6436  }
  6437  
  6438  func TestStateStore_VaultAccessorsByAlloc(t *testing.T) {
  6439  	state := testStateStore(t)
  6440  	alloc := mock.Alloc()
  6441  	var accessors []*structs.VaultAccessor
  6442  	var expected []*structs.VaultAccessor
  6443  
  6444  	for i := 0; i < 5; i++ {
  6445  		accessor := mock.VaultAccessor()
  6446  		accessor.AllocID = alloc.ID
  6447  		expected = append(expected, accessor)
  6448  		accessors = append(accessors, accessor)
  6449  	}
  6450  
  6451  	for i := 0; i < 10; i++ {
  6452  		accessor := mock.VaultAccessor()
  6453  		accessors = append(accessors, accessor)
  6454  	}
  6455  
  6456  	err := state.UpsertVaultAccessor(1000, accessors)
  6457  	if err != nil {
  6458  		t.Fatalf("err: %v", err)
  6459  	}
  6460  
  6461  	ws := memdb.NewWatchSet()
  6462  	out, err := state.VaultAccessorsByAlloc(ws, alloc.ID)
  6463  	if err != nil {
  6464  		t.Fatalf("err: %v", err)
  6465  	}
  6466  
  6467  	if len(expected) != len(out) {
  6468  		t.Fatalf("bad: %#v %#v", len(expected), len(out))
  6469  	}
  6470  
  6471  	index, err := state.Index("vault_accessors")
  6472  	if err != nil {
  6473  		t.Fatalf("err: %v", err)
  6474  	}
  6475  	if index != 1000 {
  6476  		t.Fatalf("bad: %d", index)
  6477  	}
  6478  
  6479  	if watchFired(ws) {
  6480  		t.Fatalf("bad")
  6481  	}
  6482  }
  6483  
  6484  func TestStateStore_VaultAccessorsByNode(t *testing.T) {
  6485  	state := testStateStore(t)
  6486  	node := mock.Node()
  6487  	var accessors []*structs.VaultAccessor
  6488  	var expected []*structs.VaultAccessor
  6489  
  6490  	for i := 0; i < 5; i++ {
  6491  		accessor := mock.VaultAccessor()
  6492  		accessor.NodeID = node.ID
  6493  		expected = append(expected, accessor)
  6494  		accessors = append(accessors, accessor)
  6495  	}
  6496  
  6497  	for i := 0; i < 10; i++ {
  6498  		accessor := mock.VaultAccessor()
  6499  		accessors = append(accessors, accessor)
  6500  	}
  6501  
  6502  	err := state.UpsertVaultAccessor(1000, accessors)
  6503  	if err != nil {
  6504  		t.Fatalf("err: %v", err)
  6505  	}
  6506  
  6507  	ws := memdb.NewWatchSet()
  6508  	out, err := state.VaultAccessorsByNode(ws, node.ID)
  6509  	if err != nil {
  6510  		t.Fatalf("err: %v", err)
  6511  	}
  6512  
  6513  	if len(expected) != len(out) {
  6514  		t.Fatalf("bad: %#v %#v", len(expected), len(out))
  6515  	}
  6516  
  6517  	index, err := state.Index("vault_accessors")
  6518  	if err != nil {
  6519  		t.Fatalf("err: %v", err)
  6520  	}
  6521  	if index != 1000 {
  6522  		t.Fatalf("bad: %d", index)
  6523  	}
  6524  
  6525  	if watchFired(ws) {
  6526  		t.Fatalf("bad")
  6527  	}
  6528  }
  6529  
  6530  func TestStateStore_RestoreVaultAccessor(t *testing.T) {
  6531  	state := testStateStore(t)
  6532  	a := mock.VaultAccessor()
  6533  
  6534  	restore, err := state.Restore()
  6535  	if err != nil {
  6536  		t.Fatalf("err: %v", err)
  6537  	}
  6538  
  6539  	err = restore.VaultAccessorRestore(a)
  6540  	if err != nil {
  6541  		t.Fatalf("err: %v", err)
  6542  	}
  6543  	restore.Commit()
  6544  
  6545  	ws := memdb.NewWatchSet()
  6546  	out, err := state.VaultAccessor(ws, a.Accessor)
  6547  	if err != nil {
  6548  		t.Fatalf("err: %v", err)
  6549  	}
  6550  
  6551  	if !reflect.DeepEqual(out, a) {
  6552  		t.Fatalf("Bad: %#v %#v", out, a)
  6553  	}
  6554  
  6555  	if watchFired(ws) {
  6556  		t.Fatalf("bad")
  6557  	}
  6558  }
  6559  
  6560  func TestStateStore_UpsertACLPolicy(t *testing.T) {
  6561  	state := testStateStore(t)
  6562  	policy := mock.ACLPolicy()
  6563  	policy2 := mock.ACLPolicy()
  6564  
  6565  	ws := memdb.NewWatchSet()
  6566  	if _, err := state.ACLPolicyByName(ws, policy.Name); err != nil {
  6567  		t.Fatalf("err: %v", err)
  6568  	}
  6569  	if _, err := state.ACLPolicyByName(ws, policy2.Name); err != nil {
  6570  		t.Fatalf("err: %v", err)
  6571  	}
  6572  
  6573  	if err := state.UpsertACLPolicies(1000,
  6574  		[]*structs.ACLPolicy{policy, policy2}); err != nil {
  6575  		t.Fatalf("err: %v", err)
  6576  	}
  6577  	if !watchFired(ws) {
  6578  		t.Fatalf("bad")
  6579  	}
  6580  
  6581  	ws = memdb.NewWatchSet()
  6582  	out, err := state.ACLPolicyByName(ws, policy.Name)
  6583  	assert.Equal(t, nil, err)
  6584  	assert.Equal(t, policy, out)
  6585  
  6586  	out, err = state.ACLPolicyByName(ws, policy2.Name)
  6587  	assert.Equal(t, nil, err)
  6588  	assert.Equal(t, policy2, out)
  6589  
  6590  	iter, err := state.ACLPolicies(ws)
  6591  	if err != nil {
  6592  		t.Fatalf("err: %v", err)
  6593  	}
  6594  
  6595  	// Ensure we see both policies
  6596  	count := 0
  6597  	for {
  6598  		raw := iter.Next()
  6599  		if raw == nil {
  6600  			break
  6601  		}
  6602  		count++
  6603  	}
  6604  	if count != 2 {
  6605  		t.Fatalf("bad: %d", count)
  6606  	}
  6607  
  6608  	index, err := state.Index("acl_policy")
  6609  	if err != nil {
  6610  		t.Fatalf("err: %v", err)
  6611  	}
  6612  	if index != 1000 {
  6613  		t.Fatalf("bad: %d", index)
  6614  	}
  6615  
  6616  	if watchFired(ws) {
  6617  		t.Fatalf("bad")
  6618  	}
  6619  }
  6620  
  6621  func TestStateStore_DeleteACLPolicy(t *testing.T) {
  6622  	state := testStateStore(t)
  6623  	policy := mock.ACLPolicy()
  6624  	policy2 := mock.ACLPolicy()
  6625  
  6626  	// Create the policy
  6627  	if err := state.UpsertACLPolicies(1000,
  6628  		[]*structs.ACLPolicy{policy, policy2}); err != nil {
  6629  		t.Fatalf("err: %v", err)
  6630  	}
  6631  
  6632  	// Create a watcher
  6633  	ws := memdb.NewWatchSet()
  6634  	if _, err := state.ACLPolicyByName(ws, policy.Name); err != nil {
  6635  		t.Fatalf("err: %v", err)
  6636  	}
  6637  
  6638  	// Delete the policy
  6639  	if err := state.DeleteACLPolicies(1001,
  6640  		[]string{policy.Name, policy2.Name}); err != nil {
  6641  		t.Fatalf("err: %v", err)
  6642  	}
  6643  
  6644  	// Ensure watching triggered
  6645  	if !watchFired(ws) {
  6646  		t.Fatalf("bad")
  6647  	}
  6648  
  6649  	// Ensure we don't get the object back
  6650  	ws = memdb.NewWatchSet()
  6651  	out, err := state.ACLPolicyByName(ws, policy.Name)
  6652  	assert.Equal(t, nil, err)
  6653  	if out != nil {
  6654  		t.Fatalf("bad: %#v", out)
  6655  	}
  6656  
  6657  	iter, err := state.ACLPolicies(ws)
  6658  	if err != nil {
  6659  		t.Fatalf("err: %v", err)
  6660  	}
  6661  
  6662  	// Ensure we see both policies
  6663  	count := 0
  6664  	for {
  6665  		raw := iter.Next()
  6666  		if raw == nil {
  6667  			break
  6668  		}
  6669  		count++
  6670  	}
  6671  	if count != 0 {
  6672  		t.Fatalf("bad: %d", count)
  6673  	}
  6674  
  6675  	index, err := state.Index("acl_policy")
  6676  	if err != nil {
  6677  		t.Fatalf("err: %v", err)
  6678  	}
  6679  	if index != 1001 {
  6680  		t.Fatalf("bad: %d", index)
  6681  	}
  6682  
  6683  	if watchFired(ws) {
  6684  		t.Fatalf("bad")
  6685  	}
  6686  }
  6687  
  6688  func TestStateStore_ACLPolicyByNamePrefix(t *testing.T) {
  6689  	state := testStateStore(t)
  6690  	names := []string{
  6691  		"foo",
  6692  		"bar",
  6693  		"foobar",
  6694  		"foozip",
  6695  		"zip",
  6696  	}
  6697  
  6698  	// Create the policies
  6699  	var baseIndex uint64 = 1000
  6700  	for _, name := range names {
  6701  		p := mock.ACLPolicy()
  6702  		p.Name = name
  6703  		if err := state.UpsertACLPolicies(baseIndex, []*structs.ACLPolicy{p}); err != nil {
  6704  			t.Fatalf("err: %v", err)
  6705  		}
  6706  		baseIndex++
  6707  	}
  6708  
  6709  	// Scan by prefix
  6710  	iter, err := state.ACLPolicyByNamePrefix(nil, "foo")
  6711  	if err != nil {
  6712  		t.Fatalf("err: %v", err)
  6713  	}
  6714  
  6715  	// Ensure we see both policies
  6716  	count := 0
  6717  	out := []string{}
  6718  	for {
  6719  		raw := iter.Next()
  6720  		if raw == nil {
  6721  			break
  6722  		}
  6723  		count++
  6724  		out = append(out, raw.(*structs.ACLPolicy).Name)
  6725  	}
  6726  	if count != 3 {
  6727  		t.Fatalf("bad: %d %v", count, out)
  6728  	}
  6729  	sort.Strings(out)
  6730  
  6731  	expect := []string{"foo", "foobar", "foozip"}
  6732  	assert.Equal(t, expect, out)
  6733  }
  6734  
  6735  func TestStateStore_BootstrapACLTokens(t *testing.T) {
  6736  	state := testStateStore(t)
  6737  	tk1 := mock.ACLToken()
  6738  	tk2 := mock.ACLToken()
  6739  
  6740  	ok, resetIdx, err := state.CanBootstrapACLToken()
  6741  	assert.Nil(t, err)
  6742  	assert.Equal(t, true, ok)
  6743  	assert.EqualValues(t, 0, resetIdx)
  6744  
  6745  	if err := state.BootstrapACLTokens(1000, 0, tk1); err != nil {
  6746  		t.Fatalf("err: %v", err)
  6747  	}
  6748  
  6749  	out, err := state.ACLTokenByAccessorID(nil, tk1.AccessorID)
  6750  	assert.Equal(t, nil, err)
  6751  	assert.Equal(t, tk1, out)
  6752  
  6753  	ok, resetIdx, err = state.CanBootstrapACLToken()
  6754  	assert.Nil(t, err)
  6755  	assert.Equal(t, false, ok)
  6756  	assert.EqualValues(t, 1000, resetIdx)
  6757  
  6758  	if err := state.BootstrapACLTokens(1001, 0, tk2); err == nil {
  6759  		t.Fatalf("expected error")
  6760  	}
  6761  
  6762  	iter, err := state.ACLTokens(nil)
  6763  	if err != nil {
  6764  		t.Fatalf("err: %v", err)
  6765  	}
  6766  
  6767  	// Ensure we see both policies
  6768  	count := 0
  6769  	for {
  6770  		raw := iter.Next()
  6771  		if raw == nil {
  6772  			break
  6773  		}
  6774  		count++
  6775  	}
  6776  	if count != 1 {
  6777  		t.Fatalf("bad: %d", count)
  6778  	}
  6779  
  6780  	index, err := state.Index("acl_token")
  6781  	if err != nil {
  6782  		t.Fatalf("err: %v", err)
  6783  	}
  6784  	if index != 1000 {
  6785  		t.Fatalf("bad: %d", index)
  6786  	}
  6787  	index, err = state.Index("acl_token_bootstrap")
  6788  	if err != nil {
  6789  		t.Fatalf("err: %v", err)
  6790  	}
  6791  	if index != 1000 {
  6792  		t.Fatalf("bad: %d", index)
  6793  	}
  6794  
  6795  	// Should allow bootstrap with reset index
  6796  	if err := state.BootstrapACLTokens(1001, 1000, tk2); err != nil {
  6797  		t.Fatalf("err %v", err)
  6798  	}
  6799  
  6800  	// Check we've modified the index
  6801  	index, err = state.Index("acl_token")
  6802  	if err != nil {
  6803  		t.Fatalf("err: %v", err)
  6804  	}
  6805  	if index != 1001 {
  6806  		t.Fatalf("bad: %d", index)
  6807  	}
  6808  	index, err = state.Index("acl_token_bootstrap")
  6809  	if err != nil {
  6810  		t.Fatalf("err: %v", err)
  6811  	}
  6812  	if index != 1001 {
  6813  		t.Fatalf("bad: %d", index)
  6814  	}
  6815  }
  6816  
  6817  func TestStateStore_UpsertACLTokens(t *testing.T) {
  6818  	state := testStateStore(t)
  6819  	tk1 := mock.ACLToken()
  6820  	tk2 := mock.ACLToken()
  6821  
  6822  	ws := memdb.NewWatchSet()
  6823  	if _, err := state.ACLTokenByAccessorID(ws, tk1.AccessorID); err != nil {
  6824  		t.Fatalf("err: %v", err)
  6825  	}
  6826  	if _, err := state.ACLTokenByAccessorID(ws, tk2.AccessorID); err != nil {
  6827  		t.Fatalf("err: %v", err)
  6828  	}
  6829  
  6830  	if err := state.UpsertACLTokens(1000,
  6831  		[]*structs.ACLToken{tk1, tk2}); err != nil {
  6832  		t.Fatalf("err: %v", err)
  6833  	}
  6834  	if !watchFired(ws) {
  6835  		t.Fatalf("bad")
  6836  	}
  6837  
  6838  	ws = memdb.NewWatchSet()
  6839  	out, err := state.ACLTokenByAccessorID(ws, tk1.AccessorID)
  6840  	assert.Equal(t, nil, err)
  6841  	assert.Equal(t, tk1, out)
  6842  
  6843  	out, err = state.ACLTokenByAccessorID(ws, tk2.AccessorID)
  6844  	assert.Equal(t, nil, err)
  6845  	assert.Equal(t, tk2, out)
  6846  
  6847  	out, err = state.ACLTokenBySecretID(ws, tk1.SecretID)
  6848  	assert.Equal(t, nil, err)
  6849  	assert.Equal(t, tk1, out)
  6850  
  6851  	out, err = state.ACLTokenBySecretID(ws, tk2.SecretID)
  6852  	assert.Equal(t, nil, err)
  6853  	assert.Equal(t, tk2, out)
  6854  
  6855  	iter, err := state.ACLTokens(ws)
  6856  	if err != nil {
  6857  		t.Fatalf("err: %v", err)
  6858  	}
  6859  
  6860  	// Ensure we see both policies
  6861  	count := 0
  6862  	for {
  6863  		raw := iter.Next()
  6864  		if raw == nil {
  6865  			break
  6866  		}
  6867  		count++
  6868  	}
  6869  	if count != 2 {
  6870  		t.Fatalf("bad: %d", count)
  6871  	}
  6872  
  6873  	index, err := state.Index("acl_token")
  6874  	if err != nil {
  6875  		t.Fatalf("err: %v", err)
  6876  	}
  6877  	if index != 1000 {
  6878  		t.Fatalf("bad: %d", index)
  6879  	}
  6880  
  6881  	if watchFired(ws) {
  6882  		t.Fatalf("bad")
  6883  	}
  6884  }
  6885  
  6886  func TestStateStore_DeleteACLTokens(t *testing.T) {
  6887  	state := testStateStore(t)
  6888  	tk1 := mock.ACLToken()
  6889  	tk2 := mock.ACLToken()
  6890  
  6891  	// Create the tokens
  6892  	if err := state.UpsertACLTokens(1000,
  6893  		[]*structs.ACLToken{tk1, tk2}); err != nil {
  6894  		t.Fatalf("err: %v", err)
  6895  	}
  6896  
  6897  	// Create a watcher
  6898  	ws := memdb.NewWatchSet()
  6899  	if _, err := state.ACLTokenByAccessorID(ws, tk1.AccessorID); err != nil {
  6900  		t.Fatalf("err: %v", err)
  6901  	}
  6902  
  6903  	// Delete the token
  6904  	if err := state.DeleteACLTokens(1001,
  6905  		[]string{tk1.AccessorID, tk2.AccessorID}); err != nil {
  6906  		t.Fatalf("err: %v", err)
  6907  	}
  6908  
  6909  	// Ensure watching triggered
  6910  	if !watchFired(ws) {
  6911  		t.Fatalf("bad")
  6912  	}
  6913  
  6914  	// Ensure we don't get the object back
  6915  	ws = memdb.NewWatchSet()
  6916  	out, err := state.ACLTokenByAccessorID(ws, tk1.AccessorID)
  6917  	assert.Equal(t, nil, err)
  6918  	if out != nil {
  6919  		t.Fatalf("bad: %#v", out)
  6920  	}
  6921  
  6922  	iter, err := state.ACLTokens(ws)
  6923  	if err != nil {
  6924  		t.Fatalf("err: %v", err)
  6925  	}
  6926  
  6927  	// Ensure we see both policies
  6928  	count := 0
  6929  	for {
  6930  		raw := iter.Next()
  6931  		if raw == nil {
  6932  			break
  6933  		}
  6934  		count++
  6935  	}
  6936  	if count != 0 {
  6937  		t.Fatalf("bad: %d", count)
  6938  	}
  6939  
  6940  	index, err := state.Index("acl_token")
  6941  	if err != nil {
  6942  		t.Fatalf("err: %v", err)
  6943  	}
  6944  	if index != 1001 {
  6945  		t.Fatalf("bad: %d", index)
  6946  	}
  6947  
  6948  	if watchFired(ws) {
  6949  		t.Fatalf("bad")
  6950  	}
  6951  }
  6952  
  6953  func TestStateStore_ACLTokenByAccessorIDPrefix(t *testing.T) {
  6954  	state := testStateStore(t)
  6955  	prefixes := []string{
  6956  		"aaaa",
  6957  		"aabb",
  6958  		"bbbb",
  6959  		"bbcc",
  6960  		"ffff",
  6961  	}
  6962  
  6963  	// Create the tokens
  6964  	var baseIndex uint64 = 1000
  6965  	for _, prefix := range prefixes {
  6966  		tk := mock.ACLToken()
  6967  		tk.AccessorID = prefix + tk.AccessorID[4:]
  6968  		if err := state.UpsertACLTokens(baseIndex, []*structs.ACLToken{tk}); err != nil {
  6969  			t.Fatalf("err: %v", err)
  6970  		}
  6971  		baseIndex++
  6972  	}
  6973  
  6974  	// Scan by prefix
  6975  	iter, err := state.ACLTokenByAccessorIDPrefix(nil, "aa")
  6976  	if err != nil {
  6977  		t.Fatalf("err: %v", err)
  6978  	}
  6979  
  6980  	// Ensure we see both tokens
  6981  	count := 0
  6982  	out := []string{}
  6983  	for {
  6984  		raw := iter.Next()
  6985  		if raw == nil {
  6986  			break
  6987  		}
  6988  		count++
  6989  		out = append(out, raw.(*structs.ACLToken).AccessorID[:4])
  6990  	}
  6991  	if count != 2 {
  6992  		t.Fatalf("bad: %d %v", count, out)
  6993  	}
  6994  	sort.Strings(out)
  6995  
  6996  	expect := []string{"aaaa", "aabb"}
  6997  	assert.Equal(t, expect, out)
  6998  }
  6999  
  7000  func TestStateStore_RestoreACLPolicy(t *testing.T) {
  7001  	state := testStateStore(t)
  7002  	policy := mock.ACLPolicy()
  7003  
  7004  	restore, err := state.Restore()
  7005  	if err != nil {
  7006  		t.Fatalf("err: %v", err)
  7007  	}
  7008  
  7009  	err = restore.ACLPolicyRestore(policy)
  7010  	if err != nil {
  7011  		t.Fatalf("err: %v", err)
  7012  	}
  7013  	restore.Commit()
  7014  
  7015  	ws := memdb.NewWatchSet()
  7016  	out, err := state.ACLPolicyByName(ws, policy.Name)
  7017  	if err != nil {
  7018  		t.Fatalf("err: %v", err)
  7019  	}
  7020  	assert.Equal(t, policy, out)
  7021  }
  7022  
  7023  func TestStateStore_ACLTokensByGlobal(t *testing.T) {
  7024  	state := testStateStore(t)
  7025  	tk1 := mock.ACLToken()
  7026  	tk2 := mock.ACLToken()
  7027  	tk3 := mock.ACLToken()
  7028  	tk4 := mock.ACLToken()
  7029  	tk3.Global = true
  7030  
  7031  	if err := state.UpsertACLTokens(1000,
  7032  		[]*structs.ACLToken{tk1, tk2, tk3, tk4}); err != nil {
  7033  		t.Fatalf("err: %v", err)
  7034  	}
  7035  
  7036  	iter, err := state.ACLTokensByGlobal(nil, true)
  7037  	if err != nil {
  7038  		t.Fatalf("err: %v", err)
  7039  	}
  7040  
  7041  	// Ensure we see the one global policies
  7042  	count := 0
  7043  	for {
  7044  		raw := iter.Next()
  7045  		if raw == nil {
  7046  			break
  7047  		}
  7048  		count++
  7049  	}
  7050  	if count != 1 {
  7051  		t.Fatalf("bad: %d", count)
  7052  	}
  7053  }
  7054  
  7055  func TestStateStore_RestoreACLToken(t *testing.T) {
  7056  	state := testStateStore(t)
  7057  	token := mock.ACLToken()
  7058  
  7059  	restore, err := state.Restore()
  7060  	if err != nil {
  7061  		t.Fatalf("err: %v", err)
  7062  	}
  7063  
  7064  	err = restore.ACLTokenRestore(token)
  7065  	if err != nil {
  7066  		t.Fatalf("err: %v", err)
  7067  	}
  7068  	restore.Commit()
  7069  
  7070  	ws := memdb.NewWatchSet()
  7071  	out, err := state.ACLTokenByAccessorID(ws, token.AccessorID)
  7072  	if err != nil {
  7073  		t.Fatalf("err: %v", err)
  7074  	}
  7075  	assert.Equal(t, token, out)
  7076  }
  7077  
  7078  func TestStateStore_SchedulerConfig(t *testing.T) {
  7079  	state := testStateStore(t)
  7080  	schedConfig := &structs.SchedulerConfiguration{
  7081  		PreemptionConfig: structs.PreemptionConfig{
  7082  			SystemSchedulerEnabled: false,
  7083  		},
  7084  		CreateIndex: 100,
  7085  		ModifyIndex: 200,
  7086  	}
  7087  
  7088  	require := require.New(t)
  7089  	restore, err := state.Restore()
  7090  
  7091  	require.Nil(err)
  7092  
  7093  	err = restore.SchedulerConfigRestore(schedConfig)
  7094  	require.Nil(err)
  7095  
  7096  	restore.Commit()
  7097  
  7098  	modIndex, out, err := state.SchedulerConfig()
  7099  	require.Nil(err)
  7100  	require.Equal(schedConfig.ModifyIndex, modIndex)
  7101  
  7102  	require.Equal(schedConfig, out)
  7103  }
  7104  
  7105  func TestStateStore_Abandon(t *testing.T) {
  7106  	s := testStateStore(t)
  7107  	abandonCh := s.AbandonCh()
  7108  	s.Abandon()
  7109  	select {
  7110  	case <-abandonCh:
  7111  	default:
  7112  		t.Fatalf("bad")
  7113  	}
  7114  }
  7115  
  7116  // Verifies that an error is returned when an allocation doesn't exist in the state store.
  7117  func TestStateSnapshot_DenormalizeAllocationDiffSlice_AllocDoesNotExist(t *testing.T) {
  7118  	state := testStateStore(t)
  7119  	alloc := mock.Alloc()
  7120  	require := require.New(t)
  7121  
  7122  	// Insert job
  7123  	err := state.UpsertJob(999, alloc.Job)
  7124  	require.NoError(err)
  7125  
  7126  	allocDiffs := []*structs.AllocationDiff{
  7127  		{
  7128  			ID: alloc.ID,
  7129  		},
  7130  	}
  7131  
  7132  	snap, err := state.Snapshot()
  7133  	require.NoError(err)
  7134  
  7135  	denormalizedAllocs, err := snap.DenormalizeAllocationDiffSlice(allocDiffs)
  7136  
  7137  	require.EqualError(err, fmt.Sprintf("alloc %v doesn't exist", alloc.ID))
  7138  	require.Nil(denormalizedAllocs)
  7139  }
  7140  
  7141  // TestStateStore_SnapshotAfter_OK asserts StateStore.SnapshotAfter blocks
  7142  // until the StateStore's latest index is >= the requested index.
  7143  func TestStateStore_SnapshotAfter_OK(t *testing.T) {
  7144  	t.Parallel()
  7145  
  7146  	s := testStateStore(t)
  7147  	index, err := s.LatestIndex()
  7148  	require.NoError(t, err)
  7149  
  7150  	node := mock.Node()
  7151  	require.NoError(t, s.UpsertNode(index+1, node))
  7152  
  7153  	// Assert SnapshotAfter returns immediately if index < latest index
  7154  	ctx, cancel := context.WithTimeout(context.Background(), 0)
  7155  	snap, err := s.SnapshotAfter(ctx, index)
  7156  	cancel()
  7157  	require.NoError(t, err)
  7158  
  7159  	snapIndex, err := snap.LatestIndex()
  7160  	require.NoError(t, err)
  7161  	if snapIndex <= index {
  7162  		require.Fail(t, "snapshot index should be greater than index")
  7163  	}
  7164  
  7165  	// Assert SnapshotAfter returns immediately if index == latest index
  7166  	ctx, cancel = context.WithTimeout(context.Background(), 0)
  7167  	snap, err = s.SnapshotAfter(ctx, index+1)
  7168  	cancel()
  7169  	require.NoError(t, err)
  7170  
  7171  	snapIndex, err = snap.LatestIndex()
  7172  	require.NoError(t, err)
  7173  	require.Equal(t, snapIndex, index+1)
  7174  
  7175  	// Assert SnapshotAfter blocks if index > latest index
  7176  	errCh := make(chan error, 1)
  7177  	ctx, cancel = context.WithTimeout(context.Background(), 10*time.Second)
  7178  	defer cancel()
  7179  	go func() {
  7180  		defer close(errCh)
  7181  		waitIndex := index + 2
  7182  		snap, err := s.SnapshotAfter(ctx, waitIndex)
  7183  		if err != nil {
  7184  			errCh <- err
  7185  			return
  7186  		}
  7187  
  7188  		snapIndex, err := snap.LatestIndex()
  7189  		if err != nil {
  7190  			errCh <- err
  7191  			return
  7192  		}
  7193  
  7194  		if snapIndex < waitIndex {
  7195  			errCh <- fmt.Errorf("snapshot index < wait index: %d < %d", snapIndex, waitIndex)
  7196  			return
  7197  		}
  7198  	}()
  7199  
  7200  	select {
  7201  	case err := <-errCh:
  7202  		require.NoError(t, err)
  7203  	case <-time.After(500 * time.Millisecond):
  7204  		// Let it block for a bit before unblocking by upserting
  7205  	}
  7206  
  7207  	node.Name = "hal"
  7208  	require.NoError(t, s.UpsertNode(index+2, node))
  7209  
  7210  	select {
  7211  	case err := <-errCh:
  7212  		require.NoError(t, err)
  7213  	case <-time.After(5 * time.Second):
  7214  		require.Fail(t, "timed out waiting for SnapshotAfter to unblock")
  7215  	}
  7216  }
  7217  
  7218  // TestStateStore_SnapshotAfter_Timeout asserts StateStore.SnapshotAfter
  7219  // returns an error if the desired index is not reached within the deadline.
  7220  func TestStateStore_SnapshotAfter_Timeout(t *testing.T) {
  7221  	t.Parallel()
  7222  
  7223  	s := testStateStore(t)
  7224  	index, err := s.LatestIndex()
  7225  	require.NoError(t, err)
  7226  
  7227  	// Assert SnapshotAfter blocks if index > latest index
  7228  	ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond)
  7229  	defer cancel()
  7230  	snap, err := s.SnapshotAfter(ctx, index+1)
  7231  	require.EqualError(t, err, context.DeadlineExceeded.Error())
  7232  	require.Nil(t, snap)
  7233  }
  7234  
  7235  // watchFired is a helper for unit tests that returns if the given watch set
  7236  // fired (it doesn't care which watch actually fired). This uses a fixed
  7237  // timeout since we already expect the event happened before calling this and
  7238  // just need to distinguish a fire from a timeout. We do need a little time to
  7239  // allow the watch to set up any goroutines, though.
  7240  func watchFired(ws memdb.WatchSet) bool {
  7241  	timedOut := ws.Watch(time.After(50 * time.Millisecond))
  7242  	return !timedOut
  7243  }
  7244  
  7245  // NodeIDSort is used to sort nodes by ID
  7246  type NodeIDSort []*structs.Node
  7247  
  7248  func (n NodeIDSort) Len() int {
  7249  	return len(n)
  7250  }
  7251  
  7252  func (n NodeIDSort) Less(i, j int) bool {
  7253  	return n[i].ID < n[j].ID
  7254  }
  7255  
  7256  func (n NodeIDSort) Swap(i, j int) {
  7257  	n[i], n[j] = n[j], n[i]
  7258  }
  7259  
  7260  // JobIDis used to sort jobs by id
  7261  type JobIDSort []*structs.Job
  7262  
  7263  func (n JobIDSort) Len() int {
  7264  	return len(n)
  7265  }
  7266  
  7267  func (n JobIDSort) Less(i, j int) bool {
  7268  	return n[i].ID < n[j].ID
  7269  }
  7270  
  7271  func (n JobIDSort) Swap(i, j int) {
  7272  	n[i], n[j] = n[j], n[i]
  7273  }
  7274  
  7275  // EvalIDis used to sort evals by id
  7276  type EvalIDSort []*structs.Evaluation
  7277  
  7278  func (n EvalIDSort) Len() int {
  7279  	return len(n)
  7280  }
  7281  
  7282  func (n EvalIDSort) Less(i, j int) bool {
  7283  	return n[i].ID < n[j].ID
  7284  }
  7285  
  7286  func (n EvalIDSort) Swap(i, j int) {
  7287  	n[i], n[j] = n[j], n[i]
  7288  }
  7289  
  7290  // AllocIDsort used to sort allocations by id
  7291  type AllocIDSort []*structs.Allocation
  7292  
  7293  func (n AllocIDSort) Len() int {
  7294  	return len(n)
  7295  }
  7296  
  7297  func (n AllocIDSort) Less(i, j int) bool {
  7298  	return n[i].ID < n[j].ID
  7299  }
  7300  
  7301  func (n AllocIDSort) Swap(i, j int) {
  7302  	n[i], n[j] = n[j], n[i]
  7303  }