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