github.com/taylorchu/nomad@v0.5.3-rc1.0.20170407200202-db11e7dd7b55/nomad/state/state_store_test.go (about) 1 package state 2 3 import ( 4 "fmt" 5 "os" 6 "reflect" 7 "sort" 8 "testing" 9 "time" 10 11 memdb "github.com/hashicorp/go-memdb" 12 "github.com/hashicorp/nomad/nomad/mock" 13 "github.com/hashicorp/nomad/nomad/structs" 14 ) 15 16 func testStateStore(t *testing.T) *StateStore { 17 state, err := NewStateStore(os.Stderr) 18 if err != nil { 19 t.Fatalf("err: %v", err) 20 } 21 if state == nil { 22 t.Fatalf("missing state") 23 } 24 return state 25 } 26 27 func TestStateStore_UpsertNode_Node(t *testing.T) { 28 state := testStateStore(t) 29 node := mock.Node() 30 31 // Create a watchset so we can test that upsert fires the watch 32 ws := memdb.NewWatchSet() 33 _, err := state.NodeByID(ws, node.ID) 34 if err != nil { 35 t.Fatalf("bad: %v", err) 36 } 37 38 err = state.UpsertNode(1000, node) 39 if err != nil { 40 t.Fatalf("err: %v", err) 41 } 42 if !watchFired(ws) { 43 t.Fatalf("bad") 44 } 45 46 ws = memdb.NewWatchSet() 47 out, err := state.NodeByID(ws, node.ID) 48 if err != nil { 49 t.Fatalf("err: %v", err) 50 } 51 52 if !reflect.DeepEqual(node, out) { 53 t.Fatalf("bad: %#v %#v", node, out) 54 } 55 56 index, err := state.Index("nodes") 57 if err != nil { 58 t.Fatalf("err: %v", err) 59 } 60 if index != 1000 { 61 t.Fatalf("bad: %d", index) 62 } 63 64 if watchFired(ws) { 65 t.Fatalf("bad") 66 } 67 } 68 69 func TestStateStore_DeleteNode_Node(t *testing.T) { 70 state := testStateStore(t) 71 node := mock.Node() 72 73 err := state.UpsertNode(1000, node) 74 if err != nil { 75 t.Fatalf("err: %v", err) 76 } 77 78 // Create a watchset so we can test that delete fires the watch 79 ws := memdb.NewWatchSet() 80 if _, err := state.NodeByID(ws, node.ID); err != nil { 81 t.Fatalf("bad: %v", err) 82 } 83 84 err = state.DeleteNode(1001, node.ID) 85 if err != nil { 86 t.Fatalf("err: %v", err) 87 } 88 89 if !watchFired(ws) { 90 t.Fatalf("bad") 91 } 92 93 ws = memdb.NewWatchSet() 94 out, err := state.NodeByID(ws, node.ID) 95 if err != nil { 96 t.Fatalf("err: %v", err) 97 } 98 99 if out != nil { 100 t.Fatalf("bad: %#v %#v", node, out) 101 } 102 103 index, err := state.Index("nodes") 104 if err != nil { 105 t.Fatalf("err: %v", err) 106 } 107 if index != 1001 { 108 t.Fatalf("bad: %d", index) 109 } 110 111 if watchFired(ws) { 112 t.Fatalf("bad") 113 } 114 } 115 116 func TestStateStore_UpdateNodeStatus_Node(t *testing.T) { 117 state := testStateStore(t) 118 node := mock.Node() 119 120 err := state.UpsertNode(800, node) 121 if err != nil { 122 t.Fatalf("err: %v", err) 123 } 124 125 // Create a watchset so we can test that update node status fires the watch 126 ws := memdb.NewWatchSet() 127 if _, err := state.NodeByID(ws, node.ID); err != nil { 128 t.Fatalf("bad: %v", err) 129 } 130 131 err = state.UpdateNodeStatus(801, node.ID, structs.NodeStatusReady) 132 if err != nil { 133 t.Fatalf("err: %v", err) 134 } 135 136 if !watchFired(ws) { 137 t.Fatalf("bad") 138 } 139 140 ws = memdb.NewWatchSet() 141 out, err := state.NodeByID(ws, node.ID) 142 if err != nil { 143 t.Fatalf("err: %v", err) 144 } 145 146 if out.Status != structs.NodeStatusReady { 147 t.Fatalf("bad: %#v", out) 148 } 149 if out.ModifyIndex != 801 { 150 t.Fatalf("bad: %#v", out) 151 } 152 153 index, err := state.Index("nodes") 154 if err != nil { 155 t.Fatalf("err: %v", err) 156 } 157 if index != 801 { 158 t.Fatalf("bad: %d", index) 159 } 160 161 if watchFired(ws) { 162 t.Fatalf("bad") 163 } 164 } 165 166 func TestStateStore_UpdateNodeDrain_Node(t *testing.T) { 167 state := testStateStore(t) 168 node := mock.Node() 169 170 err := state.UpsertNode(1000, node) 171 if err != nil { 172 t.Fatalf("err: %v", err) 173 } 174 175 // Create a watchset so we can test that update node drain fires the watch 176 ws := memdb.NewWatchSet() 177 if _, err := state.NodeByID(ws, node.ID); err != nil { 178 t.Fatalf("bad: %v", err) 179 } 180 181 err = state.UpdateNodeDrain(1001, node.ID, true) 182 if err != nil { 183 t.Fatalf("err: %v", err) 184 } 185 186 if !watchFired(ws) { 187 t.Fatalf("bad") 188 } 189 190 ws = memdb.NewWatchSet() 191 out, err := state.NodeByID(ws, node.ID) 192 if err != nil { 193 t.Fatalf("err: %v", err) 194 } 195 196 if !out.Drain { 197 t.Fatalf("bad: %#v", out) 198 } 199 if out.ModifyIndex != 1001 { 200 t.Fatalf("bad: %#v", out) 201 } 202 203 index, err := state.Index("nodes") 204 if err != nil { 205 t.Fatalf("err: %v", err) 206 } 207 if index != 1001 { 208 t.Fatalf("bad: %d", index) 209 } 210 211 if watchFired(ws) { 212 t.Fatalf("bad") 213 } 214 } 215 216 func TestStateStore_Nodes(t *testing.T) { 217 state := testStateStore(t) 218 var nodes []*structs.Node 219 220 for i := 0; i < 10; i++ { 221 node := mock.Node() 222 nodes = append(nodes, node) 223 224 err := state.UpsertNode(1000+uint64(i), node) 225 if err != nil { 226 t.Fatalf("err: %v", err) 227 } 228 } 229 230 // Create a watchset so we can test that getters don't cause it to fire 231 ws := memdb.NewWatchSet() 232 iter, err := state.Nodes(ws) 233 if err != nil { 234 t.Fatalf("bad: %v", err) 235 } 236 237 var out []*structs.Node 238 for { 239 raw := iter.Next() 240 if raw == nil { 241 break 242 } 243 out = append(out, raw.(*structs.Node)) 244 } 245 246 sort.Sort(NodeIDSort(nodes)) 247 sort.Sort(NodeIDSort(out)) 248 249 if !reflect.DeepEqual(nodes, out) { 250 t.Fatalf("bad: %#v %#v", nodes, out) 251 } 252 253 if watchFired(ws) { 254 t.Fatalf("bad") 255 } 256 } 257 258 func TestStateStore_NodesByIDPrefix(t *testing.T) { 259 state := testStateStore(t) 260 node := mock.Node() 261 262 node.ID = "11111111-662e-d0ab-d1c9-3e434af7bdb4" 263 err := state.UpsertNode(1000, node) 264 if err != nil { 265 t.Fatalf("err: %v", err) 266 } 267 268 // Create a watchset so we can test that getters don't cause it to fire 269 ws := memdb.NewWatchSet() 270 iter, err := state.NodesByIDPrefix(ws, node.ID) 271 if err != nil { 272 t.Fatalf("err: %v", err) 273 } 274 275 gatherNodes := func(iter memdb.ResultIterator) []*structs.Node { 276 var nodes []*structs.Node 277 for { 278 raw := iter.Next() 279 if raw == nil { 280 break 281 } 282 node := raw.(*structs.Node) 283 nodes = append(nodes, node) 284 } 285 return nodes 286 } 287 288 nodes := gatherNodes(iter) 289 if len(nodes) != 1 { 290 t.Fatalf("err: %v", err) 291 } 292 293 if watchFired(ws) { 294 t.Fatalf("bad") 295 } 296 297 iter, err = state.NodesByIDPrefix(ws, "11") 298 if err != nil { 299 t.Fatalf("err: %v", err) 300 } 301 302 nodes = gatherNodes(iter) 303 if len(nodes) != 1 { 304 t.Fatalf("err: %v", err) 305 } 306 307 node = mock.Node() 308 node.ID = "11222222-662e-d0ab-d1c9-3e434af7bdb4" 309 err = state.UpsertNode(1001, node) 310 if err != nil { 311 t.Fatalf("err: %v", err) 312 } 313 314 if !watchFired(ws) { 315 t.Fatalf("bad") 316 } 317 318 ws = memdb.NewWatchSet() 319 iter, err = state.NodesByIDPrefix(ws, "11") 320 if err != nil { 321 t.Fatalf("err: %v", err) 322 } 323 324 nodes = gatherNodes(iter) 325 if len(nodes) != 2 { 326 t.Fatalf("err: %v", err) 327 } 328 329 iter, err = state.NodesByIDPrefix(ws, "1111") 330 if err != nil { 331 t.Fatalf("err: %v", err) 332 } 333 334 nodes = gatherNodes(iter) 335 if len(nodes) != 1 { 336 t.Fatalf("err: %v", err) 337 } 338 339 if watchFired(ws) { 340 t.Fatalf("bad") 341 } 342 } 343 344 func TestStateStore_RestoreNode(t *testing.T) { 345 state := testStateStore(t) 346 node := mock.Node() 347 348 restore, err := state.Restore() 349 if err != nil { 350 t.Fatalf("err: %v", err) 351 } 352 353 err = restore.NodeRestore(node) 354 if err != nil { 355 t.Fatalf("err: %v", err) 356 } 357 restore.Commit() 358 359 ws := memdb.NewWatchSet() 360 out, err := state.NodeByID(ws, node.ID) 361 if err != nil { 362 t.Fatalf("err: %v", err) 363 } 364 365 if !reflect.DeepEqual(out, node) { 366 t.Fatalf("Bad: %#v %#v", out, node) 367 } 368 } 369 370 func TestStateStore_UpsertJob_Job(t *testing.T) { 371 state := testStateStore(t) 372 job := mock.Job() 373 374 // Create a watchset so we can test that upsert fires the watch 375 ws := memdb.NewWatchSet() 376 _, err := state.JobByID(ws, job.ID) 377 if err != nil { 378 t.Fatalf("bad: %v", err) 379 } 380 381 if err := state.UpsertJob(1000, job); err != nil { 382 t.Fatalf("err: %v", err) 383 } 384 if !watchFired(ws) { 385 t.Fatalf("bad") 386 } 387 388 ws = memdb.NewWatchSet() 389 out, err := state.JobByID(ws, job.ID) 390 if err != nil { 391 t.Fatalf("err: %v", err) 392 } 393 394 if !reflect.DeepEqual(job, out) { 395 t.Fatalf("bad: %#v %#v", job, out) 396 } 397 398 index, err := state.Index("jobs") 399 if err != nil { 400 t.Fatalf("err: %v", err) 401 } 402 if index != 1000 { 403 t.Fatalf("bad: %d", index) 404 } 405 406 summary, err := state.JobSummaryByID(ws, job.ID) 407 if err != nil { 408 t.Fatalf("err: %v", err) 409 } 410 if summary == nil { 411 t.Fatalf("nil summary") 412 } 413 if summary.JobID != job.ID { 414 t.Fatalf("bad summary id: %v", summary.JobID) 415 } 416 _, ok := summary.Summary["web"] 417 if !ok { 418 t.Fatalf("nil summary for task group") 419 } 420 if watchFired(ws) { 421 t.Fatalf("bad") 422 } 423 } 424 425 func TestStateStore_UpdateUpsertJob_Job(t *testing.T) { 426 state := testStateStore(t) 427 job := mock.Job() 428 429 // Create a watchset so we can test that upsert fires the watch 430 ws := memdb.NewWatchSet() 431 _, err := state.JobByID(ws, job.ID) 432 if err != nil { 433 t.Fatalf("bad: %v", err) 434 } 435 436 if err := state.UpsertJob(1000, job); err != nil { 437 t.Fatalf("err: %v", err) 438 } 439 440 job2 := mock.Job() 441 job2.ID = job.ID 442 err = state.UpsertJob(1001, job2) 443 if err != nil { 444 t.Fatalf("err: %v", err) 445 } 446 447 if !watchFired(ws) { 448 t.Fatalf("bad") 449 } 450 451 ws = memdb.NewWatchSet() 452 out, err := state.JobByID(ws, job.ID) 453 if err != nil { 454 t.Fatalf("err: %v", err) 455 } 456 457 if !reflect.DeepEqual(job2, out) { 458 t.Fatalf("bad: %#v %#v", job2, out) 459 } 460 461 if out.CreateIndex != 1000 { 462 t.Fatalf("bad: %#v", out) 463 } 464 if out.ModifyIndex != 1001 { 465 t.Fatalf("bad: %#v", out) 466 } 467 468 index, err := state.Index("jobs") 469 if err != nil { 470 t.Fatalf("err: %v", err) 471 } 472 if index != 1001 { 473 t.Fatalf("bad: %d", index) 474 } 475 476 // Test that the job summary remains the same if the job is updated but 477 // count remains same 478 summary, err := state.JobSummaryByID(ws, job.ID) 479 if err != nil { 480 t.Fatalf("err: %v", err) 481 } 482 if summary == nil { 483 t.Fatalf("nil summary") 484 } 485 if summary.JobID != job.ID { 486 t.Fatalf("bad summary id: %v", summary.JobID) 487 } 488 _, ok := summary.Summary["web"] 489 if !ok { 490 t.Fatalf("nil summary for task group") 491 } 492 493 if watchFired(ws) { 494 t.Fatalf("bad") 495 } 496 } 497 498 func TestStateStore_UpdateUpsertJob_PeriodicJob(t *testing.T) { 499 state := testStateStore(t) 500 job := mock.PeriodicJob() 501 502 // Create a watchset so we can test that upsert fires the watch 503 ws := memdb.NewWatchSet() 504 _, err := state.JobByID(ws, job.ID) 505 if err != nil { 506 t.Fatalf("bad: %v", err) 507 } 508 509 if err := state.UpsertJob(1000, job); err != nil { 510 t.Fatalf("err: %v", err) 511 } 512 513 // Create a child and an evaluation 514 job2 := job.Copy() 515 job2.Periodic = nil 516 job2.ID = fmt.Sprintf("%v/%s-1490635020", job.ID, structs.PeriodicLaunchSuffix) 517 err = state.UpsertJob(1001, job2) 518 if err != nil { 519 t.Fatalf("err: %v", err) 520 } 521 522 eval := mock.Eval() 523 eval.JobID = job2.ID 524 err = state.UpsertEvals(1002, []*structs.Evaluation{eval}) 525 if err != nil { 526 t.Fatalf("err: %v", err) 527 } 528 529 job3 := job.Copy() 530 job3.TaskGroups[0].Tasks[0].Name = "new name" 531 err = state.UpsertJob(1003, job3) 532 if err != nil { 533 t.Fatalf("err: %v", err) 534 } 535 536 if !watchFired(ws) { 537 t.Fatalf("bad") 538 } 539 540 ws = memdb.NewWatchSet() 541 out, err := state.JobByID(ws, job.ID) 542 if err != nil { 543 t.Fatalf("err: %v", err) 544 } 545 546 if s, e := out.Status, structs.JobStatusRunning; s != e { 547 t.Fatalf("got status %v; want %v", s, e) 548 } 549 550 } 551 552 // This test ensures that UpsertJob creates the EphemeralDisk is a job doesn't have 553 // one and clear out the task's disk resource asks 554 // COMPAT 0.4.1 -> 0.5 555 func TestStateStore_UpsertJob_NoEphemeralDisk(t *testing.T) { 556 state := testStateStore(t) 557 job := mock.Job() 558 559 // Set the EphemeralDisk to nil and set the tasks's DiskMB to 150 560 job.TaskGroups[0].EphemeralDisk = nil 561 job.TaskGroups[0].Tasks[0].Resources.DiskMB = 150 562 563 err := state.UpsertJob(1000, job) 564 if err != nil { 565 t.Fatalf("err: %v", err) 566 } 567 568 ws := memdb.NewWatchSet() 569 out, err := state.JobByID(ws, job.ID) 570 if err != nil { 571 t.Fatalf("err: %v", err) 572 } 573 574 // Expect the state store to create the EphemeralDisk and clear out Tasks's 575 // DiskMB 576 expected := job.Copy() 577 expected.TaskGroups[0].EphemeralDisk = &structs.EphemeralDisk{ 578 SizeMB: 150, 579 } 580 expected.TaskGroups[0].Tasks[0].Resources.DiskMB = 0 581 582 if !reflect.DeepEqual(expected, out) { 583 t.Fatalf("bad: %#v %#v", expected, out) 584 } 585 } 586 587 // Upsert a job that is the child of a parent job and ensures its summary gets 588 // updated. 589 func TestStateStore_UpsertJob_ChildJob(t *testing.T) { 590 state := testStateStore(t) 591 592 // Create a watchset so we can test that upsert fires the watch 593 parent := mock.Job() 594 ws := memdb.NewWatchSet() 595 _, err := state.JobByID(ws, parent.ID) 596 if err != nil { 597 t.Fatalf("bad: %v", err) 598 } 599 600 if err := state.UpsertJob(1000, parent); err != nil { 601 t.Fatalf("err: %v", err) 602 } 603 604 child := mock.Job() 605 child.ParentID = parent.ID 606 if err := state.UpsertJob(1001, child); err != nil { 607 t.Fatalf("err: %v", err) 608 } 609 610 summary, err := state.JobSummaryByID(ws, parent.ID) 611 if err != nil { 612 t.Fatalf("err: %v", err) 613 } 614 if summary == nil { 615 t.Fatalf("nil summary") 616 } 617 if summary.JobID != parent.ID { 618 t.Fatalf("bad summary id: %v", parent.ID) 619 } 620 if summary.Children == nil { 621 t.Fatalf("nil children summary") 622 } 623 if summary.Children.Pending != 1 || summary.Children.Running != 0 || summary.Children.Dead != 0 { 624 t.Fatalf("bad children summary: %v", summary.Children) 625 } 626 if !watchFired(ws) { 627 t.Fatalf("bad") 628 } 629 } 630 631 func TestStateStore_DeleteJob_Job(t *testing.T) { 632 state := testStateStore(t) 633 job := mock.Job() 634 635 err := state.UpsertJob(1000, job) 636 if err != nil { 637 t.Fatalf("err: %v", err) 638 } 639 640 // Create a watchset so we can test that delete fires the watch 641 ws := memdb.NewWatchSet() 642 if _, err := state.JobByID(ws, job.ID); err != nil { 643 t.Fatalf("bad: %v", err) 644 } 645 646 err = state.DeleteJob(1001, job.ID) 647 if err != nil { 648 t.Fatalf("err: %v", err) 649 } 650 651 if !watchFired(ws) { 652 t.Fatalf("bad") 653 } 654 655 ws = memdb.NewWatchSet() 656 out, err := state.JobByID(ws, job.ID) 657 if err != nil { 658 t.Fatalf("err: %v", err) 659 } 660 661 if out != nil { 662 t.Fatalf("bad: %#v %#v", job, out) 663 } 664 665 index, err := state.Index("jobs") 666 if err != nil { 667 t.Fatalf("err: %v", err) 668 } 669 if index != 1001 { 670 t.Fatalf("bad: %d", index) 671 } 672 673 summary, err := state.JobSummaryByID(ws, job.ID) 674 if err != nil { 675 t.Fatalf("err: %v", err) 676 } 677 if summary != nil { 678 t.Fatalf("expected summary to be nil, but got: %v", summary) 679 } 680 681 if watchFired(ws) { 682 t.Fatalf("bad") 683 } 684 } 685 686 func TestStateStore_DeleteJob_ChildJob(t *testing.T) { 687 state := testStateStore(t) 688 689 parent := mock.Job() 690 if err := state.UpsertJob(998, parent); err != nil { 691 t.Fatalf("err: %v", err) 692 } 693 694 child := mock.Job() 695 child.ParentID = parent.ID 696 697 if err := state.UpsertJob(999, child); err != nil { 698 t.Fatalf("err: %v", err) 699 } 700 701 // Create a watchset so we can test that delete fires the watch 702 ws := memdb.NewWatchSet() 703 if _, err := state.JobSummaryByID(ws, parent.ID); err != nil { 704 t.Fatalf("bad: %v", err) 705 } 706 707 err := state.DeleteJob(1001, child.ID) 708 if err != nil { 709 t.Fatalf("err: %v", err) 710 } 711 if !watchFired(ws) { 712 t.Fatalf("bad") 713 } 714 715 ws = memdb.NewWatchSet() 716 summary, err := state.JobSummaryByID(ws, parent.ID) 717 if err != nil { 718 t.Fatalf("err: %v", err) 719 } 720 if summary == nil { 721 t.Fatalf("nil summary") 722 } 723 if summary.JobID != parent.ID { 724 t.Fatalf("bad summary id: %v", parent.ID) 725 } 726 if summary.Children == nil { 727 t.Fatalf("nil children summary") 728 } 729 if summary.Children.Pending != 0 || summary.Children.Running != 0 || summary.Children.Dead != 1 { 730 t.Fatalf("bad children summary: %v", summary.Children) 731 } 732 if watchFired(ws) { 733 t.Fatalf("bad") 734 } 735 } 736 737 func TestStateStore_Jobs(t *testing.T) { 738 state := testStateStore(t) 739 var jobs []*structs.Job 740 741 for i := 0; i < 10; i++ { 742 job := mock.Job() 743 jobs = append(jobs, job) 744 745 err := state.UpsertJob(1000+uint64(i), job) 746 if err != nil { 747 t.Fatalf("err: %v", err) 748 } 749 } 750 751 ws := memdb.NewWatchSet() 752 iter, err := state.Jobs(ws) 753 if err != nil { 754 t.Fatalf("err: %v", err) 755 } 756 757 var out []*structs.Job 758 for { 759 raw := iter.Next() 760 if raw == nil { 761 break 762 } 763 out = append(out, raw.(*structs.Job)) 764 } 765 766 sort.Sort(JobIDSort(jobs)) 767 sort.Sort(JobIDSort(out)) 768 769 if !reflect.DeepEqual(jobs, out) { 770 t.Fatalf("bad: %#v %#v", jobs, out) 771 } 772 if watchFired(ws) { 773 t.Fatalf("bad") 774 } 775 } 776 777 func TestStateStore_JobsByIDPrefix(t *testing.T) { 778 state := testStateStore(t) 779 job := mock.Job() 780 781 job.ID = "redis" 782 err := state.UpsertJob(1000, job) 783 if err != nil { 784 t.Fatalf("err: %v", err) 785 } 786 787 ws := memdb.NewWatchSet() 788 iter, err := state.JobsByIDPrefix(ws, job.ID) 789 if err != nil { 790 t.Fatalf("err: %v", err) 791 } 792 793 gatherJobs := func(iter memdb.ResultIterator) []*structs.Job { 794 var jobs []*structs.Job 795 for { 796 raw := iter.Next() 797 if raw == nil { 798 break 799 } 800 jobs = append(jobs, raw.(*structs.Job)) 801 } 802 return jobs 803 } 804 805 jobs := gatherJobs(iter) 806 if len(jobs) != 1 { 807 t.Fatalf("err: %v", err) 808 } 809 810 iter, err = state.JobsByIDPrefix(ws, "re") 811 if err != nil { 812 t.Fatalf("err: %v", err) 813 } 814 815 jobs = gatherJobs(iter) 816 if len(jobs) != 1 { 817 t.Fatalf("err: %v", err) 818 } 819 if watchFired(ws) { 820 t.Fatalf("bad") 821 } 822 823 job = mock.Job() 824 job.ID = "riak" 825 err = state.UpsertJob(1001, job) 826 if err != nil { 827 t.Fatalf("err: %v", err) 828 } 829 830 if !watchFired(ws) { 831 t.Fatalf("bad") 832 } 833 834 ws = memdb.NewWatchSet() 835 iter, err = state.JobsByIDPrefix(ws, "r") 836 if err != nil { 837 t.Fatalf("err: %v", err) 838 } 839 840 jobs = gatherJobs(iter) 841 if len(jobs) != 2 { 842 t.Fatalf("err: %v", err) 843 } 844 845 iter, err = state.JobsByIDPrefix(ws, "ri") 846 if err != nil { 847 t.Fatalf("err: %v", err) 848 } 849 850 jobs = gatherJobs(iter) 851 if len(jobs) != 1 { 852 t.Fatalf("err: %v", err) 853 } 854 if watchFired(ws) { 855 t.Fatalf("bad") 856 } 857 } 858 859 func TestStateStore_JobsByPeriodic(t *testing.T) { 860 state := testStateStore(t) 861 var periodic, nonPeriodic []*structs.Job 862 863 for i := 0; i < 10; i++ { 864 job := mock.Job() 865 nonPeriodic = append(nonPeriodic, job) 866 867 err := state.UpsertJob(1000+uint64(i), job) 868 if err != nil { 869 t.Fatalf("err: %v", err) 870 } 871 } 872 873 for i := 0; i < 10; i++ { 874 job := mock.PeriodicJob() 875 periodic = append(periodic, job) 876 877 err := state.UpsertJob(2000+uint64(i), job) 878 if err != nil { 879 t.Fatalf("err: %v", err) 880 } 881 } 882 883 ws := memdb.NewWatchSet() 884 iter, err := state.JobsByPeriodic(ws, true) 885 if err != nil { 886 t.Fatalf("err: %v", err) 887 } 888 889 var outPeriodic []*structs.Job 890 for { 891 raw := iter.Next() 892 if raw == nil { 893 break 894 } 895 outPeriodic = append(outPeriodic, raw.(*structs.Job)) 896 } 897 898 iter, err = state.JobsByPeriodic(ws, false) 899 if err != nil { 900 t.Fatalf("err: %v", err) 901 } 902 903 var outNonPeriodic []*structs.Job 904 for { 905 raw := iter.Next() 906 if raw == nil { 907 break 908 } 909 outNonPeriodic = append(outNonPeriodic, raw.(*structs.Job)) 910 } 911 912 sort.Sort(JobIDSort(periodic)) 913 sort.Sort(JobIDSort(nonPeriodic)) 914 sort.Sort(JobIDSort(outPeriodic)) 915 sort.Sort(JobIDSort(outNonPeriodic)) 916 917 if !reflect.DeepEqual(periodic, outPeriodic) { 918 t.Fatalf("bad: %#v %#v", periodic, outPeriodic) 919 } 920 921 if !reflect.DeepEqual(nonPeriodic, outNonPeriodic) { 922 t.Fatalf("bad: %#v %#v", nonPeriodic, outNonPeriodic) 923 } 924 if watchFired(ws) { 925 t.Fatalf("bad") 926 } 927 } 928 929 func TestStateStore_JobsByScheduler(t *testing.T) { 930 state := testStateStore(t) 931 var serviceJobs []*structs.Job 932 var sysJobs []*structs.Job 933 934 for i := 0; i < 10; i++ { 935 job := mock.Job() 936 serviceJobs = append(serviceJobs, job) 937 938 err := state.UpsertJob(1000+uint64(i), job) 939 if err != nil { 940 t.Fatalf("err: %v", err) 941 } 942 } 943 944 for i := 0; i < 10; i++ { 945 job := mock.SystemJob() 946 sysJobs = append(sysJobs, job) 947 948 err := state.UpsertJob(2000+uint64(i), job) 949 if err != nil { 950 t.Fatalf("err: %v", err) 951 } 952 } 953 954 ws := memdb.NewWatchSet() 955 iter, err := state.JobsByScheduler(ws, "service") 956 if err != nil { 957 t.Fatalf("err: %v", err) 958 } 959 960 var outService []*structs.Job 961 for { 962 raw := iter.Next() 963 if raw == nil { 964 break 965 } 966 outService = append(outService, raw.(*structs.Job)) 967 } 968 969 iter, err = state.JobsByScheduler(ws, "system") 970 if err != nil { 971 t.Fatalf("err: %v", err) 972 } 973 974 var outSystem []*structs.Job 975 for { 976 raw := iter.Next() 977 if raw == nil { 978 break 979 } 980 outSystem = append(outSystem, raw.(*structs.Job)) 981 } 982 983 sort.Sort(JobIDSort(serviceJobs)) 984 sort.Sort(JobIDSort(sysJobs)) 985 sort.Sort(JobIDSort(outService)) 986 sort.Sort(JobIDSort(outSystem)) 987 988 if !reflect.DeepEqual(serviceJobs, outService) { 989 t.Fatalf("bad: %#v %#v", serviceJobs, outService) 990 } 991 992 if !reflect.DeepEqual(sysJobs, outSystem) { 993 t.Fatalf("bad: %#v %#v", sysJobs, outSystem) 994 } 995 if watchFired(ws) { 996 t.Fatalf("bad") 997 } 998 } 999 1000 func TestStateStore_JobsByGC(t *testing.T) { 1001 state := testStateStore(t) 1002 var gc, nonGc []*structs.Job 1003 1004 for i := 0; i < 20; i++ { 1005 var job *structs.Job 1006 if i%2 == 0 { 1007 job = mock.Job() 1008 } else { 1009 job = mock.PeriodicJob() 1010 } 1011 nonGc = append(nonGc, job) 1012 1013 if err := state.UpsertJob(1000+uint64(i), job); err != nil { 1014 t.Fatalf("err: %v", err) 1015 } 1016 } 1017 1018 for i := 0; i < 10; i++ { 1019 job := mock.Job() 1020 job.Type = structs.JobTypeBatch 1021 gc = append(gc, job) 1022 1023 if err := state.UpsertJob(2000+uint64(i), job); err != nil { 1024 t.Fatalf("err: %v", err) 1025 } 1026 } 1027 1028 ws := memdb.NewWatchSet() 1029 iter, err := state.JobsByGC(ws, true) 1030 if err != nil { 1031 t.Fatalf("err: %v", err) 1032 } 1033 1034 var outGc []*structs.Job 1035 for i := iter.Next(); i != nil; i = iter.Next() { 1036 outGc = append(outGc, i.(*structs.Job)) 1037 } 1038 1039 iter, err = state.JobsByGC(ws, false) 1040 if err != nil { 1041 t.Fatalf("err: %v", err) 1042 } 1043 1044 var outNonGc []*structs.Job 1045 for i := iter.Next(); i != nil; i = iter.Next() { 1046 outNonGc = append(outNonGc, i.(*structs.Job)) 1047 } 1048 1049 sort.Sort(JobIDSort(gc)) 1050 sort.Sort(JobIDSort(nonGc)) 1051 sort.Sort(JobIDSort(outGc)) 1052 sort.Sort(JobIDSort(outNonGc)) 1053 1054 if !reflect.DeepEqual(gc, outGc) { 1055 t.Fatalf("bad: %#v %#v", gc, outGc) 1056 } 1057 1058 if !reflect.DeepEqual(nonGc, outNonGc) { 1059 t.Fatalf("bad: %#v %#v", nonGc, outNonGc) 1060 } 1061 if watchFired(ws) { 1062 t.Fatalf("bad") 1063 } 1064 } 1065 1066 func TestStateStore_RestoreJob(t *testing.T) { 1067 state := testStateStore(t) 1068 job := mock.Job() 1069 1070 restore, err := state.Restore() 1071 if err != nil { 1072 t.Fatalf("err: %v", err) 1073 } 1074 1075 err = restore.JobRestore(job) 1076 if err != nil { 1077 t.Fatalf("err: %v", err) 1078 } 1079 restore.Commit() 1080 1081 ws := memdb.NewWatchSet() 1082 out, err := state.JobByID(ws, job.ID) 1083 if err != nil { 1084 t.Fatalf("err: %v", err) 1085 } 1086 1087 if !reflect.DeepEqual(out, job) { 1088 t.Fatalf("Bad: %#v %#v", out, job) 1089 } 1090 } 1091 1092 // This test ensures that the state restore creates the EphemeralDisk for a job if 1093 // it doesn't have one 1094 // COMPAT 0.4.1 -> 0.5 1095 func TestStateStore_Jobs_NoEphemeralDisk(t *testing.T) { 1096 state := testStateStore(t) 1097 job := mock.Job() 1098 1099 // Set EphemeralDisk to nil and set the DiskMB to 150 1100 job.TaskGroups[0].EphemeralDisk = nil 1101 job.TaskGroups[0].Tasks[0].Resources.DiskMB = 150 1102 1103 restore, err := state.Restore() 1104 if err != nil { 1105 t.Fatalf("err: %v", err) 1106 } 1107 1108 err = restore.JobRestore(job) 1109 if err != nil { 1110 t.Fatalf("err: %v", err) 1111 } 1112 restore.Commit() 1113 1114 ws := memdb.NewWatchSet() 1115 out, err := state.JobByID(ws, job.ID) 1116 if err != nil { 1117 t.Fatalf("err: %v", err) 1118 } 1119 1120 // Expect job to have local disk and clear out the task's disk resource ask 1121 expected := job.Copy() 1122 expected.TaskGroups[0].EphemeralDisk = &structs.EphemeralDisk{ 1123 SizeMB: 150, 1124 } 1125 expected.TaskGroups[0].Tasks[0].Resources.DiskMB = 0 1126 if !reflect.DeepEqual(out, expected) { 1127 t.Fatalf("Bad: %#v %#v", out, job) 1128 } 1129 } 1130 1131 func TestStateStore_UpsertPeriodicLaunch(t *testing.T) { 1132 state := testStateStore(t) 1133 job := mock.Job() 1134 launch := &structs.PeriodicLaunch{ID: job.ID, Launch: time.Now()} 1135 1136 // Create a watchset so we can test that upsert fires the watch 1137 ws := memdb.NewWatchSet() 1138 if _, err := state.PeriodicLaunchByID(ws, launch.ID); err != nil { 1139 t.Fatalf("bad: %v", err) 1140 } 1141 1142 err := state.UpsertPeriodicLaunch(1000, launch) 1143 if err != nil { 1144 t.Fatalf("err: %v", err) 1145 } 1146 1147 if !watchFired(ws) { 1148 t.Fatalf("bad") 1149 } 1150 1151 ws = memdb.NewWatchSet() 1152 out, err := state.PeriodicLaunchByID(ws, job.ID) 1153 if err != nil { 1154 t.Fatalf("err: %v", err) 1155 } 1156 if out.CreateIndex != 1000 { 1157 t.Fatalf("bad: %#v", out) 1158 } 1159 if out.ModifyIndex != 1000 { 1160 t.Fatalf("bad: %#v", out) 1161 } 1162 1163 if !reflect.DeepEqual(launch, out) { 1164 t.Fatalf("bad: %#v %#v", job, out) 1165 } 1166 1167 index, err := state.Index("periodic_launch") 1168 if err != nil { 1169 t.Fatalf("err: %v", err) 1170 } 1171 if index != 1000 { 1172 t.Fatalf("bad: %d", index) 1173 } 1174 1175 if watchFired(ws) { 1176 t.Fatalf("bad") 1177 } 1178 } 1179 1180 func TestStateStore_UpdateUpsertPeriodicLaunch(t *testing.T) { 1181 state := testStateStore(t) 1182 job := mock.Job() 1183 launch := &structs.PeriodicLaunch{ID: job.ID, Launch: time.Now()} 1184 1185 err := state.UpsertPeriodicLaunch(1000, launch) 1186 if err != nil { 1187 t.Fatalf("err: %v", err) 1188 } 1189 1190 // Create a watchset so we can test that upsert fires the watch 1191 ws := memdb.NewWatchSet() 1192 if _, err := state.PeriodicLaunchByID(ws, launch.ID); err != nil { 1193 t.Fatalf("bad: %v", err) 1194 } 1195 1196 launch2 := &structs.PeriodicLaunch{ 1197 ID: job.ID, 1198 Launch: launch.Launch.Add(1 * time.Second), 1199 } 1200 err = state.UpsertPeriodicLaunch(1001, launch2) 1201 if err != nil { 1202 t.Fatalf("err: %v", err) 1203 } 1204 1205 if !watchFired(ws) { 1206 t.Fatalf("bad") 1207 } 1208 1209 ws = memdb.NewWatchSet() 1210 out, err := state.PeriodicLaunchByID(ws, job.ID) 1211 if err != nil { 1212 t.Fatalf("err: %v", err) 1213 } 1214 if out.CreateIndex != 1000 { 1215 t.Fatalf("bad: %#v", out) 1216 } 1217 if out.ModifyIndex != 1001 { 1218 t.Fatalf("bad: %#v", out) 1219 } 1220 1221 if !reflect.DeepEqual(launch2, out) { 1222 t.Fatalf("bad: %#v %#v", launch2, out) 1223 } 1224 1225 index, err := state.Index("periodic_launch") 1226 if err != nil { 1227 t.Fatalf("err: %v", err) 1228 } 1229 if index != 1001 { 1230 t.Fatalf("bad: %d", index) 1231 } 1232 1233 if watchFired(ws) { 1234 t.Fatalf("bad") 1235 } 1236 } 1237 1238 func TestStateStore_DeletePeriodicLaunch(t *testing.T) { 1239 state := testStateStore(t) 1240 job := mock.Job() 1241 launch := &structs.PeriodicLaunch{ID: job.ID, Launch: time.Now()} 1242 1243 err := state.UpsertPeriodicLaunch(1000, launch) 1244 if err != nil { 1245 t.Fatalf("err: %v", err) 1246 } 1247 1248 // Create a watchset so we can test that delete fires the watch 1249 ws := memdb.NewWatchSet() 1250 if _, err := state.PeriodicLaunchByID(ws, launch.ID); err != nil { 1251 t.Fatalf("bad: %v", err) 1252 } 1253 1254 err = state.DeletePeriodicLaunch(1001, launch.ID) 1255 if err != nil { 1256 t.Fatalf("err: %v", err) 1257 } 1258 1259 if !watchFired(ws) { 1260 t.Fatalf("bad") 1261 } 1262 1263 ws = memdb.NewWatchSet() 1264 out, err := state.PeriodicLaunchByID(ws, job.ID) 1265 if err != nil { 1266 t.Fatalf("err: %v", err) 1267 } 1268 1269 if out != nil { 1270 t.Fatalf("bad: %#v %#v", job, out) 1271 } 1272 1273 index, err := state.Index("periodic_launch") 1274 if err != nil { 1275 t.Fatalf("err: %v", err) 1276 } 1277 if index != 1001 { 1278 t.Fatalf("bad: %d", index) 1279 } 1280 1281 if watchFired(ws) { 1282 t.Fatalf("bad") 1283 } 1284 } 1285 1286 func TestStateStore_PeriodicLaunches(t *testing.T) { 1287 state := testStateStore(t) 1288 var launches []*structs.PeriodicLaunch 1289 1290 for i := 0; i < 10; i++ { 1291 job := mock.Job() 1292 launch := &structs.PeriodicLaunch{ID: job.ID, Launch: time.Now()} 1293 launches = append(launches, launch) 1294 1295 err := state.UpsertPeriodicLaunch(1000+uint64(i), launch) 1296 if err != nil { 1297 t.Fatalf("err: %v", err) 1298 } 1299 } 1300 1301 ws := memdb.NewWatchSet() 1302 iter, err := state.PeriodicLaunches(ws) 1303 if err != nil { 1304 t.Fatalf("err: %v", err) 1305 } 1306 1307 out := make(map[string]*structs.PeriodicLaunch, 10) 1308 for { 1309 raw := iter.Next() 1310 if raw == nil { 1311 break 1312 } 1313 launch := raw.(*structs.PeriodicLaunch) 1314 if _, ok := out[launch.ID]; ok { 1315 t.Fatalf("duplicate: %v", launch.ID) 1316 } 1317 1318 out[launch.ID] = launch 1319 } 1320 1321 for _, launch := range launches { 1322 l, ok := out[launch.ID] 1323 if !ok { 1324 t.Fatalf("bad %v", launch.ID) 1325 } 1326 1327 if !reflect.DeepEqual(launch, l) { 1328 t.Fatalf("bad: %#v %#v", launch, l) 1329 } 1330 1331 delete(out, launch.ID) 1332 } 1333 1334 if len(out) != 0 { 1335 t.Fatalf("leftover: %#v", out) 1336 } 1337 1338 if watchFired(ws) { 1339 t.Fatalf("bad") 1340 } 1341 } 1342 1343 func TestStateStore_RestorePeriodicLaunch(t *testing.T) { 1344 state := testStateStore(t) 1345 job := mock.Job() 1346 launch := &structs.PeriodicLaunch{ID: job.ID, Launch: time.Now()} 1347 1348 restore, err := state.Restore() 1349 if err != nil { 1350 t.Fatalf("err: %v", err) 1351 } 1352 1353 err = restore.PeriodicLaunchRestore(launch) 1354 if err != nil { 1355 t.Fatalf("err: %v", err) 1356 } 1357 restore.Commit() 1358 1359 ws := memdb.NewWatchSet() 1360 out, err := state.PeriodicLaunchByID(ws, job.ID) 1361 if err != nil { 1362 t.Fatalf("err: %v", err) 1363 } 1364 1365 if !reflect.DeepEqual(out, launch) { 1366 t.Fatalf("Bad: %#v %#v", out, job) 1367 } 1368 1369 if watchFired(ws) { 1370 t.Fatalf("bad") 1371 } 1372 } 1373 1374 func TestStateStore_RestoreJobSummary(t *testing.T) { 1375 state := testStateStore(t) 1376 job := mock.Job() 1377 jobSummary := &structs.JobSummary{ 1378 JobID: job.ID, 1379 Summary: map[string]structs.TaskGroupSummary{ 1380 "web": structs.TaskGroupSummary{ 1381 Starting: 10, 1382 }, 1383 }, 1384 } 1385 restore, err := state.Restore() 1386 if err != nil { 1387 t.Fatalf("err: %v", err) 1388 } 1389 1390 err = restore.JobSummaryRestore(jobSummary) 1391 if err != nil { 1392 t.Fatalf("err: %v", err) 1393 } 1394 restore.Commit() 1395 1396 ws := memdb.NewWatchSet() 1397 out, err := state.JobSummaryByID(ws, job.ID) 1398 if err != nil { 1399 t.Fatalf("err: %v", err) 1400 } 1401 1402 if !reflect.DeepEqual(out, jobSummary) { 1403 t.Fatalf("Bad: %#v %#v", out, jobSummary) 1404 } 1405 } 1406 1407 func TestStateStore_Indexes(t *testing.T) { 1408 state := testStateStore(t) 1409 node := mock.Node() 1410 1411 err := state.UpsertNode(1000, node) 1412 if err != nil { 1413 t.Fatalf("err: %v", err) 1414 } 1415 1416 iter, err := state.Indexes() 1417 if err != nil { 1418 t.Fatalf("err: %v", err) 1419 } 1420 1421 var out []*IndexEntry 1422 for { 1423 raw := iter.Next() 1424 if raw == nil { 1425 break 1426 } 1427 out = append(out, raw.(*IndexEntry)) 1428 } 1429 1430 expect := []*IndexEntry{ 1431 &IndexEntry{"nodes", 1000}, 1432 } 1433 1434 if !reflect.DeepEqual(expect, out) { 1435 t.Fatalf("bad: %#v %#v", expect, out) 1436 } 1437 } 1438 1439 func TestStateStore_LatestIndex(t *testing.T) { 1440 state := testStateStore(t) 1441 1442 if err := state.UpsertNode(1000, mock.Node()); err != nil { 1443 t.Fatalf("err: %v", err) 1444 } 1445 1446 exp := uint64(2000) 1447 if err := state.UpsertJob(exp, mock.Job()); err != nil { 1448 t.Fatalf("err: %v", err) 1449 } 1450 1451 latest, err := state.LatestIndex() 1452 if err != nil { 1453 t.Fatalf("err: %v", err) 1454 } 1455 1456 if latest != exp { 1457 t.Fatalf("LatestIndex() returned %d; want %d", latest, exp) 1458 } 1459 } 1460 1461 func TestStateStore_RestoreIndex(t *testing.T) { 1462 state := testStateStore(t) 1463 1464 restore, err := state.Restore() 1465 if err != nil { 1466 t.Fatalf("err: %v", err) 1467 } 1468 1469 index := &IndexEntry{"jobs", 1000} 1470 err = restore.IndexRestore(index) 1471 if err != nil { 1472 t.Fatalf("err: %v", err) 1473 } 1474 1475 restore.Commit() 1476 1477 out, err := state.Index("jobs") 1478 if err != nil { 1479 t.Fatalf("err: %v", err) 1480 } 1481 1482 if out != 1000 { 1483 t.Fatalf("Bad: %#v %#v", out, 1000) 1484 } 1485 } 1486 1487 func TestStateStore_UpsertEvals_Eval(t *testing.T) { 1488 state := testStateStore(t) 1489 eval := mock.Eval() 1490 1491 // Create a watchset so we can test that upsert fires the watch 1492 ws := memdb.NewWatchSet() 1493 if _, err := state.EvalByID(ws, eval.ID); err != nil { 1494 t.Fatalf("bad: %v", err) 1495 } 1496 1497 err := state.UpsertEvals(1000, []*structs.Evaluation{eval}) 1498 if err != nil { 1499 t.Fatalf("err: %v", err) 1500 } 1501 1502 if !watchFired(ws) { 1503 t.Fatalf("bad") 1504 } 1505 1506 ws = memdb.NewWatchSet() 1507 out, err := state.EvalByID(ws, eval.ID) 1508 if err != nil { 1509 t.Fatalf("err: %v", err) 1510 } 1511 1512 if !reflect.DeepEqual(eval, out) { 1513 t.Fatalf("bad: %#v %#v", eval, out) 1514 } 1515 1516 index, err := state.Index("evals") 1517 if err != nil { 1518 t.Fatalf("err: %v", err) 1519 } 1520 if index != 1000 { 1521 t.Fatalf("bad: %d", index) 1522 } 1523 1524 if watchFired(ws) { 1525 t.Fatalf("bad") 1526 } 1527 } 1528 1529 func TestStateStore_UpsertEvals_CancelBlocked(t *testing.T) { 1530 state := testStateStore(t) 1531 1532 // Create two blocked evals for the same job 1533 j := "test-job" 1534 b1, b2 := mock.Eval(), mock.Eval() 1535 b1.JobID = j 1536 b1.Status = structs.EvalStatusBlocked 1537 b2.JobID = j 1538 b2.Status = structs.EvalStatusBlocked 1539 1540 err := state.UpsertEvals(999, []*structs.Evaluation{b1, b2}) 1541 if err != nil { 1542 t.Fatalf("err: %v", err) 1543 } 1544 1545 // Create one complete and successful eval for the job 1546 eval := mock.Eval() 1547 eval.JobID = j 1548 eval.Status = structs.EvalStatusComplete 1549 1550 // Create a watchset so we can test that the upsert of the complete eval 1551 // fires the watch 1552 ws := memdb.NewWatchSet() 1553 if _, err := state.EvalByID(ws, b1.ID); err != nil { 1554 t.Fatalf("bad: %v", err) 1555 } 1556 if _, err := state.EvalByID(ws, b2.ID); err != nil { 1557 t.Fatalf("bad: %v", err) 1558 } 1559 1560 if err := state.UpsertEvals(1000, []*structs.Evaluation{eval}); err != nil { 1561 t.Fatalf("err: %v", err) 1562 } 1563 1564 if !watchFired(ws) { 1565 t.Fatalf("bad") 1566 } 1567 1568 ws = memdb.NewWatchSet() 1569 out, err := state.EvalByID(ws, eval.ID) 1570 if err != nil { 1571 t.Fatalf("err: %v", err) 1572 } 1573 1574 if !reflect.DeepEqual(eval, out) { 1575 t.Fatalf("bad: %#v %#v", eval, out) 1576 } 1577 1578 index, err := state.Index("evals") 1579 if err != nil { 1580 t.Fatalf("err: %v", err) 1581 } 1582 if index != 1000 { 1583 t.Fatalf("bad: %d", index) 1584 } 1585 1586 // Get b1/b2 and check they are cancelled 1587 out1, err := state.EvalByID(ws, b1.ID) 1588 if err != nil { 1589 t.Fatalf("err: %v", err) 1590 } 1591 1592 out2, err := state.EvalByID(ws, b2.ID) 1593 if err != nil { 1594 t.Fatalf("err: %v", err) 1595 } 1596 1597 if out1.Status != structs.EvalStatusCancelled || out2.Status != structs.EvalStatusCancelled { 1598 t.Fatalf("bad: %#v %#v", out1, out2) 1599 } 1600 1601 if watchFired(ws) { 1602 t.Fatalf("bad") 1603 } 1604 } 1605 1606 func TestStateStore_Update_UpsertEvals_Eval(t *testing.T) { 1607 state := testStateStore(t) 1608 eval := mock.Eval() 1609 1610 err := state.UpsertEvals(1000, []*structs.Evaluation{eval}) 1611 if err != nil { 1612 t.Fatalf("err: %v", err) 1613 } 1614 1615 // Create a watchset so we can test that delete fires the watch 1616 ws := memdb.NewWatchSet() 1617 ws2 := memdb.NewWatchSet() 1618 if _, err := state.EvalByID(ws, eval.ID); err != nil { 1619 t.Fatalf("bad: %v", err) 1620 } 1621 1622 if _, err := state.EvalsByJob(ws2, eval.JobID); err != nil { 1623 t.Fatalf("bad: %v", err) 1624 } 1625 1626 eval2 := mock.Eval() 1627 eval2.ID = eval.ID 1628 eval2.JobID = eval.JobID 1629 err = state.UpsertEvals(1001, []*structs.Evaluation{eval2}) 1630 if err != nil { 1631 t.Fatalf("err: %v", err) 1632 } 1633 1634 if !watchFired(ws) { 1635 t.Fatalf("bad") 1636 } 1637 if !watchFired(ws2) { 1638 t.Fatalf("bad") 1639 } 1640 1641 ws = memdb.NewWatchSet() 1642 out, err := state.EvalByID(ws, eval.ID) 1643 if err != nil { 1644 t.Fatalf("err: %v", err) 1645 } 1646 1647 if !reflect.DeepEqual(eval2, out) { 1648 t.Fatalf("bad: %#v %#v", eval2, out) 1649 } 1650 1651 if out.CreateIndex != 1000 { 1652 t.Fatalf("bad: %#v", out) 1653 } 1654 if out.ModifyIndex != 1001 { 1655 t.Fatalf("bad: %#v", out) 1656 } 1657 1658 index, err := state.Index("evals") 1659 if err != nil { 1660 t.Fatalf("err: %v", err) 1661 } 1662 if index != 1001 { 1663 t.Fatalf("bad: %d", index) 1664 } 1665 1666 if watchFired(ws) { 1667 t.Fatalf("bad") 1668 } 1669 } 1670 1671 func TestStateStore_UpsertEvals_Eval_ChildJob(t *testing.T) { 1672 state := testStateStore(t) 1673 1674 parent := mock.Job() 1675 if err := state.UpsertJob(998, parent); err != nil { 1676 t.Fatalf("err: %v", err) 1677 } 1678 1679 child := mock.Job() 1680 child.ParentID = parent.ID 1681 1682 if err := state.UpsertJob(999, child); err != nil { 1683 t.Fatalf("err: %v", err) 1684 } 1685 1686 eval := mock.Eval() 1687 eval.Status = structs.EvalStatusComplete 1688 eval.JobID = child.ID 1689 1690 // Create watchsets so we can test that upsert fires the watch 1691 ws := memdb.NewWatchSet() 1692 ws2 := memdb.NewWatchSet() 1693 ws3 := memdb.NewWatchSet() 1694 if _, err := state.JobSummaryByID(ws, parent.ID); err != nil { 1695 t.Fatalf("bad: %v", err) 1696 } 1697 if _, err := state.EvalByID(ws2, eval.ID); err != nil { 1698 t.Fatalf("bad: %v", err) 1699 } 1700 if _, err := state.EvalsByJob(ws3, eval.JobID); err != nil { 1701 t.Fatalf("bad: %v", err) 1702 } 1703 1704 err := state.UpsertEvals(1000, []*structs.Evaluation{eval}) 1705 if err != nil { 1706 t.Fatalf("err: %v", err) 1707 } 1708 1709 if !watchFired(ws) { 1710 t.Fatalf("bad") 1711 } 1712 if !watchFired(ws2) { 1713 t.Fatalf("bad") 1714 } 1715 if !watchFired(ws3) { 1716 t.Fatalf("bad") 1717 } 1718 1719 ws = memdb.NewWatchSet() 1720 out, err := state.EvalByID(ws, eval.ID) 1721 if err != nil { 1722 t.Fatalf("err: %v", err) 1723 } 1724 1725 if !reflect.DeepEqual(eval, out) { 1726 t.Fatalf("bad: %#v %#v", eval, out) 1727 } 1728 1729 index, err := state.Index("evals") 1730 if err != nil { 1731 t.Fatalf("err: %v", err) 1732 } 1733 if index != 1000 { 1734 t.Fatalf("bad: %d", index) 1735 } 1736 1737 summary, err := state.JobSummaryByID(ws, parent.ID) 1738 if err != nil { 1739 t.Fatalf("err: %v", err) 1740 } 1741 if summary == nil { 1742 t.Fatalf("nil summary") 1743 } 1744 if summary.JobID != parent.ID { 1745 t.Fatalf("bad summary id: %v", parent.ID) 1746 } 1747 if summary.Children == nil { 1748 t.Fatalf("nil children summary") 1749 } 1750 if summary.Children.Pending != 0 || summary.Children.Running != 0 || summary.Children.Dead != 1 { 1751 t.Fatalf("bad children summary: %v", summary.Children) 1752 } 1753 1754 if watchFired(ws) { 1755 t.Fatalf("bad") 1756 } 1757 } 1758 1759 func TestStateStore_DeleteEval_Eval(t *testing.T) { 1760 state := testStateStore(t) 1761 eval1 := mock.Eval() 1762 eval2 := mock.Eval() 1763 alloc1 := mock.Alloc() 1764 alloc2 := mock.Alloc() 1765 1766 // Create watchsets so we can test that upsert fires the watch 1767 watches := make([]memdb.WatchSet, 12) 1768 for i := 0; i < 12; i++ { 1769 watches[i] = memdb.NewWatchSet() 1770 } 1771 if _, err := state.EvalByID(watches[0], eval1.ID); err != nil { 1772 t.Fatalf("bad: %v", err) 1773 } 1774 if _, err := state.EvalByID(watches[1], eval2.ID); err != nil { 1775 t.Fatalf("bad: %v", err) 1776 } 1777 if _, err := state.EvalsByJob(watches[2], eval1.JobID); err != nil { 1778 t.Fatalf("bad: %v", err) 1779 } 1780 if _, err := state.EvalsByJob(watches[3], eval2.JobID); err != nil { 1781 t.Fatalf("bad: %v", err) 1782 } 1783 if _, err := state.AllocByID(watches[4], alloc1.ID); err != nil { 1784 t.Fatalf("bad: %v", err) 1785 } 1786 if _, err := state.AllocByID(watches[5], alloc2.ID); err != nil { 1787 t.Fatalf("bad: %v", err) 1788 } 1789 if _, err := state.AllocsByEval(watches[6], alloc1.EvalID); err != nil { 1790 t.Fatalf("bad: %v", err) 1791 } 1792 if _, err := state.AllocsByEval(watches[7], alloc2.EvalID); err != nil { 1793 t.Fatalf("bad: %v", err) 1794 } 1795 if _, err := state.AllocsByJob(watches[8], alloc1.JobID, false); err != nil { 1796 t.Fatalf("bad: %v", err) 1797 } 1798 if _, err := state.AllocsByJob(watches[9], alloc2.JobID, false); err != nil { 1799 t.Fatalf("bad: %v", err) 1800 } 1801 if _, err := state.AllocsByNode(watches[10], alloc1.NodeID); err != nil { 1802 t.Fatalf("bad: %v", err) 1803 } 1804 if _, err := state.AllocsByNode(watches[11], alloc2.NodeID); err != nil { 1805 t.Fatalf("bad: %v", err) 1806 } 1807 1808 state.UpsertJobSummary(900, mock.JobSummary(eval1.JobID)) 1809 state.UpsertJobSummary(901, mock.JobSummary(eval2.JobID)) 1810 state.UpsertJobSummary(902, mock.JobSummary(alloc1.JobID)) 1811 state.UpsertJobSummary(903, mock.JobSummary(alloc2.JobID)) 1812 err := state.UpsertEvals(1000, []*structs.Evaluation{eval1, eval2}) 1813 if err != nil { 1814 t.Fatalf("err: %v", err) 1815 } 1816 1817 err = state.UpsertAllocs(1001, []*structs.Allocation{alloc1, alloc2}) 1818 if err != nil { 1819 t.Fatalf("err: %v", err) 1820 } 1821 1822 err = state.DeleteEval(1002, []string{eval1.ID, eval2.ID}, []string{alloc1.ID, alloc2.ID}) 1823 if err != nil { 1824 t.Fatalf("err: %v", err) 1825 } 1826 1827 for i, ws := range watches { 1828 if !watchFired(ws) { 1829 t.Fatalf("bad %d", i) 1830 } 1831 } 1832 1833 ws := memdb.NewWatchSet() 1834 out, err := state.EvalByID(ws, eval1.ID) 1835 if err != nil { 1836 t.Fatalf("err: %v", err) 1837 } 1838 1839 if out != nil { 1840 t.Fatalf("bad: %#v %#v", eval1, out) 1841 } 1842 1843 out, err = state.EvalByID(ws, eval2.ID) 1844 if err != nil { 1845 t.Fatalf("err: %v", err) 1846 } 1847 1848 if out != nil { 1849 t.Fatalf("bad: %#v %#v", eval1, out) 1850 } 1851 1852 outA, err := state.AllocByID(ws, alloc1.ID) 1853 if err != nil { 1854 t.Fatalf("err: %v", err) 1855 } 1856 1857 if out != nil { 1858 t.Fatalf("bad: %#v %#v", alloc1, outA) 1859 } 1860 1861 outA, err = state.AllocByID(ws, alloc2.ID) 1862 if err != nil { 1863 t.Fatalf("err: %v", err) 1864 } 1865 1866 if out != nil { 1867 t.Fatalf("bad: %#v %#v", alloc1, outA) 1868 } 1869 1870 index, err := state.Index("evals") 1871 if err != nil { 1872 t.Fatalf("err: %v", err) 1873 } 1874 if index != 1002 { 1875 t.Fatalf("bad: %d", index) 1876 } 1877 1878 index, err = state.Index("allocs") 1879 if err != nil { 1880 t.Fatalf("err: %v", err) 1881 } 1882 if index != 1002 { 1883 t.Fatalf("bad: %d", index) 1884 } 1885 1886 if watchFired(ws) { 1887 t.Fatalf("bad") 1888 } 1889 } 1890 1891 func TestStateStore_DeleteEval_ChildJob(t *testing.T) { 1892 state := testStateStore(t) 1893 1894 parent := mock.Job() 1895 if err := state.UpsertJob(998, parent); err != nil { 1896 t.Fatalf("err: %v", err) 1897 } 1898 1899 child := mock.Job() 1900 child.ParentID = parent.ID 1901 1902 if err := state.UpsertJob(999, child); err != nil { 1903 t.Fatalf("err: %v", err) 1904 } 1905 1906 eval1 := mock.Eval() 1907 eval1.JobID = child.ID 1908 alloc1 := mock.Alloc() 1909 alloc1.JobID = child.ID 1910 1911 err := state.UpsertEvals(1000, []*structs.Evaluation{eval1}) 1912 if err != nil { 1913 t.Fatalf("err: %v", err) 1914 } 1915 1916 err = state.UpsertAllocs(1001, []*structs.Allocation{alloc1}) 1917 if err != nil { 1918 t.Fatalf("err: %v", err) 1919 } 1920 1921 // Create watchsets so we can test that delete fires the watch 1922 ws := memdb.NewWatchSet() 1923 if _, err := state.JobSummaryByID(ws, parent.ID); err != nil { 1924 t.Fatalf("bad: %v", err) 1925 } 1926 1927 err = state.DeleteEval(1002, []string{eval1.ID}, []string{alloc1.ID}) 1928 if err != nil { 1929 t.Fatalf("err: %v", err) 1930 } 1931 1932 if !watchFired(ws) { 1933 t.Fatalf("bad") 1934 } 1935 1936 ws = memdb.NewWatchSet() 1937 summary, err := state.JobSummaryByID(ws, parent.ID) 1938 if err != nil { 1939 t.Fatalf("err: %v", err) 1940 } 1941 if summary == nil { 1942 t.Fatalf("nil summary") 1943 } 1944 if summary.JobID != parent.ID { 1945 t.Fatalf("bad summary id: %v", parent.ID) 1946 } 1947 if summary.Children == nil { 1948 t.Fatalf("nil children summary") 1949 } 1950 if summary.Children.Pending != 0 || summary.Children.Running != 0 || summary.Children.Dead != 1 { 1951 t.Fatalf("bad children summary: %v", summary.Children) 1952 } 1953 1954 if watchFired(ws) { 1955 t.Fatalf("bad") 1956 } 1957 } 1958 1959 func TestStateStore_EvalsByJob(t *testing.T) { 1960 state := testStateStore(t) 1961 1962 eval1 := mock.Eval() 1963 eval2 := mock.Eval() 1964 eval2.JobID = eval1.JobID 1965 eval3 := mock.Eval() 1966 evals := []*structs.Evaluation{eval1, eval2} 1967 1968 err := state.UpsertEvals(1000, evals) 1969 if err != nil { 1970 t.Fatalf("err: %v", err) 1971 } 1972 err = state.UpsertEvals(1001, []*structs.Evaluation{eval3}) 1973 if err != nil { 1974 t.Fatalf("err: %v", err) 1975 } 1976 1977 ws := memdb.NewWatchSet() 1978 out, err := state.EvalsByJob(ws, eval1.JobID) 1979 if err != nil { 1980 t.Fatalf("err: %v", err) 1981 } 1982 1983 sort.Sort(EvalIDSort(evals)) 1984 sort.Sort(EvalIDSort(out)) 1985 1986 if !reflect.DeepEqual(evals, out) { 1987 t.Fatalf("bad: %#v %#v", evals, out) 1988 } 1989 1990 if watchFired(ws) { 1991 t.Fatalf("bad") 1992 } 1993 } 1994 1995 func TestStateStore_Evals(t *testing.T) { 1996 state := testStateStore(t) 1997 var evals []*structs.Evaluation 1998 1999 for i := 0; i < 10; i++ { 2000 eval := mock.Eval() 2001 evals = append(evals, eval) 2002 2003 err := state.UpsertEvals(1000+uint64(i), []*structs.Evaluation{eval}) 2004 if err != nil { 2005 t.Fatalf("err: %v", err) 2006 } 2007 } 2008 2009 ws := memdb.NewWatchSet() 2010 iter, err := state.Evals(ws) 2011 if err != nil { 2012 t.Fatalf("err: %v", err) 2013 } 2014 2015 var out []*structs.Evaluation 2016 for { 2017 raw := iter.Next() 2018 if raw == nil { 2019 break 2020 } 2021 out = append(out, raw.(*structs.Evaluation)) 2022 } 2023 2024 sort.Sort(EvalIDSort(evals)) 2025 sort.Sort(EvalIDSort(out)) 2026 2027 if !reflect.DeepEqual(evals, out) { 2028 t.Fatalf("bad: %#v %#v", evals, out) 2029 } 2030 2031 if watchFired(ws) { 2032 t.Fatalf("bad") 2033 } 2034 } 2035 2036 func TestStateStore_EvalsByIDPrefix(t *testing.T) { 2037 state := testStateStore(t) 2038 var evals []*structs.Evaluation 2039 2040 ids := []string{ 2041 "aaaaaaaa-7bfb-395d-eb95-0685af2176b2", 2042 "aaaaaaab-7bfb-395d-eb95-0685af2176b2", 2043 "aaaaaabb-7bfb-395d-eb95-0685af2176b2", 2044 "aaaaabbb-7bfb-395d-eb95-0685af2176b2", 2045 "aaaabbbb-7bfb-395d-eb95-0685af2176b2", 2046 "aaabbbbb-7bfb-395d-eb95-0685af2176b2", 2047 "aabbbbbb-7bfb-395d-eb95-0685af2176b2", 2048 "abbbbbbb-7bfb-395d-eb95-0685af2176b2", 2049 "bbbbbbbb-7bfb-395d-eb95-0685af2176b2", 2050 } 2051 for i := 0; i < 9; i++ { 2052 eval := mock.Eval() 2053 eval.ID = ids[i] 2054 evals = append(evals, eval) 2055 } 2056 2057 err := state.UpsertEvals(1000, evals) 2058 if err != nil { 2059 t.Fatalf("err: %v", err) 2060 } 2061 2062 ws := memdb.NewWatchSet() 2063 iter, err := state.EvalsByIDPrefix(ws, "aaaa") 2064 if err != nil { 2065 t.Fatalf("err: %v", err) 2066 } 2067 2068 gatherEvals := func(iter memdb.ResultIterator) []*structs.Evaluation { 2069 var evals []*structs.Evaluation 2070 for { 2071 raw := iter.Next() 2072 if raw == nil { 2073 break 2074 } 2075 evals = append(evals, raw.(*structs.Evaluation)) 2076 } 2077 return evals 2078 } 2079 2080 out := gatherEvals(iter) 2081 if len(out) != 5 { 2082 t.Fatalf("bad: expected five evaluations, got: %#v", out) 2083 } 2084 2085 sort.Sort(EvalIDSort(evals)) 2086 2087 for index, eval := range out { 2088 if ids[index] != eval.ID { 2089 t.Fatalf("bad: got unexpected id: %s", eval.ID) 2090 } 2091 } 2092 2093 iter, err = state.EvalsByIDPrefix(ws, "b-a7bfb") 2094 if err != nil { 2095 t.Fatalf("err: %v", err) 2096 } 2097 2098 out = gatherEvals(iter) 2099 if len(out) != 0 { 2100 t.Fatalf("bad: unexpected zero evaluations, got: %#v", out) 2101 } 2102 2103 if watchFired(ws) { 2104 t.Fatalf("bad") 2105 } 2106 } 2107 2108 func TestStateStore_RestoreEval(t *testing.T) { 2109 state := testStateStore(t) 2110 eval := mock.Eval() 2111 2112 restore, err := state.Restore() 2113 if err != nil { 2114 t.Fatalf("err: %v", err) 2115 } 2116 2117 err = restore.EvalRestore(eval) 2118 if err != nil { 2119 t.Fatalf("err: %v", err) 2120 } 2121 restore.Commit() 2122 2123 ws := memdb.NewWatchSet() 2124 out, err := state.EvalByID(ws, eval.ID) 2125 if err != nil { 2126 t.Fatalf("err: %v", err) 2127 } 2128 2129 if !reflect.DeepEqual(out, eval) { 2130 t.Fatalf("Bad: %#v %#v", out, eval) 2131 } 2132 } 2133 2134 func TestStateStore_UpdateAllocsFromClient(t *testing.T) { 2135 state := testStateStore(t) 2136 parent := mock.Job() 2137 if err := state.UpsertJob(998, parent); err != nil { 2138 t.Fatalf("err: %v", err) 2139 } 2140 2141 child := mock.Job() 2142 child.ParentID = parent.ID 2143 if err := state.UpsertJob(999, child); err != nil { 2144 t.Fatalf("err: %v", err) 2145 } 2146 2147 alloc := mock.Alloc() 2148 alloc.JobID = child.ID 2149 alloc.Job = child 2150 2151 err := state.UpsertAllocs(1000, []*structs.Allocation{alloc}) 2152 if err != nil { 2153 t.Fatalf("err: %v", err) 2154 } 2155 2156 ws := memdb.NewWatchSet() 2157 summary, err := state.JobSummaryByID(ws, parent.ID) 2158 if err != nil { 2159 t.Fatalf("err: %v", err) 2160 } 2161 if summary == nil { 2162 t.Fatalf("nil summary") 2163 } 2164 if summary.JobID != parent.ID { 2165 t.Fatalf("bad summary id: %v", parent.ID) 2166 } 2167 if summary.Children == nil { 2168 t.Fatalf("nil children summary") 2169 } 2170 if summary.Children.Pending != 0 || summary.Children.Running != 1 || summary.Children.Dead != 0 { 2171 t.Fatalf("bad children summary: %v", summary.Children) 2172 } 2173 2174 // Create watchsets so we can test that update fires the watch 2175 ws = memdb.NewWatchSet() 2176 if _, err := state.JobSummaryByID(ws, parent.ID); err != nil { 2177 t.Fatalf("bad: %v", err) 2178 } 2179 2180 // Create the delta updates 2181 ts := map[string]*structs.TaskState{"web": &structs.TaskState{State: structs.TaskStateRunning}} 2182 update := &structs.Allocation{ 2183 ID: alloc.ID, 2184 ClientStatus: structs.AllocClientStatusComplete, 2185 TaskStates: ts, 2186 JobID: alloc.JobID, 2187 TaskGroup: alloc.TaskGroup, 2188 } 2189 err = state.UpdateAllocsFromClient(1001, []*structs.Allocation{update}) 2190 if err != nil { 2191 t.Fatalf("err: %v", err) 2192 } 2193 2194 if !watchFired(ws) { 2195 t.Fatalf("bad") 2196 } 2197 2198 ws = memdb.NewWatchSet() 2199 summary, err = state.JobSummaryByID(ws, parent.ID) 2200 if err != nil { 2201 t.Fatalf("err: %v", err) 2202 } 2203 if summary == nil { 2204 t.Fatalf("nil summary") 2205 } 2206 if summary.JobID != parent.ID { 2207 t.Fatalf("bad summary id: %v", parent.ID) 2208 } 2209 if summary.Children == nil { 2210 t.Fatalf("nil children summary") 2211 } 2212 if summary.Children.Pending != 0 || summary.Children.Running != 0 || summary.Children.Dead != 1 { 2213 t.Fatalf("bad children summary: %v", summary.Children) 2214 } 2215 2216 if watchFired(ws) { 2217 t.Fatalf("bad") 2218 } 2219 } 2220 2221 func TestStateStore_UpdateAllocsFromClient_ChildJob(t *testing.T) { 2222 state := testStateStore(t) 2223 alloc1 := mock.Alloc() 2224 alloc2 := mock.Alloc() 2225 2226 if err := state.UpsertJob(999, alloc1.Job); err != nil { 2227 t.Fatalf("err: %v", err) 2228 } 2229 if err := state.UpsertJob(999, alloc2.Job); err != nil { 2230 t.Fatalf("err: %v", err) 2231 } 2232 2233 err := state.UpsertAllocs(1000, []*structs.Allocation{alloc1, alloc2}) 2234 if err != nil { 2235 t.Fatalf("err: %v", err) 2236 } 2237 2238 // Create watchsets so we can test that update fires the watch 2239 watches := make([]memdb.WatchSet, 8) 2240 for i := 0; i < 8; i++ { 2241 watches[i] = memdb.NewWatchSet() 2242 } 2243 if _, err := state.AllocByID(watches[0], alloc1.ID); err != nil { 2244 t.Fatalf("bad: %v", err) 2245 } 2246 if _, err := state.AllocByID(watches[1], alloc2.ID); err != nil { 2247 t.Fatalf("bad: %v", err) 2248 } 2249 if _, err := state.AllocsByEval(watches[2], alloc1.EvalID); err != nil { 2250 t.Fatalf("bad: %v", err) 2251 } 2252 if _, err := state.AllocsByEval(watches[3], alloc2.EvalID); err != nil { 2253 t.Fatalf("bad: %v", err) 2254 } 2255 if _, err := state.AllocsByJob(watches[4], alloc1.JobID, false); err != nil { 2256 t.Fatalf("bad: %v", err) 2257 } 2258 if _, err := state.AllocsByJob(watches[5], alloc2.JobID, false); err != nil { 2259 t.Fatalf("bad: %v", err) 2260 } 2261 if _, err := state.AllocsByNode(watches[6], alloc1.NodeID); err != nil { 2262 t.Fatalf("bad: %v", err) 2263 } 2264 if _, err := state.AllocsByNode(watches[7], alloc2.NodeID); err != nil { 2265 t.Fatalf("bad: %v", err) 2266 } 2267 2268 // Create the delta updates 2269 ts := map[string]*structs.TaskState{"web": &structs.TaskState{State: structs.TaskStatePending}} 2270 update := &structs.Allocation{ 2271 ID: alloc1.ID, 2272 ClientStatus: structs.AllocClientStatusFailed, 2273 TaskStates: ts, 2274 JobID: alloc1.JobID, 2275 TaskGroup: alloc1.TaskGroup, 2276 } 2277 update2 := &structs.Allocation{ 2278 ID: alloc2.ID, 2279 ClientStatus: structs.AllocClientStatusRunning, 2280 TaskStates: ts, 2281 JobID: alloc2.JobID, 2282 TaskGroup: alloc2.TaskGroup, 2283 } 2284 2285 err = state.UpdateAllocsFromClient(1001, []*structs.Allocation{update, update2}) 2286 if err != nil { 2287 t.Fatalf("err: %v", err) 2288 } 2289 2290 for i, ws := range watches { 2291 if !watchFired(ws) { 2292 t.Fatalf("bad %d", i) 2293 } 2294 } 2295 2296 ws := memdb.NewWatchSet() 2297 out, err := state.AllocByID(ws, alloc1.ID) 2298 if err != nil { 2299 t.Fatalf("err: %v", err) 2300 } 2301 2302 alloc1.CreateIndex = 1000 2303 alloc1.ModifyIndex = 1001 2304 alloc1.TaskStates = ts 2305 alloc1.ClientStatus = structs.AllocClientStatusFailed 2306 if !reflect.DeepEqual(alloc1, out) { 2307 t.Fatalf("bad: %#v %#v", alloc1, out) 2308 } 2309 2310 out, err = state.AllocByID(ws, alloc2.ID) 2311 if err != nil { 2312 t.Fatalf("err: %v", err) 2313 } 2314 2315 alloc2.ModifyIndex = 1000 2316 alloc2.ModifyIndex = 1001 2317 alloc2.ClientStatus = structs.AllocClientStatusRunning 2318 alloc2.TaskStates = ts 2319 if !reflect.DeepEqual(alloc2, out) { 2320 t.Fatalf("bad: %#v %#v", alloc2, out) 2321 } 2322 2323 index, err := state.Index("allocs") 2324 if err != nil { 2325 t.Fatalf("err: %v", err) 2326 } 2327 if index != 1001 { 2328 t.Fatalf("bad: %d", index) 2329 } 2330 2331 // Ensure summaries have been updated 2332 summary, err := state.JobSummaryByID(ws, alloc1.JobID) 2333 if err != nil { 2334 t.Fatalf("err: %v", err) 2335 } 2336 tgSummary := summary.Summary["web"] 2337 if tgSummary.Failed != 1 { 2338 t.Fatalf("expected failed: %v, actual: %v, summary: %#v", 1, tgSummary.Failed, tgSummary) 2339 } 2340 2341 summary2, err := state.JobSummaryByID(ws, alloc2.JobID) 2342 if err != nil { 2343 t.Fatalf("err: %v", err) 2344 } 2345 tgSummary2 := summary2.Summary["web"] 2346 if tgSummary2.Running != 1 { 2347 t.Fatalf("expected running: %v, actual: %v", 1, tgSummary2.Running) 2348 } 2349 2350 if watchFired(ws) { 2351 t.Fatalf("bad") 2352 } 2353 } 2354 2355 func TestStateStore_UpdateMultipleAllocsFromClient(t *testing.T) { 2356 state := testStateStore(t) 2357 alloc := mock.Alloc() 2358 2359 if err := state.UpsertJob(999, alloc.Job); err != nil { 2360 t.Fatalf("err: %v", err) 2361 } 2362 err := state.UpsertAllocs(1000, []*structs.Allocation{alloc}) 2363 if err != nil { 2364 t.Fatalf("err: %v", err) 2365 } 2366 2367 // Create the delta updates 2368 ts := map[string]*structs.TaskState{"web": &structs.TaskState{State: structs.TaskStatePending}} 2369 update := &structs.Allocation{ 2370 ID: alloc.ID, 2371 ClientStatus: structs.AllocClientStatusRunning, 2372 TaskStates: ts, 2373 JobID: alloc.JobID, 2374 TaskGroup: alloc.TaskGroup, 2375 } 2376 update2 := &structs.Allocation{ 2377 ID: alloc.ID, 2378 ClientStatus: structs.AllocClientStatusPending, 2379 TaskStates: ts, 2380 JobID: alloc.JobID, 2381 TaskGroup: alloc.TaskGroup, 2382 } 2383 2384 err = state.UpdateAllocsFromClient(1001, []*structs.Allocation{update, update2}) 2385 if err != nil { 2386 t.Fatalf("err: %v", err) 2387 } 2388 2389 ws := memdb.NewWatchSet() 2390 out, err := state.AllocByID(ws, alloc.ID) 2391 if err != nil { 2392 t.Fatalf("err: %v", err) 2393 } 2394 2395 alloc.CreateIndex = 1000 2396 alloc.ModifyIndex = 1001 2397 alloc.TaskStates = ts 2398 alloc.ClientStatus = structs.AllocClientStatusPending 2399 if !reflect.DeepEqual(alloc, out) { 2400 t.Fatalf("bad: %#v , actual:%#v", alloc, out) 2401 } 2402 2403 summary, err := state.JobSummaryByID(ws, alloc.JobID) 2404 expectedSummary := &structs.JobSummary{ 2405 JobID: alloc.JobID, 2406 Summary: map[string]structs.TaskGroupSummary{ 2407 "web": structs.TaskGroupSummary{ 2408 Starting: 1, 2409 }, 2410 }, 2411 Children: new(structs.JobChildrenSummary), 2412 CreateIndex: 999, 2413 ModifyIndex: 1001, 2414 } 2415 if err != nil { 2416 t.Fatalf("err: %v", err) 2417 } 2418 if !reflect.DeepEqual(summary, expectedSummary) { 2419 t.Fatalf("expected: %#v, actual: %#v", expectedSummary, summary) 2420 } 2421 } 2422 2423 func TestStateStore_UpsertAlloc_Alloc(t *testing.T) { 2424 state := testStateStore(t) 2425 alloc := mock.Alloc() 2426 2427 if err := state.UpsertJob(999, alloc.Job); err != nil { 2428 t.Fatalf("err: %v", err) 2429 } 2430 2431 // Create watchsets so we can test that update fires the watch 2432 watches := make([]memdb.WatchSet, 4) 2433 for i := 0; i < 4; i++ { 2434 watches[i] = memdb.NewWatchSet() 2435 } 2436 if _, err := state.AllocByID(watches[0], alloc.ID); err != nil { 2437 t.Fatalf("bad: %v", err) 2438 } 2439 if _, err := state.AllocsByEval(watches[1], alloc.EvalID); err != nil { 2440 t.Fatalf("bad: %v", err) 2441 } 2442 if _, err := state.AllocsByJob(watches[2], alloc.JobID, false); err != nil { 2443 t.Fatalf("bad: %v", err) 2444 } 2445 if _, err := state.AllocsByNode(watches[3], alloc.NodeID); err != nil { 2446 t.Fatalf("bad: %v", err) 2447 } 2448 2449 err := state.UpsertAllocs(1000, []*structs.Allocation{alloc}) 2450 if err != nil { 2451 t.Fatalf("err: %v", err) 2452 } 2453 2454 for i, ws := range watches { 2455 if !watchFired(ws) { 2456 t.Fatalf("bad %d", i) 2457 } 2458 } 2459 2460 ws := memdb.NewWatchSet() 2461 out, err := state.AllocByID(ws, alloc.ID) 2462 if err != nil { 2463 t.Fatalf("err: %v", err) 2464 } 2465 2466 if !reflect.DeepEqual(alloc, out) { 2467 t.Fatalf("bad: %#v %#v", alloc, out) 2468 } 2469 2470 index, err := state.Index("allocs") 2471 if err != nil { 2472 t.Fatalf("err: %v", err) 2473 } 2474 if index != 1000 { 2475 t.Fatalf("bad: %d", index) 2476 } 2477 2478 summary, err := state.JobSummaryByID(ws, alloc.JobID) 2479 if err != nil { 2480 t.Fatalf("err: %v", err) 2481 } 2482 2483 tgSummary, ok := summary.Summary["web"] 2484 if !ok { 2485 t.Fatalf("no summary for task group web") 2486 } 2487 if tgSummary.Starting != 1 { 2488 t.Fatalf("expected queued: %v, actual: %v", 1, tgSummary.Starting) 2489 } 2490 2491 if watchFired(ws) { 2492 t.Fatalf("bad") 2493 } 2494 } 2495 2496 func TestStateStore_UpsertAlloc_NoEphemeralDisk(t *testing.T) { 2497 state := testStateStore(t) 2498 alloc := mock.Alloc() 2499 alloc.Job.TaskGroups[0].EphemeralDisk = nil 2500 alloc.Job.TaskGroups[0].Tasks[0].Resources.DiskMB = 120 2501 2502 if err := state.UpsertJob(999, alloc.Job); err != nil { 2503 t.Fatalf("err: %v", err) 2504 } 2505 2506 err := state.UpsertAllocs(1000, []*structs.Allocation{alloc}) 2507 if err != nil { 2508 t.Fatalf("err: %v", err) 2509 } 2510 2511 ws := memdb.NewWatchSet() 2512 out, err := state.AllocByID(ws, alloc.ID) 2513 if err != nil { 2514 t.Fatalf("err: %v", err) 2515 } 2516 2517 expected := alloc.Copy() 2518 expected.Job.TaskGroups[0].EphemeralDisk = &structs.EphemeralDisk{SizeMB: 120} 2519 if !reflect.DeepEqual(expected, out) { 2520 t.Fatalf("bad: %#v %#v", expected, out) 2521 } 2522 } 2523 2524 func TestStateStore_UpsertAlloc_ChildJob(t *testing.T) { 2525 state := testStateStore(t) 2526 2527 parent := mock.Job() 2528 if err := state.UpsertJob(998, parent); err != nil { 2529 t.Fatalf("err: %v", err) 2530 } 2531 2532 child := mock.Job() 2533 child.ParentID = parent.ID 2534 2535 if err := state.UpsertJob(999, child); err != nil { 2536 t.Fatalf("err: %v", err) 2537 } 2538 2539 alloc := mock.Alloc() 2540 alloc.JobID = child.ID 2541 alloc.Job = child 2542 2543 // Create watchsets so we can test that delete fires the watch 2544 ws := memdb.NewWatchSet() 2545 if _, err := state.JobSummaryByID(ws, parent.ID); err != nil { 2546 t.Fatalf("bad: %v", err) 2547 } 2548 2549 err := state.UpsertAllocs(1000, []*structs.Allocation{alloc}) 2550 if err != nil { 2551 t.Fatalf("err: %v", err) 2552 } 2553 2554 if !watchFired(ws) { 2555 t.Fatalf("bad") 2556 } 2557 2558 ws = memdb.NewWatchSet() 2559 summary, err := state.JobSummaryByID(ws, parent.ID) 2560 if err != nil { 2561 t.Fatalf("err: %v", err) 2562 } 2563 if summary == nil { 2564 t.Fatalf("nil summary") 2565 } 2566 if summary.JobID != parent.ID { 2567 t.Fatalf("bad summary id: %v", parent.ID) 2568 } 2569 if summary.Children == nil { 2570 t.Fatalf("nil children summary") 2571 } 2572 if summary.Children.Pending != 0 || summary.Children.Running != 1 || summary.Children.Dead != 0 { 2573 t.Fatalf("bad children summary: %v", summary.Children) 2574 } 2575 2576 if watchFired(ws) { 2577 t.Fatalf("bad") 2578 } 2579 } 2580 2581 func TestStateStore_UpdateAlloc_Alloc(t *testing.T) { 2582 state := testStateStore(t) 2583 alloc := mock.Alloc() 2584 2585 if err := state.UpsertJob(999, alloc.Job); err != nil { 2586 t.Fatalf("err: %v", err) 2587 } 2588 2589 err := state.UpsertAllocs(1000, []*structs.Allocation{alloc}) 2590 if err != nil { 2591 t.Fatalf("err: %v", err) 2592 } 2593 2594 ws := memdb.NewWatchSet() 2595 summary, err := state.JobSummaryByID(ws, alloc.JobID) 2596 if err != nil { 2597 t.Fatalf("err: %v", err) 2598 } 2599 tgSummary := summary.Summary["web"] 2600 if tgSummary.Starting != 1 { 2601 t.Fatalf("expected starting: %v, actual: %v", 1, tgSummary.Starting) 2602 } 2603 2604 alloc2 := mock.Alloc() 2605 alloc2.ID = alloc.ID 2606 alloc2.NodeID = alloc.NodeID + ".new" 2607 state.UpsertJobSummary(1001, mock.JobSummary(alloc2.JobID)) 2608 2609 // Create watchsets so we can test that update fires the watch 2610 watches := make([]memdb.WatchSet, 4) 2611 for i := 0; i < 4; i++ { 2612 watches[i] = memdb.NewWatchSet() 2613 } 2614 if _, err := state.AllocByID(watches[0], alloc2.ID); err != nil { 2615 t.Fatalf("bad: %v", err) 2616 } 2617 if _, err := state.AllocsByEval(watches[1], alloc2.EvalID); err != nil { 2618 t.Fatalf("bad: %v", err) 2619 } 2620 if _, err := state.AllocsByJob(watches[2], alloc2.JobID, false); err != nil { 2621 t.Fatalf("bad: %v", err) 2622 } 2623 if _, err := state.AllocsByNode(watches[3], alloc2.NodeID); err != nil { 2624 t.Fatalf("bad: %v", err) 2625 } 2626 2627 err = state.UpsertAllocs(1002, []*structs.Allocation{alloc2}) 2628 if err != nil { 2629 t.Fatalf("err: %v", err) 2630 } 2631 2632 for i, ws := range watches { 2633 if !watchFired(ws) { 2634 t.Fatalf("bad %d", i) 2635 } 2636 } 2637 2638 ws = memdb.NewWatchSet() 2639 out, err := state.AllocByID(ws, alloc.ID) 2640 if err != nil { 2641 t.Fatalf("err: %v", err) 2642 } 2643 2644 if !reflect.DeepEqual(alloc2, out) { 2645 t.Fatalf("bad: %#v %#v", alloc2, out) 2646 } 2647 2648 if out.CreateIndex != 1000 { 2649 t.Fatalf("bad: %#v", out) 2650 } 2651 if out.ModifyIndex != 1002 { 2652 t.Fatalf("bad: %#v", out) 2653 } 2654 2655 index, err := state.Index("allocs") 2656 if err != nil { 2657 t.Fatalf("err: %v", err) 2658 } 2659 if index != 1002 { 2660 t.Fatalf("bad: %d", index) 2661 } 2662 2663 // Ensure that summary hasb't changed 2664 summary, err = state.JobSummaryByID(ws, alloc.JobID) 2665 if err != nil { 2666 t.Fatalf("err: %v", err) 2667 } 2668 tgSummary = summary.Summary["web"] 2669 if tgSummary.Starting != 1 { 2670 t.Fatalf("expected starting: %v, actual: %v", 1, tgSummary.Starting) 2671 } 2672 2673 if watchFired(ws) { 2674 t.Fatalf("bad") 2675 } 2676 } 2677 2678 // This test ensures that the state store will mark the clients status as lost 2679 // when set rather than preferring the existing status. 2680 func TestStateStore_UpdateAlloc_Lost(t *testing.T) { 2681 state := testStateStore(t) 2682 alloc := mock.Alloc() 2683 alloc.ClientStatus = "foo" 2684 2685 if err := state.UpsertJob(999, alloc.Job); err != nil { 2686 t.Fatalf("err: %v", err) 2687 } 2688 2689 err := state.UpsertAllocs(1000, []*structs.Allocation{alloc}) 2690 if err != nil { 2691 t.Fatalf("err: %v", err) 2692 } 2693 2694 alloc2 := new(structs.Allocation) 2695 *alloc2 = *alloc 2696 alloc2.ClientStatus = structs.AllocClientStatusLost 2697 if err := state.UpsertAllocs(1001, []*structs.Allocation{alloc2}); err != nil { 2698 t.Fatalf("err: %v", err) 2699 } 2700 2701 ws := memdb.NewWatchSet() 2702 out, err := state.AllocByID(ws, alloc2.ID) 2703 if err != nil { 2704 t.Fatalf("err: %v", err) 2705 } 2706 2707 if out.ClientStatus != structs.AllocClientStatusLost { 2708 t.Fatalf("bad: %#v", out) 2709 } 2710 } 2711 2712 // This test ensures an allocation can be updated when there is no job 2713 // associated with it. This will happen when a job is stopped by an user which 2714 // has non-terminal allocations on clients 2715 func TestStateStore_UpdateAlloc_NoJob(t *testing.T) { 2716 state := testStateStore(t) 2717 alloc := mock.Alloc() 2718 2719 // Upsert a job 2720 state.UpsertJobSummary(998, mock.JobSummary(alloc.JobID)) 2721 if err := state.UpsertJob(999, alloc.Job); err != nil { 2722 t.Fatalf("err: %v", err) 2723 } 2724 2725 err := state.UpsertAllocs(1000, []*structs.Allocation{alloc}) 2726 if err != nil { 2727 t.Fatalf("err: %v", err) 2728 } 2729 2730 if err := state.DeleteJob(1001, alloc.JobID); err != nil { 2731 t.Fatalf("err: %v", err) 2732 } 2733 2734 // Update the desired state of the allocation to stop 2735 allocCopy := alloc.Copy() 2736 allocCopy.DesiredStatus = structs.AllocDesiredStatusStop 2737 if err := state.UpsertAllocs(1002, []*structs.Allocation{allocCopy}); err != nil { 2738 t.Fatalf("err: %v", err) 2739 } 2740 2741 // Update the client state of the allocation to complete 2742 allocCopy1 := allocCopy.Copy() 2743 allocCopy1.ClientStatus = structs.AllocClientStatusComplete 2744 if err := state.UpdateAllocsFromClient(1003, []*structs.Allocation{allocCopy1}); err != nil { 2745 t.Fatalf("err: %v", err) 2746 } 2747 2748 ws := memdb.NewWatchSet() 2749 out, _ := state.AllocByID(ws, alloc.ID) 2750 // Update the modify index of the alloc before comparing 2751 allocCopy1.ModifyIndex = 1003 2752 if !reflect.DeepEqual(out, allocCopy1) { 2753 t.Fatalf("expected: %#v \n actual: %#v", allocCopy1, out) 2754 } 2755 } 2756 2757 func TestStateStore_JobSummary(t *testing.T) { 2758 state := testStateStore(t) 2759 2760 // Add a job 2761 job := mock.Job() 2762 state.UpsertJob(900, job) 2763 2764 // Get the job back 2765 ws := memdb.NewWatchSet() 2766 outJob, _ := state.JobByID(ws, job.ID) 2767 if outJob.CreateIndex != 900 { 2768 t.Fatalf("bad create index: %v", outJob.CreateIndex) 2769 } 2770 summary, _ := state.JobSummaryByID(ws, job.ID) 2771 if summary.CreateIndex != 900 { 2772 t.Fatalf("bad create index: %v", summary.CreateIndex) 2773 } 2774 2775 // Upsert an allocation 2776 alloc := mock.Alloc() 2777 alloc.JobID = job.ID 2778 alloc.Job = job 2779 state.UpsertAllocs(910, []*structs.Allocation{alloc}) 2780 2781 // Update the alloc from client 2782 alloc1 := alloc.Copy() 2783 alloc1.ClientStatus = structs.AllocClientStatusPending 2784 alloc1.DesiredStatus = "" 2785 state.UpdateAllocsFromClient(920, []*structs.Allocation{alloc}) 2786 2787 alloc3 := alloc.Copy() 2788 alloc3.ClientStatus = structs.AllocClientStatusRunning 2789 alloc3.DesiredStatus = "" 2790 state.UpdateAllocsFromClient(930, []*structs.Allocation{alloc3}) 2791 2792 // Upsert the alloc 2793 alloc4 := alloc.Copy() 2794 alloc4.ClientStatus = structs.AllocClientStatusPending 2795 alloc4.DesiredStatus = structs.AllocDesiredStatusRun 2796 state.UpsertAllocs(950, []*structs.Allocation{alloc4}) 2797 2798 // Again upsert the alloc 2799 alloc5 := alloc.Copy() 2800 alloc5.ClientStatus = structs.AllocClientStatusPending 2801 alloc5.DesiredStatus = structs.AllocDesiredStatusRun 2802 state.UpsertAllocs(970, []*structs.Allocation{alloc5}) 2803 2804 if !watchFired(ws) { 2805 t.Fatalf("bad") 2806 } 2807 2808 expectedSummary := structs.JobSummary{ 2809 JobID: job.ID, 2810 Summary: map[string]structs.TaskGroupSummary{ 2811 "web": structs.TaskGroupSummary{ 2812 Running: 1, 2813 }, 2814 }, 2815 Children: new(structs.JobChildrenSummary), 2816 CreateIndex: 900, 2817 ModifyIndex: 930, 2818 } 2819 2820 summary, _ = state.JobSummaryByID(ws, job.ID) 2821 if !reflect.DeepEqual(&expectedSummary, summary) { 2822 t.Fatalf("expected: %#v, actual: %v", expectedSummary, summary) 2823 } 2824 2825 // De-register the job. 2826 state.DeleteJob(980, job.ID) 2827 2828 // Shouldn't have any effect on the summary 2829 alloc6 := alloc.Copy() 2830 alloc6.ClientStatus = structs.AllocClientStatusRunning 2831 alloc6.DesiredStatus = "" 2832 state.UpdateAllocsFromClient(990, []*structs.Allocation{alloc6}) 2833 2834 // We shouldn't have any summary at this point 2835 summary, _ = state.JobSummaryByID(ws, job.ID) 2836 if summary != nil { 2837 t.Fatalf("expected nil, actual: %#v", summary) 2838 } 2839 2840 // Re-register the same job 2841 job1 := mock.Job() 2842 job1.ID = job.ID 2843 state.UpsertJob(1000, job1) 2844 outJob2, _ := state.JobByID(ws, job1.ID) 2845 if outJob2.CreateIndex != 1000 { 2846 t.Fatalf("bad create index: %v", outJob2.CreateIndex) 2847 } 2848 summary, _ = state.JobSummaryByID(ws, job1.ID) 2849 if summary.CreateIndex != 1000 { 2850 t.Fatalf("bad create index: %v", summary.CreateIndex) 2851 } 2852 2853 // Upsert an allocation 2854 alloc7 := alloc.Copy() 2855 alloc7.JobID = outJob.ID 2856 alloc7.Job = outJob 2857 alloc7.ClientStatus = structs.AllocClientStatusComplete 2858 alloc7.DesiredStatus = structs.AllocDesiredStatusRun 2859 state.UpdateAllocsFromClient(1020, []*structs.Allocation{alloc7}) 2860 2861 expectedSummary = structs.JobSummary{ 2862 JobID: job.ID, 2863 Summary: map[string]structs.TaskGroupSummary{ 2864 "web": structs.TaskGroupSummary{}, 2865 }, 2866 Children: new(structs.JobChildrenSummary), 2867 CreateIndex: 1000, 2868 ModifyIndex: 1000, 2869 } 2870 2871 summary, _ = state.JobSummaryByID(ws, job1.ID) 2872 if !reflect.DeepEqual(&expectedSummary, summary) { 2873 t.Fatalf("expected: %#v, actual: %#v", expectedSummary, summary) 2874 } 2875 } 2876 2877 func TestStateStore_ReconcileJobSummary(t *testing.T) { 2878 state := testStateStore(t) 2879 2880 // Create an alloc 2881 alloc := mock.Alloc() 2882 2883 // Add another task group to the job 2884 tg2 := alloc.Job.TaskGroups[0].Copy() 2885 tg2.Name = "db" 2886 alloc.Job.TaskGroups = append(alloc.Job.TaskGroups, tg2) 2887 state.UpsertJob(100, alloc.Job) 2888 2889 // Create one more alloc for the db task group 2890 alloc2 := mock.Alloc() 2891 alloc2.TaskGroup = "db" 2892 alloc2.JobID = alloc.JobID 2893 alloc2.Job = alloc.Job 2894 2895 // Upserts the alloc 2896 state.UpsertAllocs(110, []*structs.Allocation{alloc, alloc2}) 2897 2898 // Change the state of the first alloc to running 2899 alloc3 := alloc.Copy() 2900 alloc3.ClientStatus = structs.AllocClientStatusRunning 2901 state.UpdateAllocsFromClient(120, []*structs.Allocation{alloc3}) 2902 2903 //Add some more allocs to the second tg 2904 alloc4 := mock.Alloc() 2905 alloc4.JobID = alloc.JobID 2906 alloc4.Job = alloc.Job 2907 alloc4.TaskGroup = "db" 2908 alloc5 := alloc4.Copy() 2909 alloc5.ClientStatus = structs.AllocClientStatusRunning 2910 2911 alloc6 := mock.Alloc() 2912 alloc6.JobID = alloc.JobID 2913 alloc6.Job = alloc.Job 2914 alloc6.TaskGroup = "db" 2915 alloc7 := alloc6.Copy() 2916 alloc7.ClientStatus = structs.AllocClientStatusComplete 2917 2918 alloc8 := mock.Alloc() 2919 alloc8.JobID = alloc.JobID 2920 alloc8.Job = alloc.Job 2921 alloc8.TaskGroup = "db" 2922 alloc9 := alloc8.Copy() 2923 alloc9.ClientStatus = structs.AllocClientStatusFailed 2924 2925 alloc10 := mock.Alloc() 2926 alloc10.JobID = alloc.JobID 2927 alloc10.Job = alloc.Job 2928 alloc10.TaskGroup = "db" 2929 alloc11 := alloc10.Copy() 2930 alloc11.ClientStatus = structs.AllocClientStatusLost 2931 2932 state.UpsertAllocs(130, []*structs.Allocation{alloc4, alloc6, alloc8, alloc10}) 2933 2934 state.UpdateAllocsFromClient(150, []*structs.Allocation{alloc5, alloc7, alloc9, alloc11}) 2935 2936 // DeleteJobSummary is a helper method and doesn't modify the indexes table 2937 state.DeleteJobSummary(130, alloc.Job.ID) 2938 2939 state.ReconcileJobSummaries(120) 2940 2941 ws := memdb.NewWatchSet() 2942 summary, _ := state.JobSummaryByID(ws, alloc.Job.ID) 2943 expectedSummary := structs.JobSummary{ 2944 JobID: alloc.Job.ID, 2945 Summary: map[string]structs.TaskGroupSummary{ 2946 "web": structs.TaskGroupSummary{ 2947 Running: 1, 2948 }, 2949 "db": structs.TaskGroupSummary{ 2950 Starting: 1, 2951 Running: 1, 2952 Failed: 1, 2953 Complete: 1, 2954 Lost: 1, 2955 }, 2956 }, 2957 CreateIndex: 100, 2958 ModifyIndex: 120, 2959 } 2960 if !reflect.DeepEqual(&expectedSummary, summary) { 2961 t.Fatalf("expected: %v, actual: %v", expectedSummary, summary) 2962 } 2963 } 2964 2965 func TestStateStore_UpdateAlloc_JobNotPresent(t *testing.T) { 2966 state := testStateStore(t) 2967 2968 alloc := mock.Alloc() 2969 state.UpsertJob(100, alloc.Job) 2970 state.UpsertAllocs(200, []*structs.Allocation{alloc}) 2971 2972 // Delete the job 2973 state.DeleteJob(300, alloc.Job.ID) 2974 2975 // Update the alloc 2976 alloc1 := alloc.Copy() 2977 alloc1.ClientStatus = structs.AllocClientStatusRunning 2978 2979 // Updating allocation should not throw any error 2980 if err := state.UpdateAllocsFromClient(400, []*structs.Allocation{alloc1}); err != nil { 2981 t.Fatalf("expect err: %v", err) 2982 } 2983 2984 // Re-Register the job 2985 state.UpsertJob(500, alloc.Job) 2986 2987 // Update the alloc again 2988 alloc2 := alloc.Copy() 2989 alloc2.ClientStatus = structs.AllocClientStatusComplete 2990 if err := state.UpdateAllocsFromClient(400, []*structs.Allocation{alloc1}); err != nil { 2991 t.Fatalf("expect err: %v", err) 2992 } 2993 2994 // Job Summary of the newly registered job shouldn't account for the 2995 // allocation update for the older job 2996 expectedSummary := structs.JobSummary{ 2997 JobID: alloc1.JobID, 2998 Summary: map[string]structs.TaskGroupSummary{ 2999 "web": structs.TaskGroupSummary{}, 3000 }, 3001 Children: new(structs.JobChildrenSummary), 3002 CreateIndex: 500, 3003 ModifyIndex: 500, 3004 } 3005 3006 ws := memdb.NewWatchSet() 3007 summary, _ := state.JobSummaryByID(ws, alloc.Job.ID) 3008 if !reflect.DeepEqual(&expectedSummary, summary) { 3009 t.Fatalf("expected: %v, actual: %v", expectedSummary, summary) 3010 } 3011 } 3012 3013 func TestStateStore_EvictAlloc_Alloc(t *testing.T) { 3014 state := testStateStore(t) 3015 alloc := mock.Alloc() 3016 3017 state.UpsertJobSummary(999, mock.JobSummary(alloc.JobID)) 3018 err := state.UpsertAllocs(1000, []*structs.Allocation{alloc}) 3019 if err != nil { 3020 t.Fatalf("err: %v", err) 3021 } 3022 3023 alloc2 := new(structs.Allocation) 3024 *alloc2 = *alloc 3025 alloc2.DesiredStatus = structs.AllocDesiredStatusEvict 3026 err = state.UpsertAllocs(1001, []*structs.Allocation{alloc2}) 3027 if err != nil { 3028 t.Fatalf("err: %v", err) 3029 } 3030 3031 ws := memdb.NewWatchSet() 3032 out, err := state.AllocByID(ws, alloc.ID) 3033 if err != nil { 3034 t.Fatalf("err: %v", err) 3035 } 3036 3037 if out.DesiredStatus != structs.AllocDesiredStatusEvict { 3038 t.Fatalf("bad: %#v %#v", alloc, out) 3039 } 3040 3041 index, err := state.Index("allocs") 3042 if err != nil { 3043 t.Fatalf("err: %v", err) 3044 } 3045 if index != 1001 { 3046 t.Fatalf("bad: %d", index) 3047 } 3048 } 3049 3050 func TestStateStore_AllocsByNode(t *testing.T) { 3051 state := testStateStore(t) 3052 var allocs []*structs.Allocation 3053 3054 for i := 0; i < 10; i++ { 3055 alloc := mock.Alloc() 3056 alloc.NodeID = "foo" 3057 allocs = append(allocs, alloc) 3058 } 3059 3060 for idx, alloc := range allocs { 3061 state.UpsertJobSummary(uint64(900+idx), mock.JobSummary(alloc.JobID)) 3062 } 3063 3064 err := state.UpsertAllocs(1000, allocs) 3065 if err != nil { 3066 t.Fatalf("err: %v", err) 3067 } 3068 3069 ws := memdb.NewWatchSet() 3070 out, err := state.AllocsByNode(ws, "foo") 3071 if err != nil { 3072 t.Fatalf("err: %v", err) 3073 } 3074 3075 sort.Sort(AllocIDSort(allocs)) 3076 sort.Sort(AllocIDSort(out)) 3077 3078 if !reflect.DeepEqual(allocs, out) { 3079 t.Fatalf("bad: %#v %#v", allocs, out) 3080 } 3081 3082 if watchFired(ws) { 3083 t.Fatalf("bad") 3084 } 3085 } 3086 3087 func TestStateStore_AllocsByNodeTerminal(t *testing.T) { 3088 state := testStateStore(t) 3089 var allocs, term, nonterm []*structs.Allocation 3090 3091 for i := 0; i < 10; i++ { 3092 alloc := mock.Alloc() 3093 alloc.NodeID = "foo" 3094 if i%2 == 0 { 3095 alloc.DesiredStatus = structs.AllocDesiredStatusStop 3096 term = append(term, alloc) 3097 } else { 3098 nonterm = append(nonterm, alloc) 3099 } 3100 allocs = append(allocs, alloc) 3101 } 3102 3103 for idx, alloc := range allocs { 3104 state.UpsertJobSummary(uint64(900+idx), mock.JobSummary(alloc.JobID)) 3105 } 3106 3107 err := state.UpsertAllocs(1000, allocs) 3108 if err != nil { 3109 t.Fatalf("err: %v", err) 3110 } 3111 3112 // Verify the terminal allocs 3113 ws := memdb.NewWatchSet() 3114 out, err := state.AllocsByNodeTerminal(ws, "foo", true) 3115 if err != nil { 3116 t.Fatalf("err: %v", err) 3117 } 3118 3119 sort.Sort(AllocIDSort(term)) 3120 sort.Sort(AllocIDSort(out)) 3121 3122 if !reflect.DeepEqual(term, out) { 3123 t.Fatalf("bad: %#v %#v", term, out) 3124 } 3125 3126 // Verify the non-terminal allocs 3127 out, err = state.AllocsByNodeTerminal(ws, "foo", false) 3128 if err != nil { 3129 t.Fatalf("err: %v", err) 3130 } 3131 3132 sort.Sort(AllocIDSort(nonterm)) 3133 sort.Sort(AllocIDSort(out)) 3134 3135 if !reflect.DeepEqual(nonterm, out) { 3136 t.Fatalf("bad: %#v %#v", nonterm, out) 3137 } 3138 3139 if watchFired(ws) { 3140 t.Fatalf("bad") 3141 } 3142 } 3143 3144 func TestStateStore_AllocsByJob(t *testing.T) { 3145 state := testStateStore(t) 3146 var allocs []*structs.Allocation 3147 3148 for i := 0; i < 10; i++ { 3149 alloc := mock.Alloc() 3150 alloc.JobID = "foo" 3151 allocs = append(allocs, alloc) 3152 } 3153 3154 for i, alloc := range allocs { 3155 state.UpsertJobSummary(uint64(900+i), mock.JobSummary(alloc.JobID)) 3156 } 3157 3158 err := state.UpsertAllocs(1000, allocs) 3159 if err != nil { 3160 t.Fatalf("err: %v", err) 3161 } 3162 3163 ws := memdb.NewWatchSet() 3164 out, err := state.AllocsByJob(ws, "foo", false) 3165 if err != nil { 3166 t.Fatalf("err: %v", err) 3167 } 3168 3169 sort.Sort(AllocIDSort(allocs)) 3170 sort.Sort(AllocIDSort(out)) 3171 3172 if !reflect.DeepEqual(allocs, out) { 3173 t.Fatalf("bad: %#v %#v", allocs, out) 3174 } 3175 3176 if watchFired(ws) { 3177 t.Fatalf("bad") 3178 } 3179 } 3180 3181 func TestStateStore_AllocsForRegisteredJob(t *testing.T) { 3182 state := testStateStore(t) 3183 var allocs []*structs.Allocation 3184 var allocs1 []*structs.Allocation 3185 3186 job := mock.Job() 3187 job.ID = "foo" 3188 state.UpsertJob(100, job) 3189 for i := 0; i < 3; i++ { 3190 alloc := mock.Alloc() 3191 alloc.Job = job 3192 alloc.JobID = job.ID 3193 allocs = append(allocs, alloc) 3194 } 3195 if err := state.UpsertAllocs(200, allocs); err != nil { 3196 t.Fatalf("err: %v", err) 3197 } 3198 3199 if err := state.DeleteJob(250, job.ID); err != nil { 3200 t.Fatalf("err: %v", err) 3201 } 3202 3203 job1 := mock.Job() 3204 job1.ID = "foo" 3205 job1.CreateIndex = 50 3206 state.UpsertJob(300, job1) 3207 for i := 0; i < 4; i++ { 3208 alloc := mock.Alloc() 3209 alloc.Job = job1 3210 alloc.JobID = job1.ID 3211 allocs1 = append(allocs1, alloc) 3212 } 3213 3214 if err := state.UpsertAllocs(1000, allocs1); err != nil { 3215 t.Fatalf("err: %v", err) 3216 } 3217 3218 ws := memdb.NewWatchSet() 3219 out, err := state.AllocsByJob(ws, job1.ID, true) 3220 if err != nil { 3221 t.Fatalf("err: %v", err) 3222 } 3223 3224 expected := len(allocs) + len(allocs1) 3225 if len(out) != expected { 3226 t.Fatalf("expected: %v, actual: %v", expected, len(out)) 3227 } 3228 3229 out1, err := state.AllocsByJob(ws, job1.ID, false) 3230 expected = len(allocs1) 3231 if len(out1) != expected { 3232 t.Fatalf("expected: %v, actual: %v", expected, len(out1)) 3233 } 3234 3235 if watchFired(ws) { 3236 t.Fatalf("bad") 3237 } 3238 } 3239 3240 func TestStateStore_AllocsByIDPrefix(t *testing.T) { 3241 state := testStateStore(t) 3242 var allocs []*structs.Allocation 3243 3244 ids := []string{ 3245 "aaaaaaaa-7bfb-395d-eb95-0685af2176b2", 3246 "aaaaaaab-7bfb-395d-eb95-0685af2176b2", 3247 "aaaaaabb-7bfb-395d-eb95-0685af2176b2", 3248 "aaaaabbb-7bfb-395d-eb95-0685af2176b2", 3249 "aaaabbbb-7bfb-395d-eb95-0685af2176b2", 3250 "aaabbbbb-7bfb-395d-eb95-0685af2176b2", 3251 "aabbbbbb-7bfb-395d-eb95-0685af2176b2", 3252 "abbbbbbb-7bfb-395d-eb95-0685af2176b2", 3253 "bbbbbbbb-7bfb-395d-eb95-0685af2176b2", 3254 } 3255 for i := 0; i < 9; i++ { 3256 alloc := mock.Alloc() 3257 alloc.ID = ids[i] 3258 allocs = append(allocs, alloc) 3259 } 3260 3261 for i, alloc := range allocs { 3262 state.UpsertJobSummary(uint64(900+i), mock.JobSummary(alloc.JobID)) 3263 } 3264 3265 err := state.UpsertAllocs(1000, allocs) 3266 if err != nil { 3267 t.Fatalf("err: %v", err) 3268 } 3269 3270 ws := memdb.NewWatchSet() 3271 iter, err := state.AllocsByIDPrefix(ws, "aaaa") 3272 if err != nil { 3273 t.Fatalf("err: %v", err) 3274 } 3275 3276 gatherAllocs := func(iter memdb.ResultIterator) []*structs.Allocation { 3277 var allocs []*structs.Allocation 3278 for { 3279 raw := iter.Next() 3280 if raw == nil { 3281 break 3282 } 3283 allocs = append(allocs, raw.(*structs.Allocation)) 3284 } 3285 return allocs 3286 } 3287 3288 out := gatherAllocs(iter) 3289 if len(out) != 5 { 3290 t.Fatalf("bad: expected five allocations, got: %#v", out) 3291 } 3292 3293 sort.Sort(AllocIDSort(allocs)) 3294 3295 for index, alloc := range out { 3296 if ids[index] != alloc.ID { 3297 t.Fatalf("bad: got unexpected id: %s", alloc.ID) 3298 } 3299 } 3300 3301 iter, err = state.AllocsByIDPrefix(ws, "b-a7bfb") 3302 if err != nil { 3303 t.Fatalf("err: %v", err) 3304 } 3305 3306 out = gatherAllocs(iter) 3307 if len(out) != 0 { 3308 t.Fatalf("bad: unexpected zero allocations, got: %#v", out) 3309 } 3310 3311 if watchFired(ws) { 3312 t.Fatalf("bad") 3313 } 3314 } 3315 3316 func TestStateStore_Allocs(t *testing.T) { 3317 state := testStateStore(t) 3318 var allocs []*structs.Allocation 3319 3320 for i := 0; i < 10; i++ { 3321 alloc := mock.Alloc() 3322 allocs = append(allocs, alloc) 3323 } 3324 for i, alloc := range allocs { 3325 state.UpsertJobSummary(uint64(900+i), mock.JobSummary(alloc.JobID)) 3326 } 3327 3328 err := state.UpsertAllocs(1000, allocs) 3329 if err != nil { 3330 t.Fatalf("err: %v", err) 3331 } 3332 3333 ws := memdb.NewWatchSet() 3334 iter, err := state.Allocs(ws) 3335 if err != nil { 3336 t.Fatalf("err: %v", err) 3337 } 3338 3339 var out []*structs.Allocation 3340 for { 3341 raw := iter.Next() 3342 if raw == nil { 3343 break 3344 } 3345 out = append(out, raw.(*structs.Allocation)) 3346 } 3347 3348 sort.Sort(AllocIDSort(allocs)) 3349 sort.Sort(AllocIDSort(out)) 3350 3351 if !reflect.DeepEqual(allocs, out) { 3352 t.Fatalf("bad: %#v %#v", allocs, out) 3353 } 3354 3355 if watchFired(ws) { 3356 t.Fatalf("bad") 3357 } 3358 } 3359 3360 func TestStateStore_RestoreAlloc(t *testing.T) { 3361 state := testStateStore(t) 3362 alloc := mock.Alloc() 3363 3364 restore, err := state.Restore() 3365 if err != nil { 3366 t.Fatalf("err: %v", err) 3367 } 3368 3369 err = restore.AllocRestore(alloc) 3370 if err != nil { 3371 t.Fatalf("err: %v", err) 3372 } 3373 3374 restore.Commit() 3375 3376 ws := memdb.NewWatchSet() 3377 out, err := state.AllocByID(ws, alloc.ID) 3378 if err != nil { 3379 t.Fatalf("err: %v", err) 3380 } 3381 3382 if !reflect.DeepEqual(out, alloc) { 3383 t.Fatalf("Bad: %#v %#v", out, alloc) 3384 } 3385 3386 if watchFired(ws) { 3387 t.Fatalf("bad") 3388 } 3389 } 3390 3391 func TestStateStore_RestoreAlloc_NoEphemeralDisk(t *testing.T) { 3392 state := testStateStore(t) 3393 alloc := mock.Alloc() 3394 alloc.Job.TaskGroups[0].EphemeralDisk = nil 3395 alloc.Job.TaskGroups[0].Tasks[0].Resources.DiskMB = 120 3396 3397 restore, err := state.Restore() 3398 if err != nil { 3399 t.Fatalf("err: %v", err) 3400 } 3401 3402 err = restore.AllocRestore(alloc) 3403 if err != nil { 3404 t.Fatalf("err: %v", err) 3405 } 3406 3407 restore.Commit() 3408 3409 ws := memdb.NewWatchSet() 3410 out, err := state.AllocByID(ws, alloc.ID) 3411 if err != nil { 3412 t.Fatalf("err: %v", err) 3413 } 3414 3415 expected := alloc.Copy() 3416 expected.Job.TaskGroups[0].EphemeralDisk = &structs.EphemeralDisk{SizeMB: 120} 3417 expected.Job.TaskGroups[0].Tasks[0].Resources.DiskMB = 0 3418 3419 if !reflect.DeepEqual(out, expected) { 3420 t.Fatalf("Bad: %#v %#v", out, expected) 3421 } 3422 3423 if watchFired(ws) { 3424 t.Fatalf("bad") 3425 } 3426 } 3427 3428 func TestStateStore_SetJobStatus_ForceStatus(t *testing.T) { 3429 state := testStateStore(t) 3430 txn := state.db.Txn(true) 3431 3432 // Create and insert a mock job. 3433 job := mock.Job() 3434 job.Status = "" 3435 job.ModifyIndex = 0 3436 if err := txn.Insert("jobs", job); err != nil { 3437 t.Fatalf("job insert failed: %v", err) 3438 } 3439 3440 exp := "foobar" 3441 index := uint64(1000) 3442 if err := state.setJobStatus(index, txn, job, false, exp); err != nil { 3443 t.Fatalf("setJobStatus() failed: %v", err) 3444 } 3445 3446 i, err := txn.First("jobs", "id", job.ID) 3447 if err != nil { 3448 t.Fatalf("job lookup failed: %v", err) 3449 } 3450 updated := i.(*structs.Job) 3451 3452 if updated.Status != exp { 3453 t.Fatalf("setJobStatus() set %v; expected %v", updated.Status, exp) 3454 } 3455 3456 if updated.ModifyIndex != index { 3457 t.Fatalf("setJobStatus() set %d; expected %d", updated.ModifyIndex, index) 3458 } 3459 } 3460 3461 func TestStateStore_SetJobStatus_NoOp(t *testing.T) { 3462 state := testStateStore(t) 3463 txn := state.db.Txn(true) 3464 3465 // Create and insert a mock job that should be pending. 3466 job := mock.Job() 3467 job.Status = structs.JobStatusPending 3468 job.ModifyIndex = 10 3469 if err := txn.Insert("jobs", job); err != nil { 3470 t.Fatalf("job insert failed: %v", err) 3471 } 3472 3473 index := uint64(1000) 3474 if err := state.setJobStatus(index, txn, job, false, ""); err != nil { 3475 t.Fatalf("setJobStatus() failed: %v", err) 3476 } 3477 3478 i, err := txn.First("jobs", "id", job.ID) 3479 if err != nil { 3480 t.Fatalf("job lookup failed: %v", err) 3481 } 3482 updated := i.(*structs.Job) 3483 3484 if updated.ModifyIndex == index { 3485 t.Fatalf("setJobStatus() should have been a no-op") 3486 } 3487 } 3488 3489 func TestStateStore_SetJobStatus(t *testing.T) { 3490 state := testStateStore(t) 3491 txn := state.db.Txn(true) 3492 3493 // Create and insert a mock job that should be pending but has an incorrect 3494 // status. 3495 job := mock.Job() 3496 job.Status = "foobar" 3497 job.ModifyIndex = 10 3498 if err := txn.Insert("jobs", job); err != nil { 3499 t.Fatalf("job insert failed: %v", err) 3500 } 3501 3502 index := uint64(1000) 3503 if err := state.setJobStatus(index, txn, job, false, ""); err != nil { 3504 t.Fatalf("setJobStatus() failed: %v", err) 3505 } 3506 3507 i, err := txn.First("jobs", "id", job.ID) 3508 if err != nil { 3509 t.Fatalf("job lookup failed: %v", err) 3510 } 3511 updated := i.(*structs.Job) 3512 3513 if updated.Status != structs.JobStatusPending { 3514 t.Fatalf("setJobStatus() set %v; expected %v", updated.Status, structs.JobStatusPending) 3515 } 3516 3517 if updated.ModifyIndex != index { 3518 t.Fatalf("setJobStatus() set %d; expected %d", updated.ModifyIndex, index) 3519 } 3520 } 3521 3522 func TestStateStore_GetJobStatus_NoEvalsOrAllocs(t *testing.T) { 3523 job := mock.Job() 3524 state := testStateStore(t) 3525 txn := state.db.Txn(false) 3526 status, err := state.getJobStatus(txn, job, false) 3527 if err != nil { 3528 t.Fatalf("getJobStatus() failed: %v", err) 3529 } 3530 3531 if status != structs.JobStatusPending { 3532 t.Fatalf("getJobStatus() returned %v; expected %v", status, structs.JobStatusPending) 3533 } 3534 } 3535 3536 func TestStateStore_GetJobStatus_NoEvalsOrAllocs_Periodic(t *testing.T) { 3537 job := mock.PeriodicJob() 3538 state := testStateStore(t) 3539 txn := state.db.Txn(false) 3540 status, err := state.getJobStatus(txn, job, false) 3541 if err != nil { 3542 t.Fatalf("getJobStatus() failed: %v", err) 3543 } 3544 3545 if status != structs.JobStatusRunning { 3546 t.Fatalf("getJobStatus() returned %v; expected %v", status, structs.JobStatusRunning) 3547 } 3548 } 3549 3550 func TestStateStore_GetJobStatus_NoEvalsOrAllocs_EvalDelete(t *testing.T) { 3551 job := mock.Job() 3552 state := testStateStore(t) 3553 txn := state.db.Txn(false) 3554 status, err := state.getJobStatus(txn, job, true) 3555 if err != nil { 3556 t.Fatalf("getJobStatus() failed: %v", err) 3557 } 3558 3559 if status != structs.JobStatusDead { 3560 t.Fatalf("getJobStatus() returned %v; expected %v", status, structs.JobStatusDead) 3561 } 3562 } 3563 3564 func TestStateStore_GetJobStatus_DeadEvalsAndAllocs(t *testing.T) { 3565 state := testStateStore(t) 3566 job := mock.Job() 3567 3568 // Create a mock alloc that is dead. 3569 alloc := mock.Alloc() 3570 alloc.JobID = job.ID 3571 alloc.DesiredStatus = structs.AllocDesiredStatusStop 3572 state.UpsertJobSummary(999, mock.JobSummary(alloc.JobID)) 3573 if err := state.UpsertAllocs(1000, []*structs.Allocation{alloc}); err != nil { 3574 t.Fatalf("err: %v", err) 3575 } 3576 3577 // Create a mock eval that is complete 3578 eval := mock.Eval() 3579 eval.JobID = job.ID 3580 eval.Status = structs.EvalStatusComplete 3581 if err := state.UpsertEvals(1001, []*structs.Evaluation{eval}); err != nil { 3582 t.Fatalf("err: %v", err) 3583 } 3584 3585 txn := state.db.Txn(false) 3586 status, err := state.getJobStatus(txn, job, false) 3587 if err != nil { 3588 t.Fatalf("getJobStatus() failed: %v", err) 3589 } 3590 3591 if status != structs.JobStatusDead { 3592 t.Fatalf("getJobStatus() returned %v; expected %v", status, structs.JobStatusDead) 3593 } 3594 } 3595 3596 func TestStateStore_GetJobStatus_RunningAlloc(t *testing.T) { 3597 state := testStateStore(t) 3598 job := mock.Job() 3599 3600 // Create a mock alloc that is running. 3601 alloc := mock.Alloc() 3602 alloc.JobID = job.ID 3603 alloc.DesiredStatus = structs.AllocDesiredStatusRun 3604 state.UpsertJobSummary(999, mock.JobSummary(alloc.JobID)) 3605 if err := state.UpsertAllocs(1000, []*structs.Allocation{alloc}); err != nil { 3606 t.Fatalf("err: %v", err) 3607 } 3608 3609 txn := state.db.Txn(false) 3610 status, err := state.getJobStatus(txn, job, true) 3611 if err != nil { 3612 t.Fatalf("getJobStatus() failed: %v", err) 3613 } 3614 3615 if status != structs.JobStatusRunning { 3616 t.Fatalf("getJobStatus() returned %v; expected %v", status, structs.JobStatusRunning) 3617 } 3618 } 3619 3620 func TestStateStore_SetJobStatus_PendingEval(t *testing.T) { 3621 state := testStateStore(t) 3622 job := mock.Job() 3623 3624 // Create a mock eval that is pending. 3625 eval := mock.Eval() 3626 eval.JobID = job.ID 3627 eval.Status = structs.EvalStatusPending 3628 if err := state.UpsertEvals(1000, []*structs.Evaluation{eval}); err != nil { 3629 t.Fatalf("err: %v", err) 3630 } 3631 3632 txn := state.db.Txn(false) 3633 status, err := state.getJobStatus(txn, job, true) 3634 if err != nil { 3635 t.Fatalf("getJobStatus() failed: %v", err) 3636 } 3637 3638 if status != structs.JobStatusPending { 3639 t.Fatalf("getJobStatus() returned %v; expected %v", status, structs.JobStatusPending) 3640 } 3641 } 3642 3643 func TestStateJobSummary_UpdateJobCount(t *testing.T) { 3644 state := testStateStore(t) 3645 alloc := mock.Alloc() 3646 job := alloc.Job 3647 job.TaskGroups[0].Count = 3 3648 3649 // Create watchsets so we can test that upsert fires the watch 3650 ws := memdb.NewWatchSet() 3651 if _, err := state.JobSummaryByID(ws, job.ID); err != nil { 3652 t.Fatalf("bad: %v", err) 3653 } 3654 3655 if err := state.UpsertJob(1000, job); err != nil { 3656 t.Fatalf("err: %v", err) 3657 } 3658 3659 if err := state.UpsertAllocs(1001, []*structs.Allocation{alloc}); err != nil { 3660 t.Fatalf("err: %v", err) 3661 } 3662 3663 if !watchFired(ws) { 3664 t.Fatalf("bad") 3665 } 3666 3667 ws = memdb.NewWatchSet() 3668 summary, _ := state.JobSummaryByID(ws, job.ID) 3669 expectedSummary := structs.JobSummary{ 3670 JobID: job.ID, 3671 Summary: map[string]structs.TaskGroupSummary{ 3672 "web": { 3673 Starting: 1, 3674 }, 3675 }, 3676 Children: new(structs.JobChildrenSummary), 3677 CreateIndex: 1000, 3678 ModifyIndex: 1001, 3679 } 3680 if !reflect.DeepEqual(summary, &expectedSummary) { 3681 t.Fatalf("expected: %v, actual: %v", expectedSummary, summary) 3682 } 3683 3684 // Create watchsets so we can test that upsert fires the watch 3685 ws2 := memdb.NewWatchSet() 3686 if _, err := state.JobSummaryByID(ws2, job.ID); err != nil { 3687 t.Fatalf("bad: %v", err) 3688 } 3689 3690 alloc2 := mock.Alloc() 3691 alloc2.Job = job 3692 alloc2.JobID = job.ID 3693 3694 alloc3 := mock.Alloc() 3695 alloc3.Job = job 3696 alloc3.JobID = job.ID 3697 3698 if err := state.UpsertAllocs(1002, []*structs.Allocation{alloc2, alloc3}); err != nil { 3699 t.Fatalf("err: %v", err) 3700 } 3701 3702 if !watchFired(ws2) { 3703 t.Fatalf("bad") 3704 } 3705 3706 outA, _ := state.AllocByID(ws, alloc3.ID) 3707 3708 summary, _ = state.JobSummaryByID(ws, job.ID) 3709 expectedSummary = structs.JobSummary{ 3710 JobID: job.ID, 3711 Summary: map[string]structs.TaskGroupSummary{ 3712 "web": { 3713 Starting: 3, 3714 }, 3715 }, 3716 Children: new(structs.JobChildrenSummary), 3717 CreateIndex: job.CreateIndex, 3718 ModifyIndex: outA.ModifyIndex, 3719 } 3720 if !reflect.DeepEqual(summary, &expectedSummary) { 3721 t.Fatalf("expected summary: %v, actual: %v", expectedSummary, summary) 3722 } 3723 3724 // Create watchsets so we can test that upsert fires the watch 3725 ws3 := memdb.NewWatchSet() 3726 if _, err := state.JobSummaryByID(ws3, job.ID); err != nil { 3727 t.Fatalf("bad: %v", err) 3728 } 3729 3730 alloc4 := mock.Alloc() 3731 alloc4.ID = alloc2.ID 3732 alloc4.Job = alloc2.Job 3733 alloc4.JobID = alloc2.JobID 3734 alloc4.ClientStatus = structs.AllocClientStatusComplete 3735 3736 alloc5 := mock.Alloc() 3737 alloc5.ID = alloc3.ID 3738 alloc5.Job = alloc3.Job 3739 alloc5.JobID = alloc3.JobID 3740 alloc5.ClientStatus = structs.AllocClientStatusComplete 3741 3742 if err := state.UpdateAllocsFromClient(1004, []*structs.Allocation{alloc4, alloc5}); err != nil { 3743 t.Fatalf("err: %v", err) 3744 } 3745 3746 if !watchFired(ws2) { 3747 t.Fatalf("bad") 3748 } 3749 3750 outA, _ = state.AllocByID(ws, alloc5.ID) 3751 summary, _ = state.JobSummaryByID(ws, job.ID) 3752 expectedSummary = structs.JobSummary{ 3753 JobID: job.ID, 3754 Summary: map[string]structs.TaskGroupSummary{ 3755 "web": { 3756 Complete: 2, 3757 Starting: 1, 3758 }, 3759 }, 3760 Children: new(structs.JobChildrenSummary), 3761 CreateIndex: job.CreateIndex, 3762 ModifyIndex: outA.ModifyIndex, 3763 } 3764 if !reflect.DeepEqual(summary, &expectedSummary) { 3765 t.Fatalf("expected: %v, actual: %v", expectedSummary, summary) 3766 } 3767 } 3768 3769 func TestJobSummary_UpdateClientStatus(t *testing.T) { 3770 state := testStateStore(t) 3771 alloc := mock.Alloc() 3772 job := alloc.Job 3773 job.TaskGroups[0].Count = 3 3774 3775 alloc2 := mock.Alloc() 3776 alloc2.Job = job 3777 alloc2.JobID = job.ID 3778 3779 alloc3 := mock.Alloc() 3780 alloc3.Job = job 3781 alloc3.JobID = job.ID 3782 3783 err := state.UpsertJob(1000, job) 3784 if err != nil { 3785 t.Fatalf("err: %v", err) 3786 } 3787 3788 if err := state.UpsertAllocs(1001, []*structs.Allocation{alloc, alloc2, alloc3}); err != nil { 3789 t.Fatalf("err: %v", err) 3790 } 3791 3792 ws := memdb.NewWatchSet() 3793 summary, _ := state.JobSummaryByID(ws, job.ID) 3794 if summary.Summary["web"].Starting != 3 { 3795 t.Fatalf("bad job summary: %v", summary) 3796 } 3797 3798 alloc4 := mock.Alloc() 3799 alloc4.ID = alloc2.ID 3800 alloc4.Job = alloc2.Job 3801 alloc4.JobID = alloc2.JobID 3802 alloc4.ClientStatus = structs.AllocClientStatusComplete 3803 3804 alloc5 := mock.Alloc() 3805 alloc5.ID = alloc3.ID 3806 alloc5.Job = alloc3.Job 3807 alloc5.JobID = alloc3.JobID 3808 alloc5.ClientStatus = structs.AllocClientStatusFailed 3809 3810 alloc6 := mock.Alloc() 3811 alloc6.ID = alloc.ID 3812 alloc6.Job = alloc.Job 3813 alloc6.JobID = alloc.JobID 3814 alloc6.ClientStatus = structs.AllocClientStatusRunning 3815 3816 if err := state.UpdateAllocsFromClient(1002, []*structs.Allocation{alloc4, alloc5, alloc6}); err != nil { 3817 t.Fatalf("err: %v", err) 3818 } 3819 3820 if !watchFired(ws) { 3821 t.Fatalf("bad") 3822 } 3823 3824 summary, _ = state.JobSummaryByID(ws, job.ID) 3825 if summary.Summary["web"].Running != 1 || summary.Summary["web"].Failed != 1 || summary.Summary["web"].Complete != 1 { 3826 t.Fatalf("bad job summary: %v", summary) 3827 } 3828 3829 alloc7 := mock.Alloc() 3830 alloc7.Job = alloc.Job 3831 alloc7.JobID = alloc.JobID 3832 3833 if err := state.UpsertAllocs(1003, []*structs.Allocation{alloc7}); err != nil { 3834 t.Fatalf("err: %v", err) 3835 } 3836 summary, _ = state.JobSummaryByID(ws, job.ID) 3837 if summary.Summary["web"].Starting != 1 || summary.Summary["web"].Running != 1 || summary.Summary["web"].Failed != 1 || summary.Summary["web"].Complete != 1 { 3838 t.Fatalf("bad job summary: %v", summary) 3839 } 3840 } 3841 3842 func TestStateStore_UpsertVaultAccessors(t *testing.T) { 3843 state := testStateStore(t) 3844 a := mock.VaultAccessor() 3845 a2 := mock.VaultAccessor() 3846 3847 ws := memdb.NewWatchSet() 3848 if _, err := state.VaultAccessor(ws, a.Accessor); err != nil { 3849 t.Fatalf("err: %v", err) 3850 } 3851 3852 if _, err := state.VaultAccessor(ws, a2.Accessor); err != nil { 3853 t.Fatalf("err: %v", err) 3854 } 3855 3856 err := state.UpsertVaultAccessor(1000, []*structs.VaultAccessor{a, a2}) 3857 if err != nil { 3858 t.Fatalf("err: %v", err) 3859 } 3860 3861 if !watchFired(ws) { 3862 t.Fatalf("bad") 3863 } 3864 3865 ws = memdb.NewWatchSet() 3866 out, err := state.VaultAccessor(ws, a.Accessor) 3867 if err != nil { 3868 t.Fatalf("err: %v", err) 3869 } 3870 3871 if !reflect.DeepEqual(a, out) { 3872 t.Fatalf("bad: %#v %#v", a, out) 3873 } 3874 3875 out, err = state.VaultAccessor(ws, a2.Accessor) 3876 if err != nil { 3877 t.Fatalf("err: %v", err) 3878 } 3879 3880 if !reflect.DeepEqual(a2, out) { 3881 t.Fatalf("bad: %#v %#v", a2, out) 3882 } 3883 3884 iter, err := state.VaultAccessors(ws) 3885 if err != nil { 3886 t.Fatalf("err: %v", err) 3887 } 3888 3889 count := 0 3890 for { 3891 raw := iter.Next() 3892 if raw == nil { 3893 break 3894 } 3895 3896 count++ 3897 accessor := raw.(*structs.VaultAccessor) 3898 3899 if !reflect.DeepEqual(accessor, a) && !reflect.DeepEqual(accessor, a2) { 3900 t.Fatalf("bad: %#v", accessor) 3901 } 3902 } 3903 3904 if count != 2 { 3905 t.Fatalf("bad: %d", count) 3906 } 3907 3908 index, err := state.Index("vault_accessors") 3909 if err != nil { 3910 t.Fatalf("err: %v", err) 3911 } 3912 if index != 1000 { 3913 t.Fatalf("bad: %d", index) 3914 } 3915 3916 if watchFired(ws) { 3917 t.Fatalf("bad") 3918 } 3919 } 3920 3921 func TestStateStore_DeleteVaultAccessors(t *testing.T) { 3922 state := testStateStore(t) 3923 a1 := mock.VaultAccessor() 3924 a2 := mock.VaultAccessor() 3925 accessors := []*structs.VaultAccessor{a1, a2} 3926 3927 err := state.UpsertVaultAccessor(1000, accessors) 3928 if err != nil { 3929 t.Fatalf("err: %v", err) 3930 } 3931 3932 ws := memdb.NewWatchSet() 3933 if _, err := state.VaultAccessor(ws, a1.Accessor); err != nil { 3934 t.Fatalf("err: %v", err) 3935 } 3936 3937 err = state.DeleteVaultAccessors(1001, accessors) 3938 if err != nil { 3939 t.Fatalf("err: %v", err) 3940 } 3941 3942 if !watchFired(ws) { 3943 t.Fatalf("bad") 3944 } 3945 3946 ws = memdb.NewWatchSet() 3947 out, err := state.VaultAccessor(ws, a1.Accessor) 3948 if err != nil { 3949 t.Fatalf("err: %v", err) 3950 } 3951 if out != nil { 3952 t.Fatalf("bad: %#v %#v", a1, out) 3953 } 3954 out, err = state.VaultAccessor(ws, a2.Accessor) 3955 if err != nil { 3956 t.Fatalf("err: %v", err) 3957 } 3958 if out != nil { 3959 t.Fatalf("bad: %#v %#v", a2, out) 3960 } 3961 3962 index, err := state.Index("vault_accessors") 3963 if err != nil { 3964 t.Fatalf("err: %v", err) 3965 } 3966 if index != 1001 { 3967 t.Fatalf("bad: %d", index) 3968 } 3969 3970 if watchFired(ws) { 3971 t.Fatalf("bad") 3972 } 3973 } 3974 3975 func TestStateStore_VaultAccessorsByAlloc(t *testing.T) { 3976 state := testStateStore(t) 3977 alloc := mock.Alloc() 3978 var accessors []*structs.VaultAccessor 3979 var expected []*structs.VaultAccessor 3980 3981 for i := 0; i < 5; i++ { 3982 accessor := mock.VaultAccessor() 3983 accessor.AllocID = alloc.ID 3984 expected = append(expected, accessor) 3985 accessors = append(accessors, accessor) 3986 } 3987 3988 for i := 0; i < 10; i++ { 3989 accessor := mock.VaultAccessor() 3990 accessors = append(accessors, accessor) 3991 } 3992 3993 err := state.UpsertVaultAccessor(1000, accessors) 3994 if err != nil { 3995 t.Fatalf("err: %v", err) 3996 } 3997 3998 ws := memdb.NewWatchSet() 3999 out, err := state.VaultAccessorsByAlloc(ws, alloc.ID) 4000 if err != nil { 4001 t.Fatalf("err: %v", err) 4002 } 4003 4004 if len(expected) != len(out) { 4005 t.Fatalf("bad: %#v %#v", len(expected), len(out)) 4006 } 4007 4008 index, err := state.Index("vault_accessors") 4009 if err != nil { 4010 t.Fatalf("err: %v", err) 4011 } 4012 if index != 1000 { 4013 t.Fatalf("bad: %d", index) 4014 } 4015 4016 if watchFired(ws) { 4017 t.Fatalf("bad") 4018 } 4019 } 4020 4021 func TestStateStore_VaultAccessorsByNode(t *testing.T) { 4022 state := testStateStore(t) 4023 node := mock.Node() 4024 var accessors []*structs.VaultAccessor 4025 var expected []*structs.VaultAccessor 4026 4027 for i := 0; i < 5; i++ { 4028 accessor := mock.VaultAccessor() 4029 accessor.NodeID = node.ID 4030 expected = append(expected, accessor) 4031 accessors = append(accessors, accessor) 4032 } 4033 4034 for i := 0; i < 10; i++ { 4035 accessor := mock.VaultAccessor() 4036 accessors = append(accessors, accessor) 4037 } 4038 4039 err := state.UpsertVaultAccessor(1000, accessors) 4040 if err != nil { 4041 t.Fatalf("err: %v", err) 4042 } 4043 4044 ws := memdb.NewWatchSet() 4045 out, err := state.VaultAccessorsByNode(ws, node.ID) 4046 if err != nil { 4047 t.Fatalf("err: %v", err) 4048 } 4049 4050 if len(expected) != len(out) { 4051 t.Fatalf("bad: %#v %#v", len(expected), len(out)) 4052 } 4053 4054 index, err := state.Index("vault_accessors") 4055 if err != nil { 4056 t.Fatalf("err: %v", err) 4057 } 4058 if index != 1000 { 4059 t.Fatalf("bad: %d", index) 4060 } 4061 4062 if watchFired(ws) { 4063 t.Fatalf("bad") 4064 } 4065 } 4066 4067 func TestStateStore_RestoreVaultAccessor(t *testing.T) { 4068 state := testStateStore(t) 4069 a := mock.VaultAccessor() 4070 4071 restore, err := state.Restore() 4072 if err != nil { 4073 t.Fatalf("err: %v", err) 4074 } 4075 4076 err = restore.VaultAccessorRestore(a) 4077 if err != nil { 4078 t.Fatalf("err: %v", err) 4079 } 4080 restore.Commit() 4081 4082 ws := memdb.NewWatchSet() 4083 out, err := state.VaultAccessor(ws, a.Accessor) 4084 if err != nil { 4085 t.Fatalf("err: %v", err) 4086 } 4087 4088 if !reflect.DeepEqual(out, a) { 4089 t.Fatalf("Bad: %#v %#v", out, a) 4090 } 4091 4092 if watchFired(ws) { 4093 t.Fatalf("bad") 4094 } 4095 } 4096 4097 func TestStateStore_Abandon(t *testing.T) { 4098 s := testStateStore(t) 4099 abandonCh := s.AbandonCh() 4100 s.Abandon() 4101 select { 4102 case <-abandonCh: 4103 default: 4104 t.Fatalf("bad") 4105 } 4106 } 4107 4108 // watchFired is a helper for unit tests that returns if the given watch set 4109 // fired (it doesn't care which watch actually fired). This uses a fixed 4110 // timeout since we already expect the event happened before calling this and 4111 // just need to distinguish a fire from a timeout. We do need a little time to 4112 // allow the watch to set up any goroutines, though. 4113 func watchFired(ws memdb.WatchSet) bool { 4114 timedOut := ws.Watch(time.After(50 * time.Millisecond)) 4115 return !timedOut 4116 } 4117 4118 // NodeIDSort is used to sort nodes by ID 4119 type NodeIDSort []*structs.Node 4120 4121 func (n NodeIDSort) Len() int { 4122 return len(n) 4123 } 4124 4125 func (n NodeIDSort) Less(i, j int) bool { 4126 return n[i].ID < n[j].ID 4127 } 4128 4129 func (n NodeIDSort) Swap(i, j int) { 4130 n[i], n[j] = n[j], n[i] 4131 } 4132 4133 // JobIDis used to sort jobs by id 4134 type JobIDSort []*structs.Job 4135 4136 func (n JobIDSort) Len() int { 4137 return len(n) 4138 } 4139 4140 func (n JobIDSort) Less(i, j int) bool { 4141 return n[i].ID < n[j].ID 4142 } 4143 4144 func (n JobIDSort) Swap(i, j int) { 4145 n[i], n[j] = n[j], n[i] 4146 } 4147 4148 // EvalIDis used to sort evals by id 4149 type EvalIDSort []*structs.Evaluation 4150 4151 func (n EvalIDSort) Len() int { 4152 return len(n) 4153 } 4154 4155 func (n EvalIDSort) Less(i, j int) bool { 4156 return n[i].ID < n[j].ID 4157 } 4158 4159 func (n EvalIDSort) Swap(i, j int) { 4160 n[i], n[j] = n[j], n[i] 4161 } 4162 4163 // AllocIDsort used to sort allocations by id 4164 type AllocIDSort []*structs.Allocation 4165 4166 func (n AllocIDSort) Len() int { 4167 return len(n) 4168 } 4169 4170 func (n AllocIDSort) Less(i, j int) bool { 4171 return n[i].ID < n[j].ID 4172 } 4173 4174 func (n AllocIDSort) Swap(i, j int) { 4175 n[i], n[j] = n[j], n[i] 4176 }