github.imxd.top/hashicorp/consul@v1.4.5/agent/consul/fsm/commands_oss_test.go (about) 1 package fsm 2 3 import ( 4 "fmt" 5 "math/rand" 6 "os" 7 "reflect" 8 "testing" 9 "time" 10 11 "github.com/hashicorp/consul/agent/connect" 12 "github.com/hashicorp/consul/agent/consul/autopilot" 13 "github.com/hashicorp/consul/agent/structs" 14 "github.com/hashicorp/consul/api" 15 "github.com/hashicorp/consul/types" 16 "github.com/hashicorp/go-uuid" 17 "github.com/hashicorp/serf/coordinate" 18 "github.com/mitchellh/mapstructure" 19 "github.com/pascaldekloe/goe/verify" 20 "github.com/stretchr/testify/assert" 21 ) 22 23 func generateUUID() (ret string) { 24 var err error 25 if ret, err = uuid.GenerateUUID(); err != nil { 26 panic(fmt.Sprintf("Unable to generate a UUID, %v", err)) 27 } 28 return ret 29 } 30 31 func generateRandomCoordinate() *coordinate.Coordinate { 32 config := coordinate.DefaultConfig() 33 coord := coordinate.NewCoordinate(config) 34 for i := range coord.Vec { 35 coord.Vec[i] = rand.NormFloat64() 36 } 37 coord.Error = rand.NormFloat64() 38 coord.Adjustment = rand.NormFloat64() 39 return coord 40 } 41 42 func TestFSM_RegisterNode(t *testing.T) { 43 t.Parallel() 44 fsm, err := New(nil, os.Stderr) 45 if err != nil { 46 t.Fatalf("err: %v", err) 47 } 48 49 req := structs.RegisterRequest{ 50 Datacenter: "dc1", 51 Node: "foo", 52 Address: "127.0.0.1", 53 } 54 buf, err := structs.Encode(structs.RegisterRequestType, req) 55 if err != nil { 56 t.Fatalf("err: %v", err) 57 } 58 59 resp := fsm.Apply(makeLog(buf)) 60 if resp != nil { 61 t.Fatalf("resp: %v", resp) 62 } 63 64 // Verify we are registered 65 _, node, err := fsm.state.GetNode("foo") 66 if err != nil { 67 t.Fatalf("err: %s", err) 68 } 69 if node == nil { 70 t.Fatalf("not found!") 71 } 72 if node.ModifyIndex != 1 { 73 t.Fatalf("bad index: %d", node.ModifyIndex) 74 } 75 76 // Verify service registered 77 _, services, err := fsm.state.NodeServices(nil, "foo") 78 if err != nil { 79 t.Fatalf("err: %s", err) 80 } 81 if len(services.Services) != 0 { 82 t.Fatalf("Services: %v", services) 83 } 84 } 85 86 func TestFSM_RegisterNode_Service(t *testing.T) { 87 t.Parallel() 88 fsm, err := New(nil, os.Stderr) 89 if err != nil { 90 t.Fatalf("err: %v", err) 91 } 92 93 req := structs.RegisterRequest{ 94 Datacenter: "dc1", 95 Node: "foo", 96 Address: "127.0.0.1", 97 Service: &structs.NodeService{ 98 ID: "db", 99 Service: "db", 100 Tags: []string{"master"}, 101 Port: 8000, 102 }, 103 Check: &structs.HealthCheck{ 104 Node: "foo", 105 CheckID: "db", 106 Name: "db connectivity", 107 Status: api.HealthPassing, 108 ServiceID: "db", 109 }, 110 } 111 buf, err := structs.Encode(structs.RegisterRequestType, req) 112 if err != nil { 113 t.Fatalf("err: %v", err) 114 } 115 116 resp := fsm.Apply(makeLog(buf)) 117 if resp != nil { 118 t.Fatalf("resp: %v", resp) 119 } 120 121 // Verify we are registered 122 _, node, err := fsm.state.GetNode("foo") 123 if err != nil { 124 t.Fatalf("err: %s", err) 125 } 126 if node == nil { 127 t.Fatalf("not found!") 128 } 129 130 // Verify service registered 131 _, services, err := fsm.state.NodeServices(nil, "foo") 132 if err != nil { 133 t.Fatalf("err: %s", err) 134 } 135 if _, ok := services.Services["db"]; !ok { 136 t.Fatalf("not registered!") 137 } 138 139 // Verify check 140 _, checks, err := fsm.state.NodeChecks(nil, "foo") 141 if err != nil { 142 t.Fatalf("err: %s", err) 143 } 144 if checks[0].CheckID != "db" { 145 t.Fatalf("not registered!") 146 } 147 } 148 149 func TestFSM_DeregisterService(t *testing.T) { 150 t.Parallel() 151 fsm, err := New(nil, os.Stderr) 152 if err != nil { 153 t.Fatalf("err: %v", err) 154 } 155 156 req := structs.RegisterRequest{ 157 Datacenter: "dc1", 158 Node: "foo", 159 Address: "127.0.0.1", 160 Service: &structs.NodeService{ 161 ID: "db", 162 Service: "db", 163 Tags: []string{"master"}, 164 Port: 8000, 165 }, 166 } 167 buf, err := structs.Encode(structs.RegisterRequestType, req) 168 if err != nil { 169 t.Fatalf("err: %v", err) 170 } 171 172 resp := fsm.Apply(makeLog(buf)) 173 if resp != nil { 174 t.Fatalf("resp: %v", resp) 175 } 176 177 dereg := structs.DeregisterRequest{ 178 Datacenter: "dc1", 179 Node: "foo", 180 ServiceID: "db", 181 } 182 buf, err = structs.Encode(structs.DeregisterRequestType, dereg) 183 if err != nil { 184 t.Fatalf("err: %v", err) 185 } 186 187 resp = fsm.Apply(makeLog(buf)) 188 if resp != nil { 189 t.Fatalf("resp: %v", resp) 190 } 191 192 // Verify we are registered 193 _, node, err := fsm.state.GetNode("foo") 194 if err != nil { 195 t.Fatalf("err: %s", err) 196 } 197 if node == nil { 198 t.Fatalf("not found!") 199 } 200 201 // Verify service not registered 202 _, services, err := fsm.state.NodeServices(nil, "foo") 203 if err != nil { 204 t.Fatalf("err: %s", err) 205 } 206 if _, ok := services.Services["db"]; ok { 207 t.Fatalf("db registered!") 208 } 209 } 210 211 func TestFSM_DeregisterCheck(t *testing.T) { 212 t.Parallel() 213 fsm, err := New(nil, os.Stderr) 214 if err != nil { 215 t.Fatalf("err: %v", err) 216 } 217 218 req := structs.RegisterRequest{ 219 Datacenter: "dc1", 220 Node: "foo", 221 Address: "127.0.0.1", 222 Check: &structs.HealthCheck{ 223 Node: "foo", 224 CheckID: "mem", 225 Name: "memory util", 226 Status: api.HealthPassing, 227 }, 228 } 229 buf, err := structs.Encode(structs.RegisterRequestType, req) 230 if err != nil { 231 t.Fatalf("err: %v", err) 232 } 233 234 resp := fsm.Apply(makeLog(buf)) 235 if resp != nil { 236 t.Fatalf("resp: %v", resp) 237 } 238 239 dereg := structs.DeregisterRequest{ 240 Datacenter: "dc1", 241 Node: "foo", 242 CheckID: "mem", 243 } 244 buf, err = structs.Encode(structs.DeregisterRequestType, dereg) 245 if err != nil { 246 t.Fatalf("err: %v", err) 247 } 248 249 resp = fsm.Apply(makeLog(buf)) 250 if resp != nil { 251 t.Fatalf("resp: %v", resp) 252 } 253 254 // Verify we are registered 255 _, node, err := fsm.state.GetNode("foo") 256 if err != nil { 257 t.Fatalf("err: %s", err) 258 } 259 if node == nil { 260 t.Fatalf("not found!") 261 } 262 263 // Verify check not registered 264 _, checks, err := fsm.state.NodeChecks(nil, "foo") 265 if err != nil { 266 t.Fatalf("err: %s", err) 267 } 268 if len(checks) != 0 { 269 t.Fatalf("check registered!") 270 } 271 } 272 273 func TestFSM_DeregisterNode(t *testing.T) { 274 t.Parallel() 275 fsm, err := New(nil, os.Stderr) 276 if err != nil { 277 t.Fatalf("err: %v", err) 278 } 279 280 req := structs.RegisterRequest{ 281 Datacenter: "dc1", 282 Node: "foo", 283 Address: "127.0.0.1", 284 Service: &structs.NodeService{ 285 ID: "db", 286 Service: "db", 287 Tags: []string{"master"}, 288 Port: 8000, 289 }, 290 Check: &structs.HealthCheck{ 291 Node: "foo", 292 CheckID: "db", 293 Name: "db connectivity", 294 Status: api.HealthPassing, 295 ServiceID: "db", 296 }, 297 } 298 buf, err := structs.Encode(structs.RegisterRequestType, req) 299 if err != nil { 300 t.Fatalf("err: %v", err) 301 } 302 303 resp := fsm.Apply(makeLog(buf)) 304 if resp != nil { 305 t.Fatalf("resp: %v", resp) 306 } 307 308 dereg := structs.DeregisterRequest{ 309 Datacenter: "dc1", 310 Node: "foo", 311 } 312 buf, err = structs.Encode(structs.DeregisterRequestType, dereg) 313 if err != nil { 314 t.Fatalf("err: %v", err) 315 } 316 317 resp = fsm.Apply(makeLog(buf)) 318 if resp != nil { 319 t.Fatalf("resp: %v", resp) 320 } 321 322 // Verify we are not registered 323 _, node, err := fsm.state.GetNode("foo") 324 if err != nil { 325 t.Fatalf("err: %s", err) 326 } 327 if node != nil { 328 t.Fatalf("found!") 329 } 330 331 // Verify service not registered 332 _, services, err := fsm.state.NodeServices(nil, "foo") 333 if err != nil { 334 t.Fatalf("err: %s", err) 335 } 336 if services != nil { 337 t.Fatalf("Services: %v", services) 338 } 339 340 // Verify checks not registered 341 _, checks, err := fsm.state.NodeChecks(nil, "foo") 342 if err != nil { 343 t.Fatalf("err: %s", err) 344 } 345 if len(checks) != 0 { 346 t.Fatalf("Services: %v", services) 347 } 348 } 349 350 func TestFSM_KVSDelete(t *testing.T) { 351 t.Parallel() 352 fsm, err := New(nil, os.Stderr) 353 if err != nil { 354 t.Fatalf("err: %v", err) 355 } 356 357 req := structs.KVSRequest{ 358 Datacenter: "dc1", 359 Op: api.KVSet, 360 DirEnt: structs.DirEntry{ 361 Key: "/test/path", 362 Flags: 0, 363 Value: []byte("test"), 364 }, 365 } 366 buf, err := structs.Encode(structs.KVSRequestType, req) 367 if err != nil { 368 t.Fatalf("err: %v", err) 369 } 370 resp := fsm.Apply(makeLog(buf)) 371 if resp != nil { 372 t.Fatalf("resp: %v", resp) 373 } 374 375 // Run the delete 376 req.Op = api.KVDelete 377 buf, err = structs.Encode(structs.KVSRequestType, req) 378 if err != nil { 379 t.Fatalf("err: %v", err) 380 } 381 resp = fsm.Apply(makeLog(buf)) 382 if resp != nil { 383 t.Fatalf("resp: %v", resp) 384 } 385 386 // Verify key is not set 387 _, d, err := fsm.state.KVSGet(nil, "/test/path") 388 if err != nil { 389 t.Fatalf("err: %v", err) 390 } 391 if d != nil { 392 t.Fatalf("key present") 393 } 394 } 395 396 func TestFSM_KVSDeleteTree(t *testing.T) { 397 t.Parallel() 398 fsm, err := New(nil, os.Stderr) 399 if err != nil { 400 t.Fatalf("err: %v", err) 401 } 402 403 req := structs.KVSRequest{ 404 Datacenter: "dc1", 405 Op: api.KVSet, 406 DirEnt: structs.DirEntry{ 407 Key: "/test/path", 408 Flags: 0, 409 Value: []byte("test"), 410 }, 411 } 412 buf, err := structs.Encode(structs.KVSRequestType, req) 413 if err != nil { 414 t.Fatalf("err: %v", err) 415 } 416 resp := fsm.Apply(makeLog(buf)) 417 if resp != nil { 418 t.Fatalf("resp: %v", resp) 419 } 420 421 // Run the delete tree 422 req.Op = api.KVDeleteTree 423 req.DirEnt.Key = "/test" 424 buf, err = structs.Encode(structs.KVSRequestType, req) 425 if err != nil { 426 t.Fatalf("err: %v", err) 427 } 428 resp = fsm.Apply(makeLog(buf)) 429 if resp != nil { 430 t.Fatalf("resp: %v", resp) 431 } 432 433 // Verify key is not set 434 _, d, err := fsm.state.KVSGet(nil, "/test/path") 435 if err != nil { 436 t.Fatalf("err: %v", err) 437 } 438 if d != nil { 439 t.Fatalf("key present") 440 } 441 } 442 443 func TestFSM_KVSDeleteCheckAndSet(t *testing.T) { 444 t.Parallel() 445 fsm, err := New(nil, os.Stderr) 446 if err != nil { 447 t.Fatalf("err: %v", err) 448 } 449 450 req := structs.KVSRequest{ 451 Datacenter: "dc1", 452 Op: api.KVSet, 453 DirEnt: structs.DirEntry{ 454 Key: "/test/path", 455 Flags: 0, 456 Value: []byte("test"), 457 }, 458 } 459 buf, err := structs.Encode(structs.KVSRequestType, req) 460 if err != nil { 461 t.Fatalf("err: %v", err) 462 } 463 resp := fsm.Apply(makeLog(buf)) 464 if resp != nil { 465 t.Fatalf("resp: %v", resp) 466 } 467 468 // Verify key is set 469 _, d, err := fsm.state.KVSGet(nil, "/test/path") 470 if err != nil { 471 t.Fatalf("err: %v", err) 472 } 473 if d == nil { 474 t.Fatalf("key missing") 475 } 476 477 // Run the check-and-set 478 req.Op = api.KVDeleteCAS 479 req.DirEnt.ModifyIndex = d.ModifyIndex 480 buf, err = structs.Encode(structs.KVSRequestType, req) 481 if err != nil { 482 t.Fatalf("err: %v", err) 483 } 484 resp = fsm.Apply(makeLog(buf)) 485 if resp.(bool) != true { 486 t.Fatalf("resp: %v", resp) 487 } 488 489 // Verify key is gone 490 _, d, err = fsm.state.KVSGet(nil, "/test/path") 491 if err != nil { 492 t.Fatalf("err: %v", err) 493 } 494 if d != nil { 495 t.Fatalf("bad: %v", d) 496 } 497 } 498 499 func TestFSM_KVSCheckAndSet(t *testing.T) { 500 t.Parallel() 501 fsm, err := New(nil, os.Stderr) 502 if err != nil { 503 t.Fatalf("err: %v", err) 504 } 505 506 req := structs.KVSRequest{ 507 Datacenter: "dc1", 508 Op: api.KVSet, 509 DirEnt: structs.DirEntry{ 510 Key: "/test/path", 511 Flags: 0, 512 Value: []byte("test"), 513 }, 514 } 515 buf, err := structs.Encode(structs.KVSRequestType, req) 516 if err != nil { 517 t.Fatalf("err: %v", err) 518 } 519 resp := fsm.Apply(makeLog(buf)) 520 if resp != nil { 521 t.Fatalf("resp: %v", resp) 522 } 523 524 // Verify key is set 525 _, d, err := fsm.state.KVSGet(nil, "/test/path") 526 if err != nil { 527 t.Fatalf("err: %v", err) 528 } 529 if d == nil { 530 t.Fatalf("key missing") 531 } 532 533 // Run the check-and-set 534 req.Op = api.KVCAS 535 req.DirEnt.ModifyIndex = d.ModifyIndex 536 req.DirEnt.Value = []byte("zip") 537 buf, err = structs.Encode(structs.KVSRequestType, req) 538 if err != nil { 539 t.Fatalf("err: %v", err) 540 } 541 resp = fsm.Apply(makeLog(buf)) 542 if resp.(bool) != true { 543 t.Fatalf("resp: %v", resp) 544 } 545 546 // Verify key is updated 547 _, d, err = fsm.state.KVSGet(nil, "/test/path") 548 if err != nil { 549 t.Fatalf("err: %v", err) 550 } 551 if string(d.Value) != "zip" { 552 t.Fatalf("bad: %v", d) 553 } 554 } 555 556 func TestFSM_KVSLock(t *testing.T) { 557 t.Parallel() 558 fsm, err := New(nil, os.Stderr) 559 if err != nil { 560 t.Fatalf("err: %v", err) 561 } 562 563 fsm.state.EnsureNode(1, &structs.Node{Node: "foo", Address: "127.0.0.1"}) 564 session := &structs.Session{ID: generateUUID(), Node: "foo"} 565 fsm.state.SessionCreate(2, session) 566 567 req := structs.KVSRequest{ 568 Datacenter: "dc1", 569 Op: api.KVLock, 570 DirEnt: structs.DirEntry{ 571 Key: "/test/path", 572 Value: []byte("test"), 573 Session: session.ID, 574 }, 575 } 576 buf, err := structs.Encode(structs.KVSRequestType, req) 577 if err != nil { 578 t.Fatalf("err: %v", err) 579 } 580 resp := fsm.Apply(makeLog(buf)) 581 if resp != true { 582 t.Fatalf("resp: %v", resp) 583 } 584 585 // Verify key is locked 586 _, d, err := fsm.state.KVSGet(nil, "/test/path") 587 if err != nil { 588 t.Fatalf("err: %v", err) 589 } 590 if d == nil { 591 t.Fatalf("missing") 592 } 593 if d.LockIndex != 1 { 594 t.Fatalf("bad: %v", *d) 595 } 596 if d.Session != session.ID { 597 t.Fatalf("bad: %v", *d) 598 } 599 } 600 601 func TestFSM_KVSUnlock(t *testing.T) { 602 t.Parallel() 603 fsm, err := New(nil, os.Stderr) 604 if err != nil { 605 t.Fatalf("err: %v", err) 606 } 607 608 fsm.state.EnsureNode(1, &structs.Node{Node: "foo", Address: "127.0.0.1"}) 609 session := &structs.Session{ID: generateUUID(), Node: "foo"} 610 fsm.state.SessionCreate(2, session) 611 612 req := structs.KVSRequest{ 613 Datacenter: "dc1", 614 Op: api.KVLock, 615 DirEnt: structs.DirEntry{ 616 Key: "/test/path", 617 Value: []byte("test"), 618 Session: session.ID, 619 }, 620 } 621 buf, err := structs.Encode(structs.KVSRequestType, req) 622 if err != nil { 623 t.Fatalf("err: %v", err) 624 } 625 resp := fsm.Apply(makeLog(buf)) 626 if resp != true { 627 t.Fatalf("resp: %v", resp) 628 } 629 630 req = structs.KVSRequest{ 631 Datacenter: "dc1", 632 Op: api.KVUnlock, 633 DirEnt: structs.DirEntry{ 634 Key: "/test/path", 635 Value: []byte("test"), 636 Session: session.ID, 637 }, 638 } 639 buf, err = structs.Encode(structs.KVSRequestType, req) 640 if err != nil { 641 t.Fatalf("err: %v", err) 642 } 643 resp = fsm.Apply(makeLog(buf)) 644 if resp != true { 645 t.Fatalf("resp: %v", resp) 646 } 647 648 // Verify key is unlocked 649 _, d, err := fsm.state.KVSGet(nil, "/test/path") 650 if err != nil { 651 t.Fatalf("err: %v", err) 652 } 653 if d == nil { 654 t.Fatalf("missing") 655 } 656 if d.LockIndex != 1 { 657 t.Fatalf("bad: %v", *d) 658 } 659 if d.Session != "" { 660 t.Fatalf("bad: %v", *d) 661 } 662 } 663 664 func TestFSM_CoordinateUpdate(t *testing.T) { 665 t.Parallel() 666 fsm, err := New(nil, os.Stderr) 667 if err != nil { 668 t.Fatalf("err: %v", err) 669 } 670 671 // Register some nodes. 672 fsm.state.EnsureNode(1, &structs.Node{Node: "node1", Address: "127.0.0.1"}) 673 fsm.state.EnsureNode(2, &structs.Node{Node: "node2", Address: "127.0.0.1"}) 674 675 // Write a batch of two coordinates. 676 updates := structs.Coordinates{ 677 &structs.Coordinate{ 678 Node: "node1", 679 Coord: generateRandomCoordinate(), 680 }, 681 &structs.Coordinate{ 682 Node: "node2", 683 Coord: generateRandomCoordinate(), 684 }, 685 } 686 buf, err := structs.Encode(structs.CoordinateBatchUpdateType, updates) 687 if err != nil { 688 t.Fatalf("err: %v", err) 689 } 690 resp := fsm.Apply(makeLog(buf)) 691 if resp != nil { 692 t.Fatalf("resp: %v", resp) 693 } 694 695 // Read back the two coordinates to make sure they got updated. 696 _, coords, err := fsm.state.Coordinates(nil) 697 if err != nil { 698 t.Fatalf("err: %s", err) 699 } 700 if !reflect.DeepEqual(coords, updates) { 701 t.Fatalf("bad: %#v", coords) 702 } 703 } 704 705 func TestFSM_SessionCreate_Destroy(t *testing.T) { 706 t.Parallel() 707 fsm, err := New(nil, os.Stderr) 708 if err != nil { 709 t.Fatalf("err: %v", err) 710 } 711 712 fsm.state.EnsureNode(1, &structs.Node{Node: "foo", Address: "127.0.0.1"}) 713 fsm.state.EnsureCheck(2, &structs.HealthCheck{ 714 Node: "foo", 715 CheckID: "web", 716 Status: api.HealthPassing, 717 }) 718 719 // Create a new session 720 req := structs.SessionRequest{ 721 Datacenter: "dc1", 722 Op: structs.SessionCreate, 723 Session: structs.Session{ 724 ID: generateUUID(), 725 Node: "foo", 726 Checks: []types.CheckID{"web"}, 727 }, 728 } 729 buf, err := structs.Encode(structs.SessionRequestType, req) 730 if err != nil { 731 t.Fatalf("err: %v", err) 732 } 733 resp := fsm.Apply(makeLog(buf)) 734 if err, ok := resp.(error); ok { 735 t.Fatalf("resp: %v", err) 736 } 737 738 // Get the session 739 id := resp.(string) 740 _, session, err := fsm.state.SessionGet(nil, id) 741 if err != nil { 742 t.Fatalf("err: %v", err) 743 } 744 if session == nil { 745 t.Fatalf("missing") 746 } 747 748 // Verify the session 749 if session.ID != id { 750 t.Fatalf("bad: %v", *session) 751 } 752 if session.Node != "foo" { 753 t.Fatalf("bad: %v", *session) 754 } 755 if session.Checks[0] != "web" { 756 t.Fatalf("bad: %v", *session) 757 } 758 759 // Try to destroy 760 destroy := structs.SessionRequest{ 761 Datacenter: "dc1", 762 Op: structs.SessionDestroy, 763 Session: structs.Session{ 764 ID: id, 765 }, 766 } 767 buf, err = structs.Encode(structs.SessionRequestType, destroy) 768 if err != nil { 769 t.Fatalf("err: %v", err) 770 } 771 resp = fsm.Apply(makeLog(buf)) 772 if resp != nil { 773 t.Fatalf("resp: %v", resp) 774 } 775 776 _, session, err = fsm.state.SessionGet(nil, id) 777 if err != nil { 778 t.Fatalf("err: %v", err) 779 } 780 if session != nil { 781 t.Fatalf("should be destroyed") 782 } 783 } 784 785 func TestFSM_ACL_CRUD(t *testing.T) { 786 t.Parallel() 787 fsm, err := New(nil, os.Stderr) 788 if err != nil { 789 t.Fatalf("err: %v", err) 790 } 791 792 // Create a new ACL. 793 req := structs.ACLRequest{ 794 Datacenter: "dc1", 795 Op: structs.ACLSet, 796 ACL: structs.ACL{ 797 ID: generateUUID(), 798 Name: "User token", 799 Type: structs.ACLTokenTypeClient, 800 }, 801 } 802 buf, err := structs.Encode(structs.ACLRequestType, req) 803 if err != nil { 804 t.Fatalf("err: %v", err) 805 } 806 resp := fsm.Apply(makeLog(buf)) 807 if err, ok := resp.(error); ok { 808 t.Fatalf("resp: %v", err) 809 } 810 811 // Get the ACL. 812 id := resp.(string) 813 _, acl, err := fsm.state.ACLTokenGetBySecret(nil, id) 814 if err != nil { 815 t.Fatalf("err: %v", err) 816 } 817 if acl == nil { 818 t.Fatalf("missing") 819 } 820 821 // Verify the ACL. 822 if acl.SecretID != id { 823 t.Fatalf("bad: %v", *acl) 824 } 825 if acl.Description != "User token" { 826 t.Fatalf("bad: %v", *acl) 827 } 828 if acl.Type != structs.ACLTokenTypeClient { 829 t.Fatalf("bad: %v", *acl) 830 } 831 832 // Try to destroy. 833 destroy := structs.ACLRequest{ 834 Datacenter: "dc1", 835 Op: structs.ACLDelete, 836 ACL: structs.ACL{ 837 ID: id, 838 }, 839 } 840 buf, err = structs.Encode(structs.ACLRequestType, destroy) 841 if err != nil { 842 t.Fatalf("err: %v", err) 843 } 844 resp = fsm.Apply(makeLog(buf)) 845 if resp != nil { 846 t.Fatalf("resp: %v", resp) 847 } 848 849 _, acl, err = fsm.state.ACLTokenGetBySecret(nil, id) 850 if err != nil { 851 t.Fatalf("err: %v", err) 852 } 853 if acl != nil { 854 t.Fatalf("should be destroyed") 855 } 856 857 // Initialize bootstrap (should work since we haven't made a management 858 // token). 859 init := structs.ACLRequest{ 860 Datacenter: "dc1", 861 Op: structs.ACLBootstrapInit, 862 } 863 buf, err = structs.Encode(structs.ACLRequestType, init) 864 if err != nil { 865 t.Fatalf("err: %v", err) 866 } 867 resp = fsm.Apply(makeLog(buf)) 868 if enabled, ok := resp.(bool); !ok || !enabled { 869 t.Fatalf("resp: %v", resp) 870 } 871 canBootstrap, _, err := fsm.state.CanBootstrapACLToken() 872 if err != nil { 873 t.Fatalf("err: %v", err) 874 } 875 if !canBootstrap { 876 t.Fatalf("bad: shouldn't be able to bootstrap") 877 } 878 879 // Do a bootstrap. 880 bootstrap := structs.ACLRequest{ 881 Datacenter: "dc1", 882 Op: structs.ACLBootstrapNow, 883 ACL: structs.ACL{ 884 ID: generateUUID(), 885 Name: "Bootstrap Token", 886 Type: structs.ACLTokenTypeManagement, 887 }, 888 } 889 buf, err = structs.Encode(structs.ACLRequestType, bootstrap) 890 if err != nil { 891 t.Fatalf("err: %v", err) 892 } 893 resp = fsm.Apply(makeLog(buf)) 894 respACL, ok := resp.(*structs.ACL) 895 if !ok { 896 t.Fatalf("resp: %v", resp) 897 } 898 bootstrap.ACL.CreateIndex = respACL.CreateIndex 899 bootstrap.ACL.ModifyIndex = respACL.ModifyIndex 900 verify.Values(t, "", respACL, &bootstrap.ACL) 901 } 902 903 func TestFSM_PreparedQuery_CRUD(t *testing.T) { 904 t.Parallel() 905 fsm, err := New(nil, os.Stderr) 906 if err != nil { 907 t.Fatalf("err: %v", err) 908 } 909 910 // Register a service to query on. 911 fsm.state.EnsureNode(1, &structs.Node{Node: "foo", Address: "127.0.0.1"}) 912 fsm.state.EnsureService(2, "foo", &structs.NodeService{ID: "web", Service: "web", Tags: nil, Address: "127.0.0.1", Port: 80}) 913 914 // Create a new query. 915 query := structs.PreparedQueryRequest{ 916 Op: structs.PreparedQueryCreate, 917 Query: &structs.PreparedQuery{ 918 ID: generateUUID(), 919 Service: structs.ServiceQuery{ 920 Service: "web", 921 }, 922 }, 923 } 924 { 925 buf, err := structs.Encode(structs.PreparedQueryRequestType, query) 926 if err != nil { 927 t.Fatalf("err: %v", err) 928 } 929 resp := fsm.Apply(makeLog(buf)) 930 if resp != nil { 931 t.Fatalf("resp: %v", resp) 932 } 933 } 934 935 // Verify it's in the state store. 936 { 937 _, actual, err := fsm.state.PreparedQueryGet(nil, query.Query.ID) 938 if err != nil { 939 t.Fatalf("err: %s", err) 940 } 941 942 actual.CreateIndex, actual.ModifyIndex = 0, 0 943 if !reflect.DeepEqual(actual, query.Query) { 944 t.Fatalf("bad: %v", actual) 945 } 946 } 947 948 // Make an update to the query. 949 query.Op = structs.PreparedQueryUpdate 950 query.Query.Name = "my-query" 951 { 952 buf, err := structs.Encode(structs.PreparedQueryRequestType, query) 953 if err != nil { 954 t.Fatalf("err: %v", err) 955 } 956 resp := fsm.Apply(makeLog(buf)) 957 if resp != nil { 958 t.Fatalf("resp: %v", resp) 959 } 960 } 961 962 // Verify the update. 963 { 964 _, actual, err := fsm.state.PreparedQueryGet(nil, query.Query.ID) 965 if err != nil { 966 t.Fatalf("err: %s", err) 967 } 968 969 actual.CreateIndex, actual.ModifyIndex = 0, 0 970 if !reflect.DeepEqual(actual, query.Query) { 971 t.Fatalf("bad: %v", actual) 972 } 973 } 974 975 // Delete the query. 976 query.Op = structs.PreparedQueryDelete 977 { 978 buf, err := structs.Encode(structs.PreparedQueryRequestType, query) 979 if err != nil { 980 t.Fatalf("err: %v", err) 981 } 982 resp := fsm.Apply(makeLog(buf)) 983 if resp != nil { 984 t.Fatalf("resp: %v", resp) 985 } 986 } 987 988 // Make sure it's gone. 989 { 990 _, actual, err := fsm.state.PreparedQueryGet(nil, query.Query.ID) 991 if err != nil { 992 t.Fatalf("err: %s", err) 993 } 994 995 if actual != nil { 996 t.Fatalf("bad: %v", actual) 997 } 998 } 999 } 1000 1001 func TestFSM_TombstoneReap(t *testing.T) { 1002 t.Parallel() 1003 fsm, err := New(nil, os.Stderr) 1004 if err != nil { 1005 t.Fatalf("err: %v", err) 1006 } 1007 1008 // Create some tombstones 1009 fsm.state.KVSSet(11, &structs.DirEntry{ 1010 Key: "/remove", 1011 Value: []byte("foo"), 1012 }) 1013 fsm.state.KVSDelete(12, "/remove") 1014 idx, _, err := fsm.state.KVSList(nil, "/remove") 1015 if err != nil { 1016 t.Fatalf("err: %s", err) 1017 } 1018 if idx != 12 { 1019 t.Fatalf("bad index: %d", idx) 1020 } 1021 1022 // Create a new reap request 1023 req := structs.TombstoneRequest{ 1024 Datacenter: "dc1", 1025 Op: structs.TombstoneReap, 1026 ReapIndex: 12, 1027 } 1028 buf, err := structs.Encode(structs.TombstoneRequestType, req) 1029 if err != nil { 1030 t.Fatalf("err: %v", err) 1031 } 1032 resp := fsm.Apply(makeLog(buf)) 1033 if err, ok := resp.(error); ok { 1034 t.Fatalf("resp: %v", err) 1035 } 1036 1037 // Verify the tombstones are gone 1038 snap := fsm.state.Snapshot() 1039 defer snap.Close() 1040 stones, err := snap.Tombstones() 1041 if err != nil { 1042 t.Fatalf("err: %s", err) 1043 } 1044 if stones.Next() != nil { 1045 t.Fatalf("unexpected extra tombstones") 1046 } 1047 } 1048 1049 func TestFSM_Txn(t *testing.T) { 1050 t.Parallel() 1051 fsm, err := New(nil, os.Stderr) 1052 if err != nil { 1053 t.Fatalf("err: %v", err) 1054 } 1055 1056 // Set a key using a transaction. 1057 req := structs.TxnRequest{ 1058 Datacenter: "dc1", 1059 Ops: structs.TxnOps{ 1060 &structs.TxnOp{ 1061 KV: &structs.TxnKVOp{ 1062 Verb: api.KVSet, 1063 DirEnt: structs.DirEntry{ 1064 Key: "/test/path", 1065 Flags: 0, 1066 Value: []byte("test"), 1067 }, 1068 }, 1069 }, 1070 }, 1071 } 1072 buf, err := structs.Encode(structs.TxnRequestType, req) 1073 if err != nil { 1074 t.Fatalf("err: %v", err) 1075 } 1076 resp := fsm.Apply(makeLog(buf)) 1077 if _, ok := resp.(structs.TxnResponse); !ok { 1078 t.Fatalf("bad response type: %T", resp) 1079 } 1080 1081 // Verify key is set directly in the state store. 1082 _, d, err := fsm.state.KVSGet(nil, "/test/path") 1083 if err != nil { 1084 t.Fatalf("err: %v", err) 1085 } 1086 if d == nil { 1087 t.Fatalf("missing") 1088 } 1089 } 1090 1091 func TestFSM_Autopilot(t *testing.T) { 1092 t.Parallel() 1093 fsm, err := New(nil, os.Stderr) 1094 if err != nil { 1095 t.Fatalf("err: %v", err) 1096 } 1097 1098 // Set the autopilot config using a request. 1099 req := structs.AutopilotSetConfigRequest{ 1100 Datacenter: "dc1", 1101 Config: autopilot.Config{ 1102 CleanupDeadServers: true, 1103 LastContactThreshold: 10 * time.Second, 1104 MaxTrailingLogs: 300, 1105 }, 1106 } 1107 buf, err := structs.Encode(structs.AutopilotRequestType, req) 1108 if err != nil { 1109 t.Fatalf("err: %v", err) 1110 } 1111 resp := fsm.Apply(makeLog(buf)) 1112 if _, ok := resp.(error); ok { 1113 t.Fatalf("bad: %v", resp) 1114 } 1115 1116 // Verify key is set directly in the state store. 1117 _, config, err := fsm.state.AutopilotConfig() 1118 if err != nil { 1119 t.Fatalf("err: %v", err) 1120 } 1121 if config.CleanupDeadServers != req.Config.CleanupDeadServers { 1122 t.Fatalf("bad: %v", config.CleanupDeadServers) 1123 } 1124 if config.LastContactThreshold != req.Config.LastContactThreshold { 1125 t.Fatalf("bad: %v", config.LastContactThreshold) 1126 } 1127 if config.MaxTrailingLogs != req.Config.MaxTrailingLogs { 1128 t.Fatalf("bad: %v", config.MaxTrailingLogs) 1129 } 1130 1131 // Now use CAS and provide an old index 1132 req.CAS = true 1133 req.Config.CleanupDeadServers = false 1134 req.Config.ModifyIndex = config.ModifyIndex - 1 1135 buf, err = structs.Encode(structs.AutopilotRequestType, req) 1136 if err != nil { 1137 t.Fatalf("err: %v", err) 1138 } 1139 resp = fsm.Apply(makeLog(buf)) 1140 if _, ok := resp.(error); ok { 1141 t.Fatalf("bad: %v", resp) 1142 } 1143 1144 _, config, err = fsm.state.AutopilotConfig() 1145 if err != nil { 1146 t.Fatalf("err: %v", err) 1147 } 1148 if !config.CleanupDeadServers { 1149 t.Fatalf("bad: %v", config.CleanupDeadServers) 1150 } 1151 } 1152 1153 func TestFSM_Intention_CRUD(t *testing.T) { 1154 t.Parallel() 1155 1156 assert := assert.New(t) 1157 fsm, err := New(nil, os.Stderr) 1158 assert.Nil(err) 1159 1160 // Create a new intention. 1161 ixn := structs.IntentionRequest{ 1162 Datacenter: "dc1", 1163 Op: structs.IntentionOpCreate, 1164 Intention: structs.TestIntention(t), 1165 } 1166 ixn.Intention.ID = generateUUID() 1167 ixn.Intention.UpdatePrecedence() 1168 1169 { 1170 buf, err := structs.Encode(structs.IntentionRequestType, ixn) 1171 assert.Nil(err) 1172 assert.Nil(fsm.Apply(makeLog(buf))) 1173 } 1174 1175 // Verify it's in the state store. 1176 { 1177 _, actual, err := fsm.state.IntentionGet(nil, ixn.Intention.ID) 1178 assert.Nil(err) 1179 1180 actual.CreateIndex, actual.ModifyIndex = 0, 0 1181 actual.CreatedAt = ixn.Intention.CreatedAt 1182 actual.UpdatedAt = ixn.Intention.UpdatedAt 1183 assert.Equal(ixn.Intention, actual) 1184 } 1185 1186 // Make an update 1187 ixn.Op = structs.IntentionOpUpdate 1188 ixn.Intention.SourceName = "api" 1189 { 1190 buf, err := structs.Encode(structs.IntentionRequestType, ixn) 1191 assert.Nil(err) 1192 assert.Nil(fsm.Apply(makeLog(buf))) 1193 } 1194 1195 // Verify the update. 1196 { 1197 _, actual, err := fsm.state.IntentionGet(nil, ixn.Intention.ID) 1198 assert.Nil(err) 1199 1200 actual.CreateIndex, actual.ModifyIndex = 0, 0 1201 actual.CreatedAt = ixn.Intention.CreatedAt 1202 actual.UpdatedAt = ixn.Intention.UpdatedAt 1203 assert.Equal(ixn.Intention, actual) 1204 } 1205 1206 // Delete 1207 ixn.Op = structs.IntentionOpDelete 1208 { 1209 buf, err := structs.Encode(structs.IntentionRequestType, ixn) 1210 assert.Nil(err) 1211 assert.Nil(fsm.Apply(makeLog(buf))) 1212 } 1213 1214 // Make sure it's gone. 1215 { 1216 _, actual, err := fsm.state.IntentionGet(nil, ixn.Intention.ID) 1217 assert.Nil(err) 1218 assert.Nil(actual) 1219 } 1220 } 1221 1222 func TestFSM_CAConfig(t *testing.T) { 1223 t.Parallel() 1224 1225 assert := assert.New(t) 1226 fsm, err := New(nil, os.Stderr) 1227 assert.Nil(err) 1228 1229 // Set the autopilot config using a request. 1230 req := structs.CARequest{ 1231 Op: structs.CAOpSetConfig, 1232 Config: &structs.CAConfiguration{ 1233 Provider: "consul", 1234 Config: map[string]interface{}{ 1235 "PrivateKey": "asdf", 1236 "RootCert": "qwer", 1237 "RotationPeriod": 90 * 24 * time.Hour, 1238 }, 1239 }, 1240 } 1241 buf, err := structs.Encode(structs.ConnectCARequestType, req) 1242 assert.Nil(err) 1243 resp := fsm.Apply(makeLog(buf)) 1244 if _, ok := resp.(error); ok { 1245 t.Fatalf("bad: %v", resp) 1246 } 1247 1248 // Verify key is set directly in the state store. 1249 _, config, err := fsm.state.CAConfig() 1250 if err != nil { 1251 t.Fatalf("err: %v", err) 1252 } 1253 var conf *structs.ConsulCAProviderConfig 1254 if err := mapstructure.WeakDecode(config.Config, &conf); err != nil { 1255 t.Fatalf("error decoding config: %s, %v", err, config.Config) 1256 } 1257 if got, want := config.Provider, req.Config.Provider; got != want { 1258 t.Fatalf("got %v, want %v", got, want) 1259 } 1260 if got, want := conf.PrivateKey, "asdf"; got != want { 1261 t.Fatalf("got %v, want %v", got, want) 1262 } 1263 if got, want := conf.RootCert, "qwer"; got != want { 1264 t.Fatalf("got %v, want %v", got, want) 1265 } 1266 if got, want := conf.RotationPeriod, 90*24*time.Hour; got != want { 1267 t.Fatalf("got %v, want %v", got, want) 1268 } 1269 1270 // Now use CAS and provide an old index 1271 req.Config.Provider = "static" 1272 req.Config.ModifyIndex = config.ModifyIndex - 1 1273 buf, err = structs.Encode(structs.ConnectCARequestType, req) 1274 if err != nil { 1275 t.Fatalf("err: %v", err) 1276 } 1277 resp = fsm.Apply(makeLog(buf)) 1278 if _, ok := resp.(error); ok { 1279 t.Fatalf("bad: %v", resp) 1280 } 1281 1282 _, config, err = fsm.state.CAConfig() 1283 assert.Nil(err) 1284 if config.Provider != "static" { 1285 t.Fatalf("bad: %v", config.Provider) 1286 } 1287 } 1288 1289 func TestFSM_CARoots(t *testing.T) { 1290 t.Parallel() 1291 1292 assert := assert.New(t) 1293 fsm, err := New(nil, os.Stderr) 1294 assert.Nil(err) 1295 1296 // Roots 1297 ca1 := connect.TestCA(t, nil) 1298 ca2 := connect.TestCA(t, nil) 1299 ca2.Active = false 1300 1301 // Create a new request. 1302 req := structs.CARequest{ 1303 Op: structs.CAOpSetRoots, 1304 Roots: []*structs.CARoot{ca1, ca2}, 1305 } 1306 1307 { 1308 buf, err := structs.Encode(structs.ConnectCARequestType, req) 1309 assert.Nil(err) 1310 assert.True(fsm.Apply(makeLog(buf)).(bool)) 1311 } 1312 1313 // Verify it's in the state store. 1314 { 1315 _, roots, err := fsm.state.CARoots(nil) 1316 assert.Nil(err) 1317 assert.Len(roots, 2) 1318 } 1319 } 1320 1321 func TestFSM_CABuiltinProvider(t *testing.T) { 1322 t.Parallel() 1323 1324 assert := assert.New(t) 1325 fsm, err := New(nil, os.Stderr) 1326 assert.Nil(err) 1327 1328 // Provider state. 1329 expected := &structs.CAConsulProviderState{ 1330 ID: "foo", 1331 PrivateKey: "a", 1332 RootCert: "b", 1333 RaftIndex: structs.RaftIndex{ 1334 CreateIndex: 1, 1335 ModifyIndex: 1, 1336 }, 1337 } 1338 1339 // Create a new request. 1340 req := structs.CARequest{ 1341 Op: structs.CAOpSetProviderState, 1342 ProviderState: expected, 1343 } 1344 1345 { 1346 buf, err := structs.Encode(structs.ConnectCARequestType, req) 1347 assert.Nil(err) 1348 assert.True(fsm.Apply(makeLog(buf)).(bool)) 1349 } 1350 1351 // Verify it's in the state store. 1352 { 1353 _, state, err := fsm.state.CAProviderState("foo") 1354 assert.Nil(err) 1355 assert.Equal(expected, state) 1356 } 1357 }