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