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