github.imxd.top/hashicorp/consul@v1.4.5/agent/consul/kvs_endpoint_test.go (about) 1 package consul 2 3 import ( 4 "os" 5 "testing" 6 "time" 7 8 "github.com/hashicorp/consul/acl" 9 "github.com/hashicorp/consul/agent/structs" 10 "github.com/hashicorp/consul/api" 11 "github.com/hashicorp/consul/testrpc" 12 "github.com/hashicorp/net-rpc-msgpackrpc" 13 "github.com/pascaldekloe/goe/verify" 14 ) 15 16 func TestKVS_Apply(t *testing.T) { 17 t.Parallel() 18 dir1, s1 := testServer(t) 19 defer os.RemoveAll(dir1) 20 defer s1.Shutdown() 21 codec := rpcClient(t, s1) 22 defer codec.Close() 23 24 testrpc.WaitForLeader(t, s1.RPC, "dc1") 25 26 arg := structs.KVSRequest{ 27 Datacenter: "dc1", 28 Op: api.KVSet, 29 DirEnt: structs.DirEntry{ 30 Key: "test", 31 Flags: 42, 32 Value: []byte("test"), 33 }, 34 } 35 var out bool 36 if err := msgpackrpc.CallWithCodec(codec, "KVS.Apply", &arg, &out); err != nil { 37 t.Fatalf("err: %v", err) 38 } 39 40 // Verify 41 state := s1.fsm.State() 42 _, d, err := state.KVSGet(nil, "test") 43 if err != nil { 44 t.Fatalf("err: %v", err) 45 } 46 if d == nil { 47 t.Fatalf("should not be nil") 48 } 49 50 // Do a check and set 51 arg.Op = api.KVCAS 52 arg.DirEnt.ModifyIndex = d.ModifyIndex 53 arg.DirEnt.Flags = 43 54 if err := msgpackrpc.CallWithCodec(codec, "KVS.Apply", &arg, &out); err != nil { 55 t.Fatalf("err: %v", err) 56 } 57 58 // Check this was applied 59 if out != true { 60 t.Fatalf("bad: %v", out) 61 } 62 63 // Verify 64 _, d, err = state.KVSGet(nil, "test") 65 if err != nil { 66 t.Fatalf("err: %v", err) 67 } 68 if d.Flags != 43 { 69 t.Fatalf("bad: %v", d) 70 } 71 } 72 73 func TestKVS_Apply_ACLDeny(t *testing.T) { 74 t.Parallel() 75 dir1, s1 := testServerWithConfig(t, func(c *Config) { 76 c.ACLDatacenter = "dc1" 77 c.ACLsEnabled = true 78 c.ACLMasterToken = "root" 79 c.ACLDefaultPolicy = "deny" 80 }) 81 defer os.RemoveAll(dir1) 82 defer s1.Shutdown() 83 codec := rpcClient(t, s1) 84 defer codec.Close() 85 86 testrpc.WaitForLeader(t, s1.RPC, "dc1") 87 88 // Create the ACL 89 arg := structs.ACLRequest{ 90 Datacenter: "dc1", 91 Op: structs.ACLSet, 92 ACL: structs.ACL{ 93 Name: "User token", 94 Type: structs.ACLTokenTypeClient, 95 Rules: testListRules, 96 }, 97 WriteRequest: structs.WriteRequest{Token: "root"}, 98 } 99 var out string 100 if err := msgpackrpc.CallWithCodec(codec, "ACL.Apply", &arg, &out); err != nil { 101 t.Fatalf("err: %v", err) 102 } 103 id := out 104 105 // Try a write 106 argR := structs.KVSRequest{ 107 Datacenter: "dc1", 108 Op: api.KVSet, 109 DirEnt: structs.DirEntry{ 110 Key: "foo/bar", 111 Flags: 42, 112 Value: []byte("test"), 113 }, 114 WriteRequest: structs.WriteRequest{Token: id}, 115 } 116 var outR bool 117 err := msgpackrpc.CallWithCodec(codec, "KVS.Apply", &argR, &outR) 118 if !acl.IsErrPermissionDenied(err) { 119 t.Fatalf("err: %v", err) 120 } 121 122 // Try a recursive delete 123 argR = structs.KVSRequest{ 124 Datacenter: "dc1", 125 Op: api.KVDeleteTree, 126 DirEnt: structs.DirEntry{ 127 Key: "test", 128 }, 129 WriteRequest: structs.WriteRequest{Token: id}, 130 } 131 err = msgpackrpc.CallWithCodec(codec, "KVS.Apply", &argR, &outR) 132 if !acl.IsErrPermissionDenied(err) { 133 t.Fatalf("err: %v", err) 134 } 135 } 136 137 func TestKVS_Get(t *testing.T) { 138 t.Parallel() 139 dir1, s1 := testServer(t) 140 defer os.RemoveAll(dir1) 141 defer s1.Shutdown() 142 codec := rpcClient(t, s1) 143 defer codec.Close() 144 145 testrpc.WaitForLeader(t, s1.RPC, "dc1") 146 147 arg := structs.KVSRequest{ 148 Datacenter: "dc1", 149 Op: api.KVSet, 150 DirEnt: structs.DirEntry{ 151 Key: "test", 152 Flags: 42, 153 Value: []byte("test"), 154 }, 155 } 156 var out bool 157 if err := msgpackrpc.CallWithCodec(codec, "KVS.Apply", &arg, &out); err != nil { 158 t.Fatalf("err: %v", err) 159 } 160 161 getR := structs.KeyRequest{ 162 Datacenter: "dc1", 163 Key: "test", 164 } 165 var dirent structs.IndexedDirEntries 166 if err := msgpackrpc.CallWithCodec(codec, "KVS.Get", &getR, &dirent); err != nil { 167 t.Fatalf("err: %v", err) 168 } 169 170 if dirent.Index == 0 { 171 t.Fatalf("Bad: %v", dirent) 172 } 173 if len(dirent.Entries) != 1 { 174 t.Fatalf("Bad: %v", dirent) 175 } 176 d := dirent.Entries[0] 177 if d.Flags != 42 { 178 t.Fatalf("bad: %v", d) 179 } 180 if string(d.Value) != "test" { 181 t.Fatalf("bad: %v", d) 182 } 183 } 184 185 func TestKVS_Get_ACLDeny(t *testing.T) { 186 t.Parallel() 187 dir1, s1 := testServerWithConfig(t, func(c *Config) { 188 c.ACLDatacenter = "dc1" 189 c.ACLsEnabled = true 190 c.ACLMasterToken = "root" 191 c.ACLDefaultPolicy = "deny" 192 }) 193 defer os.RemoveAll(dir1) 194 defer s1.Shutdown() 195 codec := rpcClient(t, s1) 196 defer codec.Close() 197 198 testrpc.WaitForLeader(t, s1.RPC, "dc1") 199 200 arg := structs.KVSRequest{ 201 Datacenter: "dc1", 202 Op: api.KVSet, 203 DirEnt: structs.DirEntry{ 204 Key: "zip", 205 Flags: 42, 206 Value: []byte("test"), 207 }, 208 WriteRequest: structs.WriteRequest{Token: "root"}, 209 } 210 var out bool 211 if err := msgpackrpc.CallWithCodec(codec, "KVS.Apply", &arg, &out); err != nil { 212 t.Fatalf("err: %v", err) 213 } 214 215 getR := structs.KeyRequest{ 216 Datacenter: "dc1", 217 Key: "zip", 218 } 219 var dirent structs.IndexedDirEntries 220 if err := msgpackrpc.CallWithCodec(codec, "KVS.Get", &getR, &dirent); !acl.IsErrPermissionDenied(err) { 221 t.Fatalf("Expected %v, got err: %v", acl.ErrPermissionDenied, err) 222 } 223 224 } 225 226 func TestKVSEndpoint_List(t *testing.T) { 227 t.Parallel() 228 dir1, s1 := testServer(t) 229 defer os.RemoveAll(dir1) 230 defer s1.Shutdown() 231 codec := rpcClient(t, s1) 232 defer codec.Close() 233 234 testrpc.WaitForLeader(t, s1.RPC, "dc1") 235 236 keys := []string{ 237 "/test/key1", 238 "/test/key2", 239 "/test/sub/key3", 240 } 241 242 for _, key := range keys { 243 arg := structs.KVSRequest{ 244 Datacenter: "dc1", 245 Op: api.KVSet, 246 DirEnt: structs.DirEntry{ 247 Key: key, 248 Flags: 1, 249 }, 250 } 251 var out bool 252 if err := msgpackrpc.CallWithCodec(codec, "KVS.Apply", &arg, &out); err != nil { 253 t.Fatalf("err: %v", err) 254 } 255 } 256 257 getR := structs.KeyRequest{ 258 Datacenter: "dc1", 259 Key: "/test", 260 } 261 var dirent structs.IndexedDirEntries 262 if err := msgpackrpc.CallWithCodec(codec, "KVS.List", &getR, &dirent); err != nil { 263 t.Fatalf("err: %v", err) 264 } 265 266 if dirent.Index == 0 { 267 t.Fatalf("Bad: %v", dirent) 268 } 269 if len(dirent.Entries) != 3 { 270 t.Fatalf("Bad: %v", dirent.Entries) 271 } 272 for i := 0; i < len(dirent.Entries); i++ { 273 d := dirent.Entries[i] 274 if d.Key != keys[i] { 275 t.Fatalf("bad: %v", d) 276 } 277 if d.Flags != 1 { 278 t.Fatalf("bad: %v", d) 279 } 280 if d.Value != nil { 281 t.Fatalf("bad: %v", d) 282 } 283 } 284 285 // Try listing a nonexistent prefix 286 getR.Key = "/nope" 287 if err := msgpackrpc.CallWithCodec(codec, "KVS.List", &getR, &dirent); err != nil { 288 t.Fatalf("err: %v", err) 289 } 290 if dirent.Index == 0 { 291 t.Fatalf("Bad: %v", dirent) 292 } 293 if len(dirent.Entries) != 0 { 294 t.Fatalf("Bad: %v", dirent.Entries) 295 } 296 } 297 298 func TestKVSEndpoint_List_Blocking(t *testing.T) { 299 t.Parallel() 300 dir1, s1 := testServer(t) 301 defer os.RemoveAll(dir1) 302 defer s1.Shutdown() 303 codec := rpcClient(t, s1) 304 defer codec.Close() 305 306 testrpc.WaitForLeader(t, s1.RPC, "dc1") 307 308 keys := []string{ 309 "/test/key1", 310 "/test/key2", 311 "/test/sub/key3", 312 } 313 314 for _, key := range keys { 315 arg := structs.KVSRequest{ 316 Datacenter: "dc1", 317 Op: api.KVSet, 318 DirEnt: structs.DirEntry{ 319 Key: key, 320 Flags: 1, 321 }, 322 } 323 var out bool 324 if err := msgpackrpc.CallWithCodec(codec, "KVS.Apply", &arg, &out); err != nil { 325 t.Fatalf("err: %v", err) 326 } 327 } 328 329 getR := structs.KeyRequest{ 330 Datacenter: "dc1", 331 Key: "/test", 332 } 333 var dirent structs.IndexedDirEntries 334 if err := msgpackrpc.CallWithCodec(codec, "KVS.List", &getR, &dirent); err != nil { 335 t.Fatalf("err: %v", err) 336 } 337 338 // Setup a blocking query 339 getR.MinQueryIndex = dirent.Index 340 getR.MaxQueryTime = time.Second 341 342 // Async cause a change 343 start := time.Now() 344 go func() { 345 time.Sleep(100 * time.Millisecond) 346 codec := rpcClient(t, s1) 347 defer codec.Close() 348 arg := structs.KVSRequest{ 349 Datacenter: "dc1", 350 Op: api.KVDelete, 351 DirEnt: structs.DirEntry{ 352 Key: "/test/sub/key3", 353 }, 354 } 355 var out bool 356 if err := msgpackrpc.CallWithCodec(codec, "KVS.Apply", &arg, &out); err != nil { 357 t.Fatalf("err: %v", err) 358 } 359 }() 360 361 // Re-run the query 362 dirent = structs.IndexedDirEntries{} 363 if err := msgpackrpc.CallWithCodec(codec, "KVS.List", &getR, &dirent); err != nil { 364 t.Fatalf("err: %v", err) 365 } 366 367 // Should block at least 100ms 368 if time.Since(start) < 100*time.Millisecond { 369 t.Fatalf("too fast") 370 } 371 372 if dirent.Index == 0 { 373 t.Fatalf("Bad: %v", dirent) 374 } 375 if len(dirent.Entries) != 2 { 376 for _, ent := range dirent.Entries { 377 t.Errorf("Bad: %#v", *ent) 378 } 379 } 380 for i := 0; i < len(dirent.Entries); i++ { 381 d := dirent.Entries[i] 382 if d.Key != keys[i] { 383 t.Fatalf("bad: %v", d) 384 } 385 if d.Flags != 1 { 386 t.Fatalf("bad: %v", d) 387 } 388 if d.Value != nil { 389 t.Fatalf("bad: %v", d) 390 } 391 } 392 } 393 394 func TestKVSEndpoint_List_ACLDeny(t *testing.T) { 395 t.Parallel() 396 dir1, s1 := testServerWithConfig(t, func(c *Config) { 397 c.ACLDatacenter = "dc1" 398 c.ACLsEnabled = true 399 c.ACLMasterToken = "root" 400 c.ACLDefaultPolicy = "deny" 401 }) 402 defer os.RemoveAll(dir1) 403 defer s1.Shutdown() 404 codec := rpcClient(t, s1) 405 defer codec.Close() 406 407 testrpc.WaitForLeader(t, s1.RPC, "dc1") 408 409 keys := []string{ 410 "abe", 411 "bar", 412 "foo", 413 "test", 414 "zip", 415 } 416 417 for _, key := range keys { 418 arg := structs.KVSRequest{ 419 Datacenter: "dc1", 420 Op: api.KVSet, 421 DirEnt: structs.DirEntry{ 422 Key: key, 423 Flags: 1, 424 }, 425 WriteRequest: structs.WriteRequest{Token: "root"}, 426 } 427 var out bool 428 if err := msgpackrpc.CallWithCodec(codec, "KVS.Apply", &arg, &out); err != nil { 429 t.Fatalf("err: %v", err) 430 } 431 } 432 433 arg := structs.ACLRequest{ 434 Datacenter: "dc1", 435 Op: structs.ACLSet, 436 ACL: structs.ACL{ 437 Name: "User token", 438 Type: structs.ACLTokenTypeClient, 439 Rules: testListRules, 440 }, 441 WriteRequest: structs.WriteRequest{Token: "root"}, 442 } 443 var out string 444 if err := msgpackrpc.CallWithCodec(codec, "ACL.Apply", &arg, &out); err != nil { 445 t.Fatalf("err: %v", err) 446 } 447 id := out 448 449 getR := structs.KeyRequest{ 450 Datacenter: "dc1", 451 Key: "", 452 QueryOptions: structs.QueryOptions{Token: id}, 453 } 454 var dirent structs.IndexedDirEntries 455 if err := msgpackrpc.CallWithCodec(codec, "KVS.List", &getR, &dirent); err != nil { 456 t.Fatalf("err: %v", err) 457 } 458 459 if dirent.Index == 0 { 460 t.Fatalf("Bad: %v", dirent) 461 } 462 if len(dirent.Entries) != 2 { 463 t.Fatalf("Bad: %v", dirent.Entries) 464 } 465 for i := 0; i < len(dirent.Entries); i++ { 466 d := dirent.Entries[i] 467 switch i { 468 case 0: 469 if d.Key != "foo" { 470 t.Fatalf("bad key") 471 } 472 case 1: 473 if d.Key != "test" { 474 t.Fatalf("bad key") 475 } 476 } 477 } 478 } 479 480 func TestKVSEndpoint_List_ACLEnableKeyListPolicy(t *testing.T) { 481 t.Parallel() 482 dir1, s1 := testServerWithConfig(t, func(c *Config) { 483 c.ACLDatacenter = "dc1" 484 c.ACLsEnabled = true 485 c.ACLMasterToken = "root" 486 c.ACLDefaultPolicy = "deny" 487 c.ACLEnableKeyListPolicy = true 488 }) 489 defer os.RemoveAll(dir1) 490 defer s1.Shutdown() 491 codec := rpcClient(t, s1) 492 defer codec.Close() 493 494 testrpc.WaitForLeader(t, s1.RPC, "dc1") 495 496 keys := []string{ 497 "abe", 498 "bar/bar1", 499 "bar/bar2", 500 "zip", 501 } 502 503 for _, key := range keys { 504 arg := structs.KVSRequest{ 505 Datacenter: "dc1", 506 Op: api.KVSet, 507 DirEnt: structs.DirEntry{ 508 Key: key, 509 Flags: 1, 510 }, 511 WriteRequest: structs.WriteRequest{Token: "root"}, 512 } 513 var out bool 514 if err := msgpackrpc.CallWithCodec(codec, "KVS.Apply", &arg, &out); err != nil { 515 t.Fatalf("err: %v", err) 516 } 517 } 518 519 //write acl policy that denies recursive reads on "" 520 var testListRules1 = ` 521 key "" { 522 policy = "deny" 523 } 524 key "bar" { 525 policy = "list" 526 } 527 key "zip" { 528 policy = "read" 529 } 530 ` 531 532 arg := structs.ACLRequest{ 533 Datacenter: "dc1", 534 Op: structs.ACLSet, 535 ACL: structs.ACL{ 536 Name: "User token", 537 Type: structs.ACLTokenTypeClient, 538 Rules: testListRules1, 539 }, 540 WriteRequest: structs.WriteRequest{Token: "root"}, 541 } 542 var out string 543 if err := msgpackrpc.CallWithCodec(codec, "ACL.Apply", &arg, &out); err != nil { 544 t.Fatalf("err: %v", err) 545 } 546 id := out 547 548 //recursive read on empty prefix should fail 549 getReq := structs.KeyRequest{ 550 Datacenter: "dc1", 551 Key: "", 552 QueryOptions: structs.QueryOptions{Token: id}, 553 } 554 var dirent structs.IndexedDirEntries 555 if err := msgpackrpc.CallWithCodec(codec, "KVS.List", &getReq, &dirent); !acl.IsErrPermissionDenied(err) { 556 t.Fatalf("expected %v but got err: %v", acl.ErrPermissionDenied, err) 557 } 558 559 //listing keys on empty prefix should fail 560 getKeysReq := structs.KeyListRequest{ 561 Datacenter: "dc1", 562 Prefix: "", 563 Seperator: "/", 564 QueryOptions: structs.QueryOptions{Token: id}, 565 } 566 var keyList structs.IndexedKeyList 567 if err := msgpackrpc.CallWithCodec(codec, "KVS.ListKeys", &getKeysReq, &keyList); !acl.IsErrPermissionDenied(err) { 568 t.Fatalf("expected %v but got err: %v", acl.ErrPermissionDenied, err) 569 } 570 571 // recursive read with a prefix that has list permissions should succeed 572 getReq2 := structs.KeyRequest{ 573 Datacenter: "dc1", 574 Key: "bar", 575 QueryOptions: structs.QueryOptions{Token: id}, 576 } 577 if err := msgpackrpc.CallWithCodec(codec, "KVS.List", &getReq2, &dirent); err != nil { 578 t.Fatalf("err: %v", err) 579 } 580 581 expectedKeys := []string{"bar/bar1", "bar/bar2"} 582 var actualKeys []string 583 for _, entry := range dirent.Entries { 584 actualKeys = append(actualKeys, entry.Key) 585 } 586 587 verify.Values(t, "", actualKeys, expectedKeys) 588 589 // list keys with a prefix that has list permissions should succeed 590 getKeysReq2 := structs.KeyListRequest{ 591 Datacenter: "dc1", 592 Prefix: "bar", 593 QueryOptions: structs.QueryOptions{Token: id}, 594 } 595 if err := msgpackrpc.CallWithCodec(codec, "KVS.ListKeys", &getKeysReq2, &keyList); err != nil { 596 t.Fatalf("err: %v", err) 597 } 598 599 actualKeys = []string{} 600 601 for _, key := range keyList.Keys { 602 actualKeys = append(actualKeys, key) 603 } 604 605 verify.Values(t, "", actualKeys, expectedKeys) 606 607 } 608 609 func TestKVSEndpoint_ListKeys(t *testing.T) { 610 t.Parallel() 611 dir1, s1 := testServer(t) 612 defer os.RemoveAll(dir1) 613 defer s1.Shutdown() 614 codec := rpcClient(t, s1) 615 defer codec.Close() 616 617 testrpc.WaitForLeader(t, s1.RPC, "dc1") 618 619 keys := []string{ 620 "/test/key1", 621 "/test/key2", 622 "/test/sub/key3", 623 } 624 625 for _, key := range keys { 626 arg := structs.KVSRequest{ 627 Datacenter: "dc1", 628 Op: api.KVSet, 629 DirEnt: structs.DirEntry{ 630 Key: key, 631 Flags: 1, 632 }, 633 } 634 var out bool 635 if err := msgpackrpc.CallWithCodec(codec, "KVS.Apply", &arg, &out); err != nil { 636 t.Fatalf("err: %v", err) 637 } 638 } 639 640 getR := structs.KeyListRequest{ 641 Datacenter: "dc1", 642 Prefix: "/test/", 643 Seperator: "/", 644 } 645 var dirent structs.IndexedKeyList 646 if err := msgpackrpc.CallWithCodec(codec, "KVS.ListKeys", &getR, &dirent); err != nil { 647 t.Fatalf("err: %v", err) 648 } 649 650 if dirent.Index == 0 { 651 t.Fatalf("Bad: %v", dirent) 652 } 653 if len(dirent.Keys) != 3 { 654 t.Fatalf("Bad: %v", dirent.Keys) 655 } 656 if dirent.Keys[0] != "/test/key1" { 657 t.Fatalf("Bad: %v", dirent.Keys) 658 } 659 if dirent.Keys[1] != "/test/key2" { 660 t.Fatalf("Bad: %v", dirent.Keys) 661 } 662 if dirent.Keys[2] != "/test/sub/" { 663 t.Fatalf("Bad: %v", dirent.Keys) 664 } 665 666 // Try listing a nonexistent prefix 667 getR.Prefix = "/nope" 668 if err := msgpackrpc.CallWithCodec(codec, "KVS.ListKeys", &getR, &dirent); err != nil { 669 t.Fatalf("err: %v", err) 670 } 671 if dirent.Index == 0 { 672 t.Fatalf("Bad: %v", dirent) 673 } 674 if len(dirent.Keys) != 0 { 675 t.Fatalf("Bad: %v", dirent.Keys) 676 } 677 } 678 679 func TestKVSEndpoint_ListKeys_ACLDeny(t *testing.T) { 680 t.Parallel() 681 dir1, s1 := testServerWithConfig(t, func(c *Config) { 682 c.ACLDatacenter = "dc1" 683 c.ACLsEnabled = true 684 c.ACLMasterToken = "root" 685 c.ACLDefaultPolicy = "deny" 686 }) 687 defer os.RemoveAll(dir1) 688 defer s1.Shutdown() 689 codec := rpcClient(t, s1) 690 defer codec.Close() 691 692 testrpc.WaitForLeader(t, s1.RPC, "dc1") 693 694 keys := []string{ 695 "abe", 696 "bar", 697 "foo", 698 "test", 699 "zip", 700 } 701 702 for _, key := range keys { 703 arg := structs.KVSRequest{ 704 Datacenter: "dc1", 705 Op: api.KVSet, 706 DirEnt: structs.DirEntry{ 707 Key: key, 708 Flags: 1, 709 }, 710 WriteRequest: structs.WriteRequest{Token: "root"}, 711 } 712 var out bool 713 if err := msgpackrpc.CallWithCodec(codec, "KVS.Apply", &arg, &out); err != nil { 714 t.Fatalf("err: %v", err) 715 } 716 } 717 718 arg := structs.ACLRequest{ 719 Datacenter: "dc1", 720 Op: structs.ACLSet, 721 ACL: structs.ACL{ 722 Name: "User token", 723 Type: structs.ACLTokenTypeClient, 724 Rules: testListRules, 725 }, 726 WriteRequest: structs.WriteRequest{Token: "root"}, 727 } 728 var out string 729 if err := msgpackrpc.CallWithCodec(codec, "ACL.Apply", &arg, &out); err != nil { 730 t.Fatalf("err: %v", err) 731 } 732 id := out 733 734 getR := structs.KeyListRequest{ 735 Datacenter: "dc1", 736 Prefix: "", 737 Seperator: "/", 738 QueryOptions: structs.QueryOptions{Token: id}, 739 } 740 var dirent structs.IndexedKeyList 741 if err := msgpackrpc.CallWithCodec(codec, "KVS.ListKeys", &getR, &dirent); err != nil { 742 t.Fatalf("err: %v", err) 743 } 744 745 if dirent.Index == 0 { 746 t.Fatalf("Bad: %v", dirent) 747 } 748 if len(dirent.Keys) != 2 { 749 t.Fatalf("Bad: %v", dirent.Keys) 750 } 751 if dirent.Keys[0] != "foo" { 752 t.Fatalf("Bad: %v", dirent.Keys) 753 } 754 if dirent.Keys[1] != "test" { 755 t.Fatalf("Bad: %v", dirent.Keys) 756 } 757 } 758 759 func TestKVS_Apply_LockDelay(t *testing.T) { 760 t.Parallel() 761 dir1, s1 := testServer(t) 762 defer os.RemoveAll(dir1) 763 defer s1.Shutdown() 764 codec := rpcClient(t, s1) 765 defer codec.Close() 766 767 testrpc.WaitForLeader(t, s1.RPC, "dc1") 768 769 // Create and invalidate a session with a lock. 770 state := s1.fsm.State() 771 if err := state.EnsureNode(1, &structs.Node{Node: "foo", Address: "127.0.0.1"}); err != nil { 772 t.Fatalf("err: %v", err) 773 } 774 session := &structs.Session{ 775 ID: generateUUID(), 776 Node: "foo", 777 LockDelay: 50 * time.Millisecond, 778 } 779 if err := state.SessionCreate(2, session); err != nil { 780 t.Fatalf("err: %v", err) 781 } 782 id := session.ID 783 d := &structs.DirEntry{ 784 Key: "test", 785 Session: id, 786 } 787 if ok, err := state.KVSLock(3, d); err != nil || !ok { 788 t.Fatalf("err: %v", err) 789 } 790 if err := state.SessionDestroy(4, id); err != nil { 791 t.Fatalf("err: %v", err) 792 } 793 794 // Make a new session that is valid. 795 if err := state.SessionCreate(5, session); err != nil { 796 t.Fatalf("err: %v", err) 797 } 798 validID := session.ID 799 800 // Make a lock request. 801 arg := structs.KVSRequest{ 802 Datacenter: "dc1", 803 Op: api.KVLock, 804 DirEnt: structs.DirEntry{ 805 Key: "test", 806 Session: validID, 807 }, 808 } 809 var out bool 810 if err := msgpackrpc.CallWithCodec(codec, "KVS.Apply", &arg, &out); err != nil { 811 t.Fatalf("err: %v", err) 812 } 813 if out != false { 814 t.Fatalf("should not acquire") 815 } 816 817 // Wait for lock-delay. 818 time.Sleep(50 * time.Millisecond) 819 820 // Should acquire. 821 if err := msgpackrpc.CallWithCodec(codec, "KVS.Apply", &arg, &out); err != nil { 822 t.Fatalf("err: %v", err) 823 } 824 if out != true { 825 t.Fatalf("should acquire") 826 } 827 } 828 829 func TestKVS_Issue_1626(t *testing.T) { 830 t.Parallel() 831 dir1, s1 := testServer(t) 832 defer os.RemoveAll(dir1) 833 defer s1.Shutdown() 834 codec := rpcClient(t, s1) 835 defer codec.Close() 836 837 testrpc.WaitForLeader(t, s1.RPC, "dc1") 838 839 // Set up the first key. 840 { 841 arg := structs.KVSRequest{ 842 Datacenter: "dc1", 843 Op: api.KVSet, 844 DirEnt: structs.DirEntry{ 845 Key: "foo/test", 846 Value: []byte("test"), 847 }, 848 } 849 var out bool 850 if err := msgpackrpc.CallWithCodec(codec, "KVS.Apply", &arg, &out); err != nil { 851 t.Fatalf("err: %v", err) 852 } 853 } 854 855 // Retrieve the base key and snag the index. 856 var index uint64 857 { 858 getR := structs.KeyRequest{ 859 Datacenter: "dc1", 860 Key: "foo/test", 861 } 862 var dirent structs.IndexedDirEntries 863 if err := msgpackrpc.CallWithCodec(codec, "KVS.Get", &getR, &dirent); err != nil { 864 t.Fatalf("err: %v", err) 865 } 866 if dirent.Index == 0 { 867 t.Fatalf("Bad: %v", dirent) 868 } 869 if len(dirent.Entries) != 1 { 870 t.Fatalf("Bad: %v", dirent) 871 } 872 d := dirent.Entries[0] 873 if string(d.Value) != "test" { 874 t.Fatalf("bad: %v", d) 875 } 876 877 index = dirent.Index 878 } 879 880 // Set up a blocking query on the base key. 881 doneCh := make(chan *structs.IndexedDirEntries, 1) 882 go func() { 883 codec := rpcClient(t, s1) 884 defer codec.Close() 885 886 getR := structs.KeyRequest{ 887 Datacenter: "dc1", 888 Key: "foo/test", 889 QueryOptions: structs.QueryOptions{ 890 MinQueryIndex: index, 891 MaxQueryTime: 3 * time.Second, 892 }, 893 } 894 var dirent structs.IndexedDirEntries 895 if err := msgpackrpc.CallWithCodec(codec, "KVS.Get", &getR, &dirent); err != nil { 896 t.Fatalf("err: %v", err) 897 } 898 doneCh <- &dirent 899 }() 900 901 // Now update a second key with a prefix that has the first key name 902 // as part of it. 903 { 904 arg := structs.KVSRequest{ 905 Datacenter: "dc1", 906 Op: api.KVSet, 907 DirEnt: structs.DirEntry{ 908 Key: "foo/test2", 909 Value: []byte("test"), 910 }, 911 } 912 var out bool 913 if err := msgpackrpc.CallWithCodec(codec, "KVS.Apply", &arg, &out); err != nil { 914 t.Fatalf("err: %v", err) 915 } 916 } 917 918 // Make sure the blocking query didn't wake up for this update. 919 select { 920 case <-doneCh: 921 t.Fatalf("Blocking query should not have completed") 922 case <-time.After(1 * time.Second): 923 } 924 925 // Now update the first key's payload. 926 { 927 arg := structs.KVSRequest{ 928 Datacenter: "dc1", 929 Op: api.KVSet, 930 DirEnt: structs.DirEntry{ 931 Key: "foo/test", 932 Value: []byte("updated"), 933 }, 934 } 935 var out bool 936 if err := msgpackrpc.CallWithCodec(codec, "KVS.Apply", &arg, &out); err != nil { 937 t.Fatalf("err: %v", err) 938 } 939 } 940 941 // Make sure the blocking query wakes up for the final update. 942 select { 943 case dirent := <-doneCh: 944 if dirent.Index <= index { 945 t.Fatalf("Bad: %v", dirent) 946 } 947 if len(dirent.Entries) != 1 { 948 t.Fatalf("Bad: %v", dirent) 949 } 950 d := dirent.Entries[0] 951 if string(d.Value) != "updated" { 952 t.Fatalf("bad: %v", d) 953 } 954 case <-time.After(1 * time.Second): 955 t.Fatalf("Blocking query should have completed") 956 } 957 } 958 959 var testListRules = ` 960 key "" { 961 policy = "deny" 962 } 963 key "foo" { 964 policy = "read" 965 } 966 key "test" { 967 policy = "write" 968 } 969 key "test/priv" { 970 policy = "read" 971 } 972 `