github.imxd.top/hashicorp/consul@v1.4.5/agent/consul/catalog_endpoint_test.go (about) 1 package consul 2 3 import ( 4 "fmt" 5 "net/rpc" 6 "os" 7 "strings" 8 "testing" 9 "time" 10 11 "github.com/hashicorp/consul/acl" 12 "github.com/hashicorp/consul/agent/structs" 13 "github.com/hashicorp/consul/api" 14 "github.com/hashicorp/consul/lib" 15 "github.com/hashicorp/consul/testrpc" 16 "github.com/hashicorp/consul/testutil/retry" 17 "github.com/hashicorp/consul/types" 18 "github.com/hashicorp/net-rpc-msgpackrpc" 19 "github.com/stretchr/testify/assert" 20 "github.com/stretchr/testify/require" 21 ) 22 23 func TestCatalog_Register(t *testing.T) { 24 t.Parallel() 25 dir1, s1 := testServer(t) 26 defer os.RemoveAll(dir1) 27 defer s1.Shutdown() 28 codec := rpcClient(t, s1) 29 defer codec.Close() 30 31 arg := structs.RegisterRequest{ 32 Datacenter: "dc1", 33 Node: "foo", 34 Address: "127.0.0.1", 35 Service: &structs.NodeService{ 36 Service: "db", 37 Tags: []string{"master"}, 38 Port: 8000, 39 }, 40 Check: &structs.HealthCheck{ 41 CheckID: types.CheckID("db-check"), 42 ServiceID: "db", 43 }, 44 } 45 var out struct{} 46 47 err := msgpackrpc.CallWithCodec(codec, "Catalog.Register", &arg, &out) 48 if err != nil { 49 t.Fatalf("err: %v", err) 50 } 51 } 52 53 func TestCatalog_RegisterService_InvalidAddress(t *testing.T) { 54 t.Parallel() 55 dir1, s1 := testServer(t) 56 defer os.RemoveAll(dir1) 57 defer s1.Shutdown() 58 codec := rpcClient(t, s1) 59 defer codec.Close() 60 61 for _, addr := range []string{"0.0.0.0", "::", "[::]"} { 62 t.Run("addr "+addr, func(t *testing.T) { 63 arg := structs.RegisterRequest{ 64 Datacenter: "dc1", 65 Node: "foo", 66 Address: "127.0.0.1", 67 Service: &structs.NodeService{ 68 Service: "db", 69 Address: addr, 70 Port: 8000, 71 }, 72 } 73 var out struct{} 74 75 err := msgpackrpc.CallWithCodec(codec, "Catalog.Register", &arg, &out) 76 if err == nil || err.Error() != "Invalid service address" { 77 t.Fatalf("got error %v want 'Invalid service address'", err) 78 } 79 }) 80 } 81 } 82 83 func TestCatalog_RegisterService_SkipNodeUpdate(t *testing.T) { 84 t.Parallel() 85 dir1, s1 := testServer(t) 86 defer os.RemoveAll(dir1) 87 defer s1.Shutdown() 88 codec := rpcClient(t, s1) 89 defer codec.Close() 90 91 // Register a node 92 arg := structs.RegisterRequest{ 93 Datacenter: "dc1", 94 Node: "foo", 95 Address: "127.0.0.1", 96 } 97 var out struct{} 98 err := msgpackrpc.CallWithCodec(codec, "Catalog.Register", &arg, &out) 99 if err != nil { 100 t.Fatal(err) 101 } 102 103 // Update it with a blank address, should fail. 104 arg.Address = "" 105 arg.Service = &structs.NodeService{ 106 Service: "db", 107 Port: 8000, 108 } 109 err = msgpackrpc.CallWithCodec(codec, "Catalog.Register", &arg, &out) 110 if err == nil || err.Error() != "Must provide address if SkipNodeUpdate is not set" { 111 t.Fatalf("got error %v want 'Must provide address...'", err) 112 } 113 114 // Set SkipNodeUpdate, should succeed 115 arg.SkipNodeUpdate = true 116 err = msgpackrpc.CallWithCodec(codec, "Catalog.Register", &arg, &out) 117 if err != nil { 118 t.Fatal(err) 119 } 120 } 121 122 func TestCatalog_Register_NodeID(t *testing.T) { 123 t.Parallel() 124 dir1, s1 := testServer(t) 125 defer os.RemoveAll(dir1) 126 defer s1.Shutdown() 127 codec := rpcClient(t, s1) 128 defer codec.Close() 129 130 arg := structs.RegisterRequest{ 131 Datacenter: "dc1", 132 ID: "nope", 133 Node: "foo", 134 Address: "127.0.0.1", 135 Service: &structs.NodeService{ 136 Service: "db", 137 Tags: []string{"master"}, 138 Port: 8000, 139 }, 140 Check: &structs.HealthCheck{ 141 CheckID: types.CheckID("db-check"), 142 ServiceID: "db", 143 }, 144 } 145 var out struct{} 146 147 err := msgpackrpc.CallWithCodec(codec, "Catalog.Register", &arg, &out) 148 if err == nil || !strings.Contains(err.Error(), "Bad node ID") { 149 t.Fatalf("err: %v", err) 150 } 151 152 arg.ID = types.NodeID("adf4238a-882b-9ddc-4a9d-5b6758e4159e") 153 if err := msgpackrpc.CallWithCodec(codec, "Catalog.Register", &arg, &out); err != nil { 154 t.Fatalf("err: %v", err) 155 } 156 } 157 158 func TestCatalog_Register_ACLDeny(t *testing.T) { 159 t.Parallel() 160 dir1, s1 := testServerWithConfig(t, func(c *Config) { 161 c.ACLDatacenter = "dc1" 162 c.ACLsEnabled = true 163 c.ACLMasterToken = "root" 164 c.ACLDefaultPolicy = "deny" 165 c.ACLEnforceVersion8 = false 166 }) 167 defer os.RemoveAll(dir1) 168 defer s1.Shutdown() 169 testrpc.WaitForTestAgent(t, s1.RPC, "dc1") 170 codec := rpcClient(t, s1) 171 defer codec.Close() 172 173 // Create the ACL. 174 arg := structs.ACLRequest{ 175 Datacenter: "dc1", 176 Op: structs.ACLSet, 177 ACL: structs.ACL{ 178 Name: "User token", 179 Type: structs.ACLTokenTypeClient, 180 Rules: ` 181 service "foo" { 182 policy = "write" 183 } 184 `, 185 }, 186 WriteRequest: structs.WriteRequest{Token: "root"}, 187 } 188 var id string 189 if err := msgpackrpc.CallWithCodec(codec, "ACL.Apply", &arg, &id); err != nil { 190 t.Fatalf("err: %v", err) 191 } 192 193 argR := structs.RegisterRequest{ 194 Datacenter: "dc1", 195 Node: "foo", 196 Address: "127.0.0.1", 197 Service: &structs.NodeService{ 198 Service: "db", 199 Tags: []string{"master"}, 200 Port: 8000, 201 }, 202 WriteRequest: structs.WriteRequest{Token: id}, 203 } 204 var outR struct{} 205 206 // This should fail since we are writing to the "db" service, which isn't 207 // allowed. 208 err := msgpackrpc.CallWithCodec(codec, "Catalog.Register", &argR, &outR) 209 if !acl.IsErrPermissionDenied(err) { 210 t.Fatalf("err: %v", err) 211 } 212 213 // The "foo" service should work, though. 214 argR.Service.Service = "foo" 215 err = msgpackrpc.CallWithCodec(codec, "Catalog.Register", &argR, &outR) 216 if err != nil { 217 t.Fatalf("err: %v", err) 218 } 219 220 // Try the special case for the "consul" service that allows it no matter 221 // what with pre-version 8 ACL enforcement. 222 argR.Service.Service = "consul" 223 err = msgpackrpc.CallWithCodec(codec, "Catalog.Register", &argR, &outR) 224 if err != nil { 225 t.Fatalf("err: %v", err) 226 } 227 228 // Make sure the exception goes away when we turn on version 8 ACL 229 // enforcement. 230 s1.config.ACLEnforceVersion8 = true 231 err = msgpackrpc.CallWithCodec(codec, "Catalog.Register", &argR, &outR) 232 if !acl.IsErrPermissionDenied(err) { 233 t.Fatalf("err: %v", err) 234 } 235 236 // Register a db service using the root token. 237 argR.Service.Service = "db" 238 argR.Service.ID = "my-id" 239 argR.Token = "root" 240 err = msgpackrpc.CallWithCodec(codec, "Catalog.Register", &argR, &outR) 241 if err != nil { 242 t.Fatalf("err: %v", err) 243 } 244 245 // Prove that we are properly looking up the node services and passing 246 // that to the ACL helper. We can vet the helper independently in its 247 // own unit test after this. This is trying to register over the db 248 // service we created above, which is a check that depends on looking 249 // at the existing registration data with that service ID. This is a new 250 // check for version 8. 251 argR.Service.Service = "foo" 252 argR.Service.ID = "my-id" 253 argR.Token = id 254 err = msgpackrpc.CallWithCodec(codec, "Catalog.Register", &argR, &outR) 255 if !acl.IsErrPermissionDenied(err) { 256 t.Fatalf("err: %v", err) 257 } 258 } 259 260 func TestCatalog_Register_ForwardLeader(t *testing.T) { 261 t.Parallel() 262 dir1, s1 := testServer(t) 263 defer os.RemoveAll(dir1) 264 defer s1.Shutdown() 265 codec1 := rpcClient(t, s1) 266 defer codec1.Close() 267 268 dir2, s2 := testServer(t) 269 defer os.RemoveAll(dir2) 270 defer s2.Shutdown() 271 codec2 := rpcClient(t, s2) 272 defer codec2.Close() 273 274 // Try to join 275 joinLAN(t, s2, s1) 276 277 testrpc.WaitForLeader(t, s1.RPC, "dc1") 278 testrpc.WaitForLeader(t, s2.RPC, "dc1") 279 280 // Use the follower as the client 281 var codec rpc.ClientCodec 282 if !s1.IsLeader() { 283 codec = codec1 284 } else { 285 codec = codec2 286 } 287 288 arg := structs.RegisterRequest{ 289 Datacenter: "dc1", 290 Node: "foo", 291 Address: "127.0.0.1", 292 Service: &structs.NodeService{ 293 Service: "db", 294 Tags: []string{"master"}, 295 Port: 8000, 296 }, 297 } 298 var out struct{} 299 if err := msgpackrpc.CallWithCodec(codec, "Catalog.Register", &arg, &out); err != nil { 300 t.Fatalf("err: %v", err) 301 } 302 } 303 304 func TestCatalog_Register_ForwardDC(t *testing.T) { 305 t.Parallel() 306 dir1, s1 := testServer(t) 307 defer os.RemoveAll(dir1) 308 defer s1.Shutdown() 309 codec := rpcClient(t, s1) 310 defer codec.Close() 311 312 dir2, s2 := testServerDC(t, "dc2") 313 defer os.RemoveAll(dir2) 314 defer s2.Shutdown() 315 316 // Try to join 317 joinWAN(t, s2, s1) 318 319 testrpc.WaitForLeader(t, s1.RPC, "dc2") 320 321 arg := structs.RegisterRequest{ 322 Datacenter: "dc2", // Should forward through s1 323 Node: "foo", 324 Address: "127.0.0.1", 325 Service: &structs.NodeService{ 326 Service: "db", 327 Tags: []string{"master"}, 328 Port: 8000, 329 }, 330 } 331 var out struct{} 332 if err := msgpackrpc.CallWithCodec(codec, "Catalog.Register", &arg, &out); err != nil { 333 t.Fatalf("err: %v", err) 334 } 335 } 336 337 func TestCatalog_Register_ConnectProxy(t *testing.T) { 338 t.Parallel() 339 340 assert := assert.New(t) 341 dir1, s1 := testServer(t) 342 defer os.RemoveAll(dir1) 343 defer s1.Shutdown() 344 codec := rpcClient(t, s1) 345 defer codec.Close() 346 347 args := structs.TestRegisterRequestProxy(t) 348 349 // Register 350 var out struct{} 351 assert.Nil(msgpackrpc.CallWithCodec(codec, "Catalog.Register", &args, &out)) 352 353 // List 354 req := structs.ServiceSpecificRequest{ 355 Datacenter: "dc1", 356 ServiceName: args.Service.Service, 357 } 358 var resp structs.IndexedServiceNodes 359 assert.Nil(msgpackrpc.CallWithCodec(codec, "Catalog.ServiceNodes", &req, &resp)) 360 assert.Len(resp.ServiceNodes, 1) 361 v := resp.ServiceNodes[0] 362 assert.Equal(structs.ServiceKindConnectProxy, v.ServiceKind) 363 assert.Equal(args.Service.Proxy.DestinationServiceName, v.ServiceProxy.DestinationServiceName) 364 } 365 366 // DEPRECATED (ProxyDestination) - remove this whole test case when removing 367 // ProxyDestination 368 func TestCatalog_Register_DeprecatedConnectProxy(t *testing.T) { 369 t.Parallel() 370 371 assert := assert.New(t) 372 dir1, s1 := testServer(t) 373 defer os.RemoveAll(dir1) 374 defer s1.Shutdown() 375 codec := rpcClient(t, s1) 376 defer codec.Close() 377 378 args := structs.TestRegisterRequestProxy(t) 379 args.Service.ProxyDestination = "legacy" 380 args.Service.Proxy = structs.ConnectProxyConfig{} 381 382 // Register 383 var out struct{} 384 assert.Nil(msgpackrpc.CallWithCodec(codec, "Catalog.Register", &args, &out)) 385 386 // List 387 req := structs.ServiceSpecificRequest{ 388 Datacenter: "dc1", 389 ServiceName: args.Service.Service, 390 } 391 var resp structs.IndexedServiceNodes 392 assert.Nil(msgpackrpc.CallWithCodec(codec, "Catalog.ServiceNodes", &req, &resp)) 393 assert.Len(resp.ServiceNodes, 1) 394 v := resp.ServiceNodes[0] 395 assert.Equal(structs.ServiceKindConnectProxy, v.ServiceKind) 396 assert.Equal(args.Service.ProxyDestination, v.ServiceProxy.DestinationServiceName) 397 } 398 399 // Test an invalid ConnectProxy. We don't need to exhaustively test because 400 // this is all tested in structs on the Validate method. 401 func TestCatalog_Register_ConnectProxy_invalid(t *testing.T) { 402 t.Parallel() 403 404 assert := assert.New(t) 405 dir1, s1 := testServer(t) 406 defer os.RemoveAll(dir1) 407 defer s1.Shutdown() 408 codec := rpcClient(t, s1) 409 defer codec.Close() 410 411 args := structs.TestRegisterRequestProxy(t) 412 args.Service.Proxy.DestinationServiceName = "" 413 414 // Register 415 var out struct{} 416 err := msgpackrpc.CallWithCodec(codec, "Catalog.Register", &args, &out) 417 assert.NotNil(err) 418 assert.Contains(err.Error(), "DestinationServiceName") 419 } 420 421 // Test that write is required for the proxy destination to register a proxy. 422 func TestCatalog_Register_ConnectProxy_ACLProxyDestination(t *testing.T) { 423 t.Parallel() 424 425 assert := assert.New(t) 426 dir1, s1 := testServerWithConfig(t, func(c *Config) { 427 c.ACLDatacenter = "dc1" 428 c.ACLsEnabled = true 429 c.ACLMasterToken = "root" 430 c.ACLDefaultPolicy = "deny" 431 }) 432 defer os.RemoveAll(dir1) 433 defer s1.Shutdown() 434 codec := rpcClient(t, s1) 435 defer codec.Close() 436 437 testrpc.WaitForLeader(t, s1.RPC, "dc1") 438 439 // Create the ACL. 440 arg := structs.ACLRequest{ 441 Datacenter: "dc1", 442 Op: structs.ACLSet, 443 ACL: structs.ACL{ 444 Name: "User token", 445 Type: structs.ACLTokenTypeClient, 446 Rules: ` 447 service "foo" { 448 policy = "write" 449 } 450 `, 451 }, 452 WriteRequest: structs.WriteRequest{Token: "root"}, 453 } 454 var token string 455 assert.Nil(msgpackrpc.CallWithCodec(codec, "ACL.Apply", &arg, &token)) 456 457 // Register should fail because we don't have permission on the destination 458 args := structs.TestRegisterRequestProxy(t) 459 args.Service.Service = "foo" 460 args.Service.Proxy.DestinationServiceName = "bar" 461 args.WriteRequest.Token = token 462 var out struct{} 463 err := msgpackrpc.CallWithCodec(codec, "Catalog.Register", &args, &out) 464 assert.True(acl.IsErrPermissionDenied(err)) 465 466 // Register should fail with the right destination but wrong name 467 args = structs.TestRegisterRequestProxy(t) 468 args.Service.Service = "bar" 469 args.Service.Proxy.DestinationServiceName = "foo" 470 args.WriteRequest.Token = token 471 err = msgpackrpc.CallWithCodec(codec, "Catalog.Register", &args, &out) 472 assert.True(acl.IsErrPermissionDenied(err)) 473 474 // Register should work with the right destination 475 args = structs.TestRegisterRequestProxy(t) 476 args.Service.Service = "foo" 477 args.Service.Proxy.DestinationServiceName = "foo" 478 args.WriteRequest.Token = token 479 assert.Nil(msgpackrpc.CallWithCodec(codec, "Catalog.Register", &args, &out)) 480 } 481 482 func TestCatalog_Register_ConnectNative(t *testing.T) { 483 t.Parallel() 484 485 assert := assert.New(t) 486 dir1, s1 := testServer(t) 487 defer os.RemoveAll(dir1) 488 defer s1.Shutdown() 489 codec := rpcClient(t, s1) 490 defer codec.Close() 491 492 args := structs.TestRegisterRequest(t) 493 args.Service.Connect.Native = true 494 495 // Register 496 var out struct{} 497 assert.Nil(msgpackrpc.CallWithCodec(codec, "Catalog.Register", &args, &out)) 498 499 // List 500 req := structs.ServiceSpecificRequest{ 501 Datacenter: "dc1", 502 ServiceName: args.Service.Service, 503 } 504 var resp structs.IndexedServiceNodes 505 assert.Nil(msgpackrpc.CallWithCodec(codec, "Catalog.ServiceNodes", &req, &resp)) 506 assert.Len(resp.ServiceNodes, 1) 507 v := resp.ServiceNodes[0] 508 assert.Equal(structs.ServiceKindTypical, v.ServiceKind) 509 assert.True(v.ServiceConnect.Native) 510 } 511 512 func TestCatalog_Deregister(t *testing.T) { 513 t.Parallel() 514 dir1, s1 := testServer(t) 515 defer os.RemoveAll(dir1) 516 defer s1.Shutdown() 517 codec := rpcClient(t, s1) 518 defer codec.Close() 519 520 arg := structs.DeregisterRequest{ 521 Datacenter: "dc1", 522 Node: "foo", 523 } 524 var out struct{} 525 526 err := msgpackrpc.CallWithCodec(codec, "Catalog.Deregister", &arg, &out) 527 if err != nil { 528 t.Fatalf("err: %v", err) 529 } 530 531 testrpc.WaitForLeader(t, s1.RPC, "dc1") 532 533 if err := msgpackrpc.CallWithCodec(codec, "Catalog.Deregister", &arg, &out); err != nil { 534 t.Fatalf("err: %v", err) 535 } 536 } 537 538 func TestCatalog_Deregister_ACLDeny(t *testing.T) { 539 t.Parallel() 540 dir1, s1 := testServerWithConfig(t, func(c *Config) { 541 c.ACLDatacenter = "dc1" 542 c.ACLsEnabled = true 543 c.ACLMasterToken = "root" 544 c.ACLDefaultPolicy = "deny" 545 c.ACLEnforceVersion8 = false 546 }) 547 defer os.RemoveAll(dir1) 548 defer s1.Shutdown() 549 codec := rpcClient(t, s1) 550 defer codec.Close() 551 552 testrpc.WaitForLeader(t, s1.RPC, "dc1") 553 554 // Create the ACL. 555 arg := structs.ACLRequest{ 556 Datacenter: "dc1", 557 Op: structs.ACLSet, 558 ACL: structs.ACL{ 559 Name: "User token", 560 Type: structs.ACLTokenTypeClient, 561 Rules: ` 562 node "node" { 563 policy = "write" 564 } 565 566 service "service" { 567 policy = "write" 568 } 569 `, 570 }, 571 WriteRequest: structs.WriteRequest{Token: "root"}, 572 } 573 var id string 574 if err := msgpackrpc.CallWithCodec(codec, "ACL.Apply", &arg, &id); err != nil { 575 t.Fatalf("err: %v", err) 576 } 577 578 // Register a node, node check, service, and service check. 579 argR := structs.RegisterRequest{ 580 Datacenter: "dc1", 581 Node: "node", 582 Address: "127.0.0.1", 583 Service: &structs.NodeService{ 584 Service: "service", 585 Port: 8000, 586 }, 587 Checks: structs.HealthChecks{ 588 &structs.HealthCheck{ 589 Node: "node", 590 CheckID: "node-check", 591 }, 592 &structs.HealthCheck{ 593 Node: "node", 594 CheckID: "service-check", 595 ServiceID: "service", 596 }, 597 }, 598 WriteRequest: structs.WriteRequest{Token: id}, 599 } 600 var outR struct{} 601 if err := msgpackrpc.CallWithCodec(codec, "Catalog.Register", &argR, &outR); err != nil { 602 t.Fatalf("err: %v", err) 603 } 604 605 // First pass with version 8 ACL enforcement disabled, we should be able 606 // to deregister everything even without a token. 607 var err error 608 var out struct{} 609 err = msgpackrpc.CallWithCodec(codec, "Catalog.Deregister", 610 &structs.DeregisterRequest{ 611 Datacenter: "dc1", 612 Node: "node", 613 CheckID: "service-check"}, &out) 614 if err != nil { 615 t.Fatalf("err: %v", err) 616 } 617 err = msgpackrpc.CallWithCodec(codec, "Catalog.Deregister", 618 &structs.DeregisterRequest{ 619 Datacenter: "dc1", 620 Node: "node", 621 CheckID: "node-check"}, &out) 622 if err != nil { 623 t.Fatalf("err: %v", err) 624 } 625 err = msgpackrpc.CallWithCodec(codec, "Catalog.Deregister", 626 &structs.DeregisterRequest{ 627 Datacenter: "dc1", 628 Node: "node", 629 ServiceID: "service"}, &out) 630 if err != nil { 631 t.Fatalf("err: %v", err) 632 } 633 err = msgpackrpc.CallWithCodec(codec, "Catalog.Deregister", 634 &structs.DeregisterRequest{ 635 Datacenter: "dc1", 636 Node: "node"}, &out) 637 if err != nil { 638 t.Fatalf("err: %v", err) 639 } 640 641 // Turn on version 8 ACL enforcement and put the catalog entry back. 642 s1.config.ACLEnforceVersion8 = true 643 if err := msgpackrpc.CallWithCodec(codec, "Catalog.Register", &argR, &outR); err != nil { 644 t.Fatalf("err: %v", err) 645 } 646 647 // Second pass with version 8 ACL enforcement enabled, these should all 648 // get rejected. 649 err = msgpackrpc.CallWithCodec(codec, "Catalog.Deregister", 650 &structs.DeregisterRequest{ 651 Datacenter: "dc1", 652 Node: "node", 653 CheckID: "service-check"}, &out) 654 if !acl.IsErrPermissionDenied(err) { 655 t.Fatalf("err: %v", err) 656 } 657 err = msgpackrpc.CallWithCodec(codec, "Catalog.Deregister", 658 &structs.DeregisterRequest{ 659 Datacenter: "dc1", 660 Node: "node", 661 CheckID: "node-check"}, &out) 662 if !acl.IsErrPermissionDenied(err) { 663 t.Fatalf("err: %v", err) 664 } 665 err = msgpackrpc.CallWithCodec(codec, "Catalog.Deregister", 666 &structs.DeregisterRequest{ 667 Datacenter: "dc1", 668 Node: "node", 669 ServiceID: "service"}, &out) 670 if !acl.IsErrPermissionDenied(err) { 671 t.Fatalf("err: %v", err) 672 } 673 err = msgpackrpc.CallWithCodec(codec, "Catalog.Deregister", 674 &structs.DeregisterRequest{ 675 Datacenter: "dc1", 676 Node: "node"}, &out) 677 if !acl.IsErrPermissionDenied(err) { 678 t.Fatalf("err: %v", err) 679 } 680 681 // Third pass these should all go through with the token set. 682 err = msgpackrpc.CallWithCodec(codec, "Catalog.Deregister", 683 &structs.DeregisterRequest{ 684 Datacenter: "dc1", 685 Node: "node", 686 CheckID: "service-check", 687 WriteRequest: structs.WriteRequest{ 688 Token: id, 689 }}, &out) 690 if err != nil { 691 t.Fatalf("err: %v", err) 692 } 693 err = msgpackrpc.CallWithCodec(codec, "Catalog.Deregister", 694 &structs.DeregisterRequest{ 695 Datacenter: "dc1", 696 Node: "node", 697 CheckID: "node-check", 698 WriteRequest: structs.WriteRequest{ 699 Token: id, 700 }}, &out) 701 if err != nil { 702 t.Fatalf("err: %v", err) 703 } 704 err = msgpackrpc.CallWithCodec(codec, "Catalog.Deregister", 705 &structs.DeregisterRequest{ 706 Datacenter: "dc1", 707 Node: "node", 708 ServiceID: "service", 709 WriteRequest: structs.WriteRequest{ 710 Token: id, 711 }}, &out) 712 if err != nil { 713 t.Fatalf("err: %v", err) 714 } 715 err = msgpackrpc.CallWithCodec(codec, "Catalog.Deregister", 716 &structs.DeregisterRequest{ 717 Datacenter: "dc1", 718 Node: "node", 719 WriteRequest: structs.WriteRequest{ 720 Token: id, 721 }}, &out) 722 if err != nil { 723 t.Fatalf("err: %v", err) 724 } 725 726 // Try a few error cases. 727 err = msgpackrpc.CallWithCodec(codec, "Catalog.Deregister", 728 &structs.DeregisterRequest{ 729 Datacenter: "dc1", 730 Node: "node", 731 ServiceID: "nope", 732 WriteRequest: structs.WriteRequest{ 733 Token: id, 734 }}, &out) 735 if err == nil || !strings.Contains(err.Error(), "Unknown service") { 736 t.Fatalf("err: %v", err) 737 } 738 err = msgpackrpc.CallWithCodec(codec, "Catalog.Deregister", 739 &structs.DeregisterRequest{ 740 Datacenter: "dc1", 741 Node: "node", 742 CheckID: "nope", 743 WriteRequest: structs.WriteRequest{ 744 Token: id, 745 }}, &out) 746 if err == nil || !strings.Contains(err.Error(), "Unknown check") { 747 t.Fatalf("err: %v", err) 748 } 749 } 750 751 func TestCatalog_ListDatacenters(t *testing.T) { 752 t.Parallel() 753 dir1, s1 := testServer(t) 754 defer os.RemoveAll(dir1) 755 defer s1.Shutdown() 756 codec := rpcClient(t, s1) 757 defer codec.Close() 758 759 dir2, s2 := testServerDC(t, "dc2") 760 defer os.RemoveAll(dir2) 761 defer s2.Shutdown() 762 763 // Try to join 764 joinWAN(t, s2, s1) 765 766 testrpc.WaitForLeader(t, s1.RPC, "dc1") 767 768 var out []string 769 if err := msgpackrpc.CallWithCodec(codec, "Catalog.ListDatacenters", struct{}{}, &out); err != nil { 770 t.Fatalf("err: %v", err) 771 } 772 773 // The DCs should come out sorted by default. 774 if len(out) != 2 { 775 t.Fatalf("bad: %v", out) 776 } 777 if out[0] != "dc1" { 778 t.Fatalf("bad: %v", out) 779 } 780 if out[1] != "dc2" { 781 t.Fatalf("bad: %v", out) 782 } 783 } 784 785 func TestCatalog_ListDatacenters_DistanceSort(t *testing.T) { 786 t.Parallel() 787 dir1, s1 := testServer(t) 788 defer os.RemoveAll(dir1) 789 defer s1.Shutdown() 790 codec := rpcClient(t, s1) 791 defer codec.Close() 792 793 dir2, s2 := testServerDC(t, "dc2") 794 defer os.RemoveAll(dir2) 795 defer s2.Shutdown() 796 797 dir3, s3 := testServerDC(t, "acdc") 798 defer os.RemoveAll(dir3) 799 defer s3.Shutdown() 800 801 // Try to join 802 joinWAN(t, s2, s1) 803 joinWAN(t, s3, s1) 804 testrpc.WaitForLeader(t, s1.RPC, "dc1") 805 806 var out []string 807 if err := msgpackrpc.CallWithCodec(codec, "Catalog.ListDatacenters", struct{}{}, &out); err != nil { 808 t.Fatalf("err: %v", err) 809 } 810 811 // It's super hard to force the Serfs into a known configuration of 812 // coordinates, so the best we can do is make sure that the sorting 813 // function is getting called (it's tested extensively in rtt_test.go). 814 // Since this is relative to dc1, it will be listed first (proving we 815 // went into the sort fn). 816 if len(out) != 3 { 817 t.Fatalf("bad: %v", out) 818 } 819 if out[0] != "dc1" { 820 t.Fatalf("bad: %v", out) 821 } 822 } 823 824 func TestCatalog_ListNodes(t *testing.T) { 825 t.Parallel() 826 dir1, s1 := testServer(t) 827 defer os.RemoveAll(dir1) 828 defer s1.Shutdown() 829 codec := rpcClient(t, s1) 830 defer codec.Close() 831 832 args := structs.DCSpecificRequest{ 833 Datacenter: "dc1", 834 } 835 var out structs.IndexedNodes 836 err := msgpackrpc.CallWithCodec(codec, "Catalog.ListNodes", &args, &out) 837 if err != nil { 838 t.Fatalf("err: %v", err) 839 } 840 841 testrpc.WaitForLeader(t, s1.RPC, "dc1") 842 843 // Just add a node 844 if err := s1.fsm.State().EnsureNode(1, &structs.Node{Node: "foo", Address: "127.0.0.1"}); err != nil { 845 t.Fatalf("err: %v", err) 846 } 847 retry.Run(t, func(r *retry.R) { 848 msgpackrpc.CallWithCodec(codec, "Catalog.ListNodes", &args, &out) 849 if got, want := len(out.Nodes), 2; got != want { 850 r.Fatalf("got %d nodes want %d", got, want) 851 } 852 }) 853 854 // Server node is auto added from Serf 855 if out.Nodes[1].Node != s1.config.NodeName { 856 t.Fatalf("bad: %v", out) 857 } 858 if out.Nodes[0].Node != "foo" { 859 t.Fatalf("bad: %v", out) 860 } 861 if out.Nodes[0].Address != "127.0.0.1" { 862 t.Fatalf("bad: %v", out) 863 } 864 } 865 866 func TestCatalog_ListNodes_NodeMetaFilter(t *testing.T) { 867 t.Parallel() 868 dir1, s1 := testServer(t) 869 defer os.RemoveAll(dir1) 870 defer s1.Shutdown() 871 codec := rpcClient(t, s1) 872 defer codec.Close() 873 874 testrpc.WaitForLeader(t, s1.RPC, "dc1") 875 876 // Add a new node with the right meta k/v pair 877 node := &structs.Node{Node: "foo", Address: "127.0.0.1", Meta: map[string]string{"somekey": "somevalue"}} 878 if err := s1.fsm.State().EnsureNode(1, node); err != nil { 879 t.Fatalf("err: %v", err) 880 } 881 882 // Filter by a specific meta k/v pair 883 args := structs.DCSpecificRequest{ 884 Datacenter: "dc1", 885 NodeMetaFilters: map[string]string{ 886 "somekey": "somevalue", 887 }, 888 } 889 var out structs.IndexedNodes 890 retry.Run(t, func(r *retry.R) { 891 msgpackrpc.CallWithCodec(codec, "Catalog.ListNodes", &args, &out) 892 if got, want := len(out.Nodes), 1; got != want { 893 r.Fatalf("got %d nodes want %d", got, want) 894 } 895 }) 896 897 // Verify that only the correct node was returned 898 if out.Nodes[0].Node != "foo" { 899 t.Fatalf("bad: %v", out) 900 } 901 if out.Nodes[0].Address != "127.0.0.1" { 902 t.Fatalf("bad: %v", out) 903 } 904 if v, ok := out.Nodes[0].Meta["somekey"]; !ok || v != "somevalue" { 905 t.Fatalf("bad: %v", out) 906 } 907 908 // Now filter on a nonexistent meta k/v pair 909 args = structs.DCSpecificRequest{ 910 Datacenter: "dc1", 911 NodeMetaFilters: map[string]string{ 912 "somekey": "invalid", 913 }, 914 } 915 out = structs.IndexedNodes{} 916 err := msgpackrpc.CallWithCodec(codec, "Catalog.ListNodes", &args, &out) 917 if err != nil { 918 t.Fatalf("err: %v", err) 919 } 920 // Should get an empty list of nodes back 921 retry.Run(t, func(r *retry.R) { 922 msgpackrpc.CallWithCodec(codec, "Catalog.ListNodes", &args, &out) 923 if len(out.Nodes) != 0 { 924 r.Fatal(nil) 925 } 926 }) 927 } 928 929 func TestCatalog_ListNodes_StaleRead(t *testing.T) { 930 t.Parallel() 931 dir1, s1 := testServer(t) 932 defer os.RemoveAll(dir1) 933 defer s1.Shutdown() 934 codec1 := rpcClient(t, s1) 935 defer codec1.Close() 936 testrpc.WaitForTestAgent(t, s1.RPC, "dc1") 937 938 dir2, s2 := testServerDCBootstrap(t, "dc1", false) 939 defer os.RemoveAll(dir2) 940 defer s2.Shutdown() 941 codec2 := rpcClient(t, s2) 942 defer codec2.Close() 943 944 // Try to join 945 joinLAN(t, s2, s1) 946 947 testrpc.WaitForTestAgent(t, s1.RPC, "dc1") 948 testrpc.WaitForTestAgent(t, s2.RPC, "dc1") 949 950 // Use the follower as the client 951 var codec rpc.ClientCodec 952 if !s1.IsLeader() { 953 codec = codec1 954 955 // Inject fake data on the follower! 956 if err := s1.fsm.State().EnsureNode(1, &structs.Node{Node: "foo", Address: "127.0.0.1"}); err != nil { 957 t.Fatalf("err: %v", err) 958 } 959 } else { 960 codec = codec2 961 962 // Inject fake data on the follower! 963 if err := s2.fsm.State().EnsureNode(1, &structs.Node{Node: "foo", Address: "127.0.0.1"}); err != nil { 964 t.Fatalf("err: %v", err) 965 } 966 } 967 968 args := structs.DCSpecificRequest{ 969 Datacenter: "dc1", 970 QueryOptions: structs.QueryOptions{AllowStale: true}, 971 } 972 var out structs.IndexedNodes 973 if err := msgpackrpc.CallWithCodec(codec, "Catalog.ListNodes", &args, &out); err != nil { 974 t.Fatalf("err: %v", err) 975 } 976 977 found := false 978 for _, n := range out.Nodes { 979 if n.Node == "foo" { 980 found = true 981 } 982 } 983 if !found { 984 t.Fatalf("failed to find foo in %#v", out.Nodes) 985 } 986 987 if out.QueryMeta.LastContact == 0 { 988 t.Fatalf("should have a last contact time") 989 } 990 if !out.QueryMeta.KnownLeader { 991 t.Fatalf("should have known leader") 992 } 993 } 994 995 func TestCatalog_ListNodes_ConsistentRead_Fail(t *testing.T) { 996 t.Parallel() 997 dir1, s1 := testServer(t) 998 defer os.RemoveAll(dir1) 999 defer s1.Shutdown() 1000 1001 dir2, s2 := testServerDCBootstrap(t, "dc1", false) 1002 defer os.RemoveAll(dir2) 1003 defer s2.Shutdown() 1004 1005 dir3, s3 := testServerDCBootstrap(t, "dc1", false) 1006 defer os.RemoveAll(dir3) 1007 defer s3.Shutdown() 1008 1009 // Try to join and wait for all servers to get promoted to voters. 1010 joinLAN(t, s2, s1) 1011 joinLAN(t, s3, s2) 1012 servers := []*Server{s1, s2, s3} 1013 retry.Run(t, func(r *retry.R) { 1014 r.Check(wantRaft(servers)) 1015 for _, s := range servers { 1016 r.Check(wantPeers(s, 3)) 1017 } 1018 }) 1019 1020 // Use the leader as the client, kill the followers. 1021 var codec rpc.ClientCodec 1022 for _, s := range servers { 1023 if s.IsLeader() { 1024 codec = rpcClient(t, s) 1025 defer codec.Close() 1026 } else { 1027 s.Shutdown() 1028 } 1029 } 1030 if codec == nil { 1031 t.Fatalf("no leader") 1032 } 1033 1034 args := structs.DCSpecificRequest{ 1035 Datacenter: "dc1", 1036 QueryOptions: structs.QueryOptions{RequireConsistent: true}, 1037 } 1038 var out structs.IndexedNodes 1039 err := msgpackrpc.CallWithCodec(codec, "Catalog.ListNodes", &args, &out) 1040 if err == nil || !strings.HasPrefix(err.Error(), "leadership lost") { 1041 t.Fatalf("err: %v", err) 1042 } 1043 if out.QueryMeta.LastContact != 0 { 1044 t.Fatalf("should not have a last contact time") 1045 } 1046 if out.QueryMeta.KnownLeader { 1047 t.Fatalf("should have no known leader") 1048 } 1049 } 1050 1051 func TestCatalog_ListNodes_ConsistentRead(t *testing.T) { 1052 t.Parallel() 1053 dir1, s1 := testServer(t) 1054 defer os.RemoveAll(dir1) 1055 defer s1.Shutdown() 1056 codec1 := rpcClient(t, s1) 1057 defer codec1.Close() 1058 1059 dir2, s2 := testServerDCBootstrap(t, "dc1", false) 1060 defer os.RemoveAll(dir2) 1061 defer s2.Shutdown() 1062 codec2 := rpcClient(t, s2) 1063 defer codec2.Close() 1064 1065 // Try to join 1066 joinLAN(t, s2, s1) 1067 1068 testrpc.WaitForLeader(t, s1.RPC, "dc1") 1069 testrpc.WaitForLeader(t, s2.RPC, "dc1") 1070 1071 // Use the leader as the client, kill the follower 1072 var codec rpc.ClientCodec 1073 if s1.IsLeader() { 1074 codec = codec1 1075 } else { 1076 codec = codec2 1077 } 1078 1079 args := structs.DCSpecificRequest{ 1080 Datacenter: "dc1", 1081 QueryOptions: structs.QueryOptions{RequireConsistent: true}, 1082 } 1083 var out structs.IndexedNodes 1084 if err := msgpackrpc.CallWithCodec(codec, "Catalog.ListNodes", &args, &out); err != nil { 1085 t.Fatalf("err: %v", err) 1086 } 1087 1088 if out.QueryMeta.LastContact != 0 { 1089 t.Fatalf("should not have a last contact time") 1090 } 1091 if !out.QueryMeta.KnownLeader { 1092 t.Fatalf("should have known leader") 1093 } 1094 } 1095 1096 func TestCatalog_ListNodes_DistanceSort(t *testing.T) { 1097 t.Parallel() 1098 dir1, s1 := testServer(t) 1099 defer os.RemoveAll(dir1) 1100 defer s1.Shutdown() 1101 codec := rpcClient(t, s1) 1102 defer codec.Close() 1103 1104 testrpc.WaitForLeader(t, s1.RPC, "dc1") 1105 if err := s1.fsm.State().EnsureNode(1, &structs.Node{Node: "aaa", Address: "127.0.0.1"}); err != nil { 1106 t.Fatalf("err: %v", err) 1107 } 1108 if err := s1.fsm.State().EnsureNode(2, &structs.Node{Node: "foo", Address: "127.0.0.2"}); err != nil { 1109 t.Fatalf("err: %v", err) 1110 } 1111 if err := s1.fsm.State().EnsureNode(3, &structs.Node{Node: "bar", Address: "127.0.0.3"}); err != nil { 1112 t.Fatalf("err: %v", err) 1113 } 1114 if err := s1.fsm.State().EnsureNode(4, &structs.Node{Node: "baz", Address: "127.0.0.4"}); err != nil { 1115 t.Fatalf("err: %v", err) 1116 } 1117 1118 // Set all but one of the nodes to known coordinates. 1119 updates := structs.Coordinates{ 1120 {Node: "foo", Coord: lib.GenerateCoordinate(2 * time.Millisecond)}, 1121 {Node: "bar", Coord: lib.GenerateCoordinate(5 * time.Millisecond)}, 1122 {Node: "baz", Coord: lib.GenerateCoordinate(1 * time.Millisecond)}, 1123 } 1124 if err := s1.fsm.State().CoordinateBatchUpdate(5, updates); err != nil { 1125 t.Fatalf("err: %v", err) 1126 } 1127 1128 // Query with no given source node, should get the natural order from 1129 // the index. 1130 args := structs.DCSpecificRequest{ 1131 Datacenter: "dc1", 1132 } 1133 var out structs.IndexedNodes 1134 retry.Run(t, func(r *retry.R) { 1135 msgpackrpc.CallWithCodec(codec, "Catalog.ListNodes", &args, &out) 1136 if got, want := len(out.Nodes), 5; got != want { 1137 r.Fatalf("got %d nodes want %d", got, want) 1138 } 1139 }) 1140 1141 if out.Nodes[0].Node != "aaa" { 1142 t.Fatalf("bad: %v", out) 1143 } 1144 if out.Nodes[1].Node != "bar" { 1145 t.Fatalf("bad: %v", out) 1146 } 1147 if out.Nodes[2].Node != "baz" { 1148 t.Fatalf("bad: %v", out) 1149 } 1150 if out.Nodes[3].Node != "foo" { 1151 t.Fatalf("bad: %v", out) 1152 } 1153 if out.Nodes[4].Node != s1.config.NodeName { 1154 t.Fatalf("bad: %v", out) 1155 } 1156 1157 // Query relative to foo, note that there's no known coordinate for the 1158 // default-added Serf node nor "aaa" so they will go at the end. 1159 args = structs.DCSpecificRequest{ 1160 Datacenter: "dc1", 1161 Source: structs.QuerySource{Datacenter: "dc1", Node: "foo"}, 1162 } 1163 retry.Run(t, func(r *retry.R) { 1164 msgpackrpc.CallWithCodec(codec, "Catalog.ListNodes", &args, &out) 1165 if got, want := len(out.Nodes), 5; got != want { 1166 r.Fatalf("got %d nodes want %d", got, want) 1167 } 1168 }) 1169 1170 if out.Nodes[0].Node != "foo" { 1171 t.Fatalf("bad: %v", out) 1172 } 1173 if out.Nodes[1].Node != "baz" { 1174 t.Fatalf("bad: %v", out) 1175 } 1176 if out.Nodes[2].Node != "bar" { 1177 t.Fatalf("bad: %v", out) 1178 } 1179 if out.Nodes[3].Node != "aaa" { 1180 t.Fatalf("bad: %v", out) 1181 } 1182 if out.Nodes[4].Node != s1.config.NodeName { 1183 t.Fatalf("bad: %v", out) 1184 } 1185 } 1186 1187 func TestCatalog_ListNodes_ACLFilter(t *testing.T) { 1188 t.Parallel() 1189 dir1, s1 := testServerWithConfig(t, func(c *Config) { 1190 c.ACLDatacenter = "dc1" 1191 c.ACLsEnabled = true 1192 c.ACLMasterToken = "root" 1193 c.ACLDefaultPolicy = "deny" 1194 c.ACLEnforceVersion8 = false 1195 }) 1196 defer os.RemoveAll(dir1) 1197 defer s1.Shutdown() 1198 codec := rpcClient(t, s1) 1199 defer codec.Close() 1200 1201 testrpc.WaitForLeader(t, s1.RPC, "dc1") 1202 1203 // We scope the reply in each of these since msgpack won't clear out an 1204 // existing slice if the incoming one is nil, so it's best to start 1205 // clean each time. 1206 1207 // Prior to version 8, the node policy should be ignored. 1208 args := structs.DCSpecificRequest{ 1209 Datacenter: "dc1", 1210 } 1211 { 1212 reply := structs.IndexedNodes{} 1213 if err := msgpackrpc.CallWithCodec(codec, "Catalog.ListNodes", &args, &reply); err != nil { 1214 t.Fatalf("err: %v", err) 1215 } 1216 if len(reply.Nodes) != 1 { 1217 t.Fatalf("bad: %v", reply.Nodes) 1218 } 1219 } 1220 1221 // Now turn on version 8 enforcement and try again. 1222 s1.config.ACLEnforceVersion8 = true 1223 { 1224 reply := structs.IndexedNodes{} 1225 if err := msgpackrpc.CallWithCodec(codec, "Catalog.ListNodes", &args, &reply); err != nil { 1226 t.Fatalf("err: %v", err) 1227 } 1228 if len(reply.Nodes) != 0 { 1229 t.Fatalf("bad: %v", reply.Nodes) 1230 } 1231 } 1232 1233 // Create an ACL that can read the node. 1234 arg := structs.ACLRequest{ 1235 Datacenter: "dc1", 1236 Op: structs.ACLSet, 1237 ACL: structs.ACL{ 1238 Name: "User token", 1239 Type: structs.ACLTokenTypeClient, 1240 Rules: fmt.Sprintf(` 1241 node "%s" { 1242 policy = "read" 1243 } 1244 `, s1.config.NodeName), 1245 }, 1246 WriteRequest: structs.WriteRequest{Token: "root"}, 1247 } 1248 var id string 1249 if err := msgpackrpc.CallWithCodec(codec, "ACL.Apply", &arg, &id); err != nil { 1250 t.Fatalf("err: %v", err) 1251 } 1252 1253 // Now try with the token and it will go through. 1254 args.Token = id 1255 { 1256 reply := structs.IndexedNodes{} 1257 if err := msgpackrpc.CallWithCodec(codec, "Catalog.ListNodes", &args, &reply); err != nil { 1258 t.Fatalf("err: %v", err) 1259 } 1260 if len(reply.Nodes) != 1 { 1261 t.Fatalf("bad: %v", reply.Nodes) 1262 } 1263 } 1264 } 1265 1266 func Benchmark_Catalog_ListNodes(t *testing.B) { 1267 dir1, s1 := testServer(nil) 1268 defer os.RemoveAll(dir1) 1269 defer s1.Shutdown() 1270 codec := rpcClient(nil, s1) 1271 defer codec.Close() 1272 1273 // Just add a node 1274 if err := s1.fsm.State().EnsureNode(1, &structs.Node{Node: "foo", Address: "127.0.0.1"}); err != nil { 1275 t.Fatalf("err: %v", err) 1276 } 1277 1278 args := structs.DCSpecificRequest{ 1279 Datacenter: "dc1", 1280 } 1281 for i := 0; i < t.N; i++ { 1282 var out structs.IndexedNodes 1283 if err := msgpackrpc.CallWithCodec(codec, "Catalog.ListNodes", &args, &out); err != nil { 1284 t.Fatalf("err: %v", err) 1285 } 1286 } 1287 } 1288 1289 func TestCatalog_ListServices(t *testing.T) { 1290 t.Parallel() 1291 dir1, s1 := testServer(t) 1292 defer os.RemoveAll(dir1) 1293 defer s1.Shutdown() 1294 codec := rpcClient(t, s1) 1295 defer codec.Close() 1296 1297 args := structs.DCSpecificRequest{ 1298 Datacenter: "dc1", 1299 } 1300 var out structs.IndexedServices 1301 err := msgpackrpc.CallWithCodec(codec, "Catalog.ListServices", &args, &out) 1302 if err != nil { 1303 t.Fatalf("err: %v", err) 1304 } 1305 1306 testrpc.WaitForLeader(t, s1.RPC, "dc1") 1307 1308 // Just add a node 1309 if err := s1.fsm.State().EnsureNode(1, &structs.Node{Node: "foo", Address: "127.0.0.1"}); err != nil { 1310 t.Fatalf("err: %v", err) 1311 } 1312 if err := s1.fsm.State().EnsureService(2, "foo", &structs.NodeService{ID: "db", Service: "db", Tags: []string{"primary"}, Address: "127.0.0.1", Port: 5000}); err != nil { 1313 t.Fatalf("err: %v", err) 1314 } 1315 1316 if err := msgpackrpc.CallWithCodec(codec, "Catalog.ListServices", &args, &out); err != nil { 1317 t.Fatalf("err: %v", err) 1318 } 1319 1320 if len(out.Services) != 2 { 1321 t.Fatalf("bad: %v", out) 1322 } 1323 for _, s := range out.Services { 1324 if s == nil { 1325 t.Fatalf("bad: %v", s) 1326 } 1327 } 1328 // Consul service should auto-register 1329 if _, ok := out.Services["consul"]; !ok { 1330 t.Fatalf("bad: %v", out) 1331 } 1332 if len(out.Services["db"]) != 1 { 1333 t.Fatalf("bad: %v", out) 1334 } 1335 if out.Services["db"][0] != "primary" { 1336 t.Fatalf("bad: %v", out) 1337 } 1338 } 1339 1340 func TestCatalog_ListServices_NodeMetaFilter(t *testing.T) { 1341 t.Parallel() 1342 dir1, s1 := testServer(t) 1343 defer os.RemoveAll(dir1) 1344 defer s1.Shutdown() 1345 codec := rpcClient(t, s1) 1346 defer codec.Close() 1347 1348 testrpc.WaitForTestAgent(t, s1.RPC, "dc1") 1349 1350 // Add a new node with the right meta k/v pair 1351 node := &structs.Node{Node: "foo", Address: "127.0.0.1", Meta: map[string]string{"somekey": "somevalue"}} 1352 if err := s1.fsm.State().EnsureNode(1, node); err != nil { 1353 t.Fatalf("err: %v", err) 1354 } 1355 // Add a service to the new node 1356 if err := s1.fsm.State().EnsureService(2, "foo", &structs.NodeService{ID: "db", Service: "db", Tags: []string{"primary"}, Address: "127.0.0.1", Port: 5000}); err != nil { 1357 t.Fatalf("err: %v", err) 1358 } 1359 1360 // Filter by a specific meta k/v pair 1361 args := structs.DCSpecificRequest{ 1362 Datacenter: "dc1", 1363 NodeMetaFilters: map[string]string{ 1364 "somekey": "somevalue", 1365 }, 1366 } 1367 var out structs.IndexedServices 1368 if err := msgpackrpc.CallWithCodec(codec, "Catalog.ListServices", &args, &out); err != nil { 1369 t.Fatalf("err: %v", err) 1370 } 1371 1372 if len(out.Services) != 1 { 1373 t.Fatalf("bad: %v", out) 1374 } 1375 if out.Services["db"] == nil { 1376 t.Fatalf("bad: %v", out.Services["db"]) 1377 } 1378 if len(out.Services["db"]) != 1 { 1379 t.Fatalf("bad: %v", out) 1380 } 1381 if out.Services["db"][0] != "primary" { 1382 t.Fatalf("bad: %v", out) 1383 } 1384 1385 // Now filter on a nonexistent meta k/v pair 1386 args = structs.DCSpecificRequest{ 1387 Datacenter: "dc1", 1388 NodeMetaFilters: map[string]string{ 1389 "somekey": "invalid", 1390 }, 1391 } 1392 out = structs.IndexedServices{} 1393 err := msgpackrpc.CallWithCodec(codec, "Catalog.ListServices", &args, &out) 1394 if err != nil { 1395 t.Fatalf("err: %v", err) 1396 } 1397 1398 // Should get an empty list of nodes back 1399 if len(out.Services) != 0 { 1400 t.Fatalf("bad: %v", out.Services) 1401 } 1402 } 1403 1404 func TestCatalog_ListServices_Blocking(t *testing.T) { 1405 t.Parallel() 1406 dir1, s1 := testServer(t) 1407 defer os.RemoveAll(dir1) 1408 defer s1.Shutdown() 1409 codec := rpcClient(t, s1) 1410 defer codec.Close() 1411 1412 args := structs.DCSpecificRequest{ 1413 Datacenter: "dc1", 1414 } 1415 var out structs.IndexedServices 1416 1417 testrpc.WaitForLeader(t, s1.RPC, "dc1") 1418 1419 // Run the query 1420 if err := msgpackrpc.CallWithCodec(codec, "Catalog.ListServices", &args, &out); err != nil { 1421 t.Fatalf("err: %v", err) 1422 } 1423 1424 // Setup a blocking query 1425 args.MinQueryIndex = out.Index 1426 args.MaxQueryTime = time.Second 1427 1428 // Async cause a change 1429 idx := out.Index 1430 start := time.Now() 1431 go func() { 1432 time.Sleep(100 * time.Millisecond) 1433 if err := s1.fsm.State().EnsureNode(idx+1, &structs.Node{Node: "foo", Address: "127.0.0.1"}); err != nil { 1434 t.Fatalf("err: %v", err) 1435 } 1436 if err := s1.fsm.State().EnsureService(idx+2, "foo", &structs.NodeService{ID: "db", Service: "db", Tags: []string{"primary"}, Address: "127.0.0.1", Port: 5000}); err != nil { 1437 t.Fatalf("err: %v", err) 1438 } 1439 }() 1440 1441 // Re-run the query 1442 out = structs.IndexedServices{} 1443 if err := msgpackrpc.CallWithCodec(codec, "Catalog.ListServices", &args, &out); err != nil { 1444 t.Fatalf("err: %v", err) 1445 } 1446 1447 // Should block at least 100ms 1448 if time.Since(start) < 100*time.Millisecond { 1449 t.Fatalf("too fast") 1450 } 1451 1452 // Check the indexes 1453 if out.Index != idx+2 { 1454 t.Fatalf("bad: %v", out) 1455 } 1456 1457 // Should find the service 1458 if len(out.Services) != 2 { 1459 t.Fatalf("bad: %v", out) 1460 } 1461 } 1462 1463 func TestCatalog_ListServices_Timeout(t *testing.T) { 1464 t.Parallel() 1465 dir1, s1 := testServer(t) 1466 defer os.RemoveAll(dir1) 1467 defer s1.Shutdown() 1468 codec := rpcClient(t, s1) 1469 defer codec.Close() 1470 1471 args := structs.DCSpecificRequest{ 1472 Datacenter: "dc1", 1473 } 1474 var out structs.IndexedServices 1475 1476 testrpc.WaitForLeader(t, s1.RPC, "dc1") 1477 1478 // Run the query 1479 if err := msgpackrpc.CallWithCodec(codec, "Catalog.ListServices", &args, &out); err != nil { 1480 t.Fatalf("err: %v", err) 1481 } 1482 1483 // Setup a blocking query 1484 args.MinQueryIndex = out.Index 1485 args.MaxQueryTime = 100 * time.Millisecond 1486 1487 // Re-run the query 1488 start := time.Now() 1489 out = structs.IndexedServices{} 1490 if err := msgpackrpc.CallWithCodec(codec, "Catalog.ListServices", &args, &out); err != nil { 1491 t.Fatalf("err: %v", err) 1492 } 1493 1494 // Should block at least 100ms 1495 if time.Since(start) < 100*time.Millisecond { 1496 t.Fatalf("too fast") 1497 } 1498 1499 // Check the indexes, should not change 1500 if out.Index != args.MinQueryIndex { 1501 t.Fatalf("bad: %v", out) 1502 } 1503 } 1504 1505 func TestCatalog_ListServices_Stale(t *testing.T) { 1506 t.Parallel() 1507 dir1, s1 := testServerWithConfig(t, func(c *Config) { 1508 c.ACLDatacenter = "dc1" 1509 c.ACLsEnabled = true 1510 }) 1511 defer os.RemoveAll(dir1) 1512 defer s1.Shutdown() 1513 1514 testrpc.WaitForTestAgent(t, s1.RPC, "dc1") 1515 dir2, s2 := testServerWithConfig(t, func(c *Config) { 1516 c.ACLDatacenter = "dc1" // Enable ACLs! 1517 c.ACLsEnabled = true 1518 c.Bootstrap = false // Disable bootstrap 1519 }) 1520 defer os.RemoveAll(dir2) 1521 defer s2.Shutdown() 1522 1523 args := structs.DCSpecificRequest{ 1524 Datacenter: "dc1", 1525 } 1526 args.AllowStale = true 1527 var out structs.IndexedServices 1528 1529 // Inject a node 1530 if err := s1.fsm.State().EnsureNode(3, &structs.Node{Node: "foo", Address: "127.0.0.1"}); err != nil { 1531 t.Fatalf("err: %v", err) 1532 } 1533 1534 codec := rpcClient(t, s2) 1535 defer codec.Close() 1536 1537 // Run the query, do not wait for leader, never any contact with leader, should fail 1538 if err := msgpackrpc.CallWithCodec(codec, "Catalog.ListServices", &args, &out); err == nil || err.Error() != structs.ErrNoLeader.Error() { 1539 t.Fatalf("expected %v but got err: %v and %v", structs.ErrNoLeader, err, out) 1540 } 1541 1542 // Try to join 1543 joinLAN(t, s2, s1) 1544 retry.Run(t, func(r *retry.R) { r.Check(wantRaft([]*Server{s1, s2})) }) 1545 waitForLeader(s1, s2) 1546 1547 testrpc.WaitForLeader(t, s2.RPC, "dc1") 1548 if err := msgpackrpc.CallWithCodec(codec, "Catalog.ListServices", &args, &out); err != nil { 1549 t.Fatalf("err: %v", err) 1550 } 1551 1552 // Should find the services 1553 if len(out.Services) != 1 { 1554 t.Fatalf("bad: %#v", out.Services) 1555 } 1556 1557 if !out.KnownLeader { 1558 t.Fatalf("should have a leader: %v", out) 1559 } 1560 1561 s1.Leave() 1562 s1.Shutdown() 1563 1564 testrpc.WaitUntilNoLeader(t, s2.RPC, "dc1") 1565 1566 args.AllowStale = false 1567 // Since the leader is now down, non-stale query should fail now 1568 if err := msgpackrpc.CallWithCodec(codec, "Catalog.ListServices", &args, &out); err == nil || err.Error() != structs.ErrNoLeader.Error() { 1569 t.Fatalf("expected %v but got err: %v and %v", structs.ErrNoLeader, err, out) 1570 } 1571 1572 // With stale, request should still work 1573 args.AllowStale = true 1574 if err := msgpackrpc.CallWithCodec(codec, "Catalog.ListServices", &args, &out); err != nil { 1575 t.Fatalf("err: %v", err) 1576 } 1577 1578 // Should find old service 1579 if len(out.Services) != 1 { 1580 t.Fatalf("bad: %#v", out) 1581 } 1582 1583 if out.KnownLeader { 1584 t.Fatalf("should not have a leader anymore: %#v", out) 1585 } 1586 } 1587 1588 func TestCatalog_ListServiceNodes(t *testing.T) { 1589 t.Parallel() 1590 dir1, s1 := testServer(t) 1591 defer os.RemoveAll(dir1) 1592 defer s1.Shutdown() 1593 codec := rpcClient(t, s1) 1594 defer codec.Close() 1595 1596 args := structs.ServiceSpecificRequest{ 1597 Datacenter: "dc1", 1598 ServiceName: "db", 1599 ServiceTags: []string{"slave"}, 1600 TagFilter: false, 1601 } 1602 var out structs.IndexedServiceNodes 1603 err := msgpackrpc.CallWithCodec(codec, "Catalog.ServiceNodes", &args, &out) 1604 if err != nil { 1605 t.Fatalf("err: %v", err) 1606 } 1607 1608 testrpc.WaitForLeader(t, s1.RPC, "dc1") 1609 1610 // Just add a node 1611 if err := s1.fsm.State().EnsureNode(1, &structs.Node{Node: "foo", Address: "127.0.0.1"}); err != nil { 1612 t.Fatalf("err: %v", err) 1613 } 1614 if err := s1.fsm.State().EnsureService(2, "foo", &structs.NodeService{ID: "db", Service: "db", Tags: []string{"primary"}, Address: "127.0.0.1", Port: 5000}); err != nil { 1615 t.Fatalf("err: %v", err) 1616 } 1617 1618 if err := msgpackrpc.CallWithCodec(codec, "Catalog.ServiceNodes", &args, &out); err != nil { 1619 t.Fatalf("err: %v", err) 1620 } 1621 1622 if len(out.ServiceNodes) != 1 { 1623 t.Fatalf("bad: %v", out) 1624 } 1625 1626 // Try with a filter 1627 args.TagFilter = true 1628 out = structs.IndexedServiceNodes{} 1629 1630 if err := msgpackrpc.CallWithCodec(codec, "Catalog.ServiceNodes", &args, &out); err != nil { 1631 t.Fatalf("err: %v", err) 1632 } 1633 if len(out.ServiceNodes) != 0 { 1634 t.Fatalf("bad: %v", out) 1635 } 1636 } 1637 1638 // TestCatalog_ListServiceNodes_ServiceTags_V1_2_3Compat asserts the compatibility between <=v1.2.3 agents and >=v1.3.0 servers 1639 // see https://github.com/hashicorp/consul/issues/4922 1640 func TestCatalog_ListServiceNodes_ServiceTags_V1_2_3Compat(t *testing.T) { 1641 t.Parallel() 1642 dir1, s1 := testServer(t) 1643 defer os.RemoveAll(dir1) 1644 defer s1.Shutdown() 1645 codec := rpcClient(t, s1) 1646 defer codec.Close() 1647 1648 testrpc.WaitForTestAgent(t, s1.RPC, "dc1") 1649 1650 err := s1.fsm.State().EnsureNode(1, &structs.Node{Node: "foo", Address: "127.0.0.1"}) 1651 require.NoError(t, err) 1652 1653 // register two service instances with different tags 1654 err = s1.fsm.State().EnsureService(2, "foo", &structs.NodeService{ID: "db1", Service: "db", Tags: []string{"primary"}, Address: "127.0.0.1", Port: 5000}) 1655 require.NoError(t, err) 1656 err = s1.fsm.State().EnsureService(2, "foo", &structs.NodeService{ID: "db2", Service: "db", Tags: []string{"secondary"}, Address: "127.0.0.1", Port: 5001}) 1657 require.NoError(t, err) 1658 1659 // DEPRECATED (singular-service-tag) - remove this when backwards RPC compat 1660 // with 1.2.x is not required. 1661 // make a request with the <=1.2.3 ServiceTag tag field (vs ServiceTags) 1662 args := structs.ServiceSpecificRequest{ 1663 Datacenter: "dc1", 1664 ServiceName: "db", 1665 ServiceTag: "primary", 1666 TagFilter: true, 1667 } 1668 var out structs.IndexedServiceNodes 1669 err = msgpackrpc.CallWithCodec(codec, "Catalog.ServiceNodes", &args, &out) 1670 require.NoError(t, err) 1671 1672 // nodes should be filtered, even when using the old ServiceTag field 1673 require.Equal(t, 1, len(out.ServiceNodes)) 1674 require.Equal(t, "db1", out.ServiceNodes[0].ServiceID) 1675 1676 // DEPRECATED (singular-service-tag) - remove this when backwards RPC compat 1677 // with 1.2.x is not required. 1678 // test with the other tag 1679 args = structs.ServiceSpecificRequest{ 1680 Datacenter: "dc1", 1681 ServiceName: "db", 1682 ServiceTag: "secondary", 1683 TagFilter: true, 1684 } 1685 out = structs.IndexedServiceNodes{} 1686 err = msgpackrpc.CallWithCodec(codec, "Catalog.ServiceNodes", &args, &out) 1687 require.NoError(t, err) 1688 require.Equal(t, 1, len(out.ServiceNodes)) 1689 require.Equal(t, "db2", out.ServiceNodes[0].ServiceID) 1690 1691 // no tag, both instances 1692 args = structs.ServiceSpecificRequest{ 1693 Datacenter: "dc1", 1694 ServiceName: "db", 1695 } 1696 out = structs.IndexedServiceNodes{} 1697 err = msgpackrpc.CallWithCodec(codec, "Catalog.ServiceNodes", &args, &out) 1698 require.NoError(t, err) 1699 require.Equal(t, 2, len(out.ServiceNodes)) 1700 1701 // DEPRECATED (singular-service-tag) - remove this when backwards RPC compat 1702 // with 1.2.x is not required. 1703 // when both ServiceTag and ServiceTags fields are populated, use ServiceTag 1704 args = structs.ServiceSpecificRequest{ 1705 Datacenter: "dc1", 1706 ServiceName: "db", 1707 ServiceTag: "primary", 1708 ServiceTags: []string{"secondary"}, 1709 TagFilter: true, 1710 } 1711 out = structs.IndexedServiceNodes{} 1712 err = msgpackrpc.CallWithCodec(codec, "Catalog.ServiceNodes", &args, &out) 1713 require.NoError(t, err) 1714 require.Equal(t, "db1", out.ServiceNodes[0].ServiceID) 1715 } 1716 1717 func TestCatalog_ListServiceNodes_NodeMetaFilter(t *testing.T) { 1718 t.Parallel() 1719 dir1, s1 := testServer(t) 1720 defer os.RemoveAll(dir1) 1721 defer s1.Shutdown() 1722 codec := rpcClient(t, s1) 1723 defer codec.Close() 1724 1725 testrpc.WaitForLeader(t, s1.RPC, "dc1") 1726 1727 // Add 2 nodes with specific meta maps 1728 node := &structs.Node{Node: "foo", Address: "127.0.0.1", Meta: map[string]string{"somekey": "somevalue", "common": "1"}} 1729 if err := s1.fsm.State().EnsureNode(1, node); err != nil { 1730 t.Fatalf("err: %v", err) 1731 } 1732 node2 := &structs.Node{Node: "bar", Address: "127.0.0.2", Meta: map[string]string{"common": "1"}} 1733 if err := s1.fsm.State().EnsureNode(2, node2); err != nil { 1734 t.Fatalf("err: %v", err) 1735 } 1736 if err := s1.fsm.State().EnsureService(3, "foo", &structs.NodeService{ID: "db", Service: "db", Tags: []string{"primary", "v2"}, Address: "127.0.0.1", Port: 5000}); err != nil { 1737 t.Fatalf("err: %v", err) 1738 } 1739 if err := s1.fsm.State().EnsureService(4, "bar", &structs.NodeService{ID: "db2", Service: "db", Tags: []string{"secondary", "v2"}, Address: "127.0.0.2", Port: 5000}); err != nil { 1740 t.Fatalf("err: %v", err) 1741 } 1742 1743 cases := []struct { 1744 filters map[string]string 1745 tags []string 1746 services structs.ServiceNodes 1747 }{ 1748 // Basic meta filter 1749 { 1750 filters: map[string]string{"somekey": "somevalue"}, 1751 services: structs.ServiceNodes{&structs.ServiceNode{Node: "foo", ServiceID: "db"}}, 1752 }, 1753 // Basic meta filter, tag 1754 { 1755 filters: map[string]string{"somekey": "somevalue"}, 1756 tags: []string{"primary"}, 1757 services: structs.ServiceNodes{&structs.ServiceNode{Node: "foo", ServiceID: "db"}}, 1758 }, 1759 // Common meta filter 1760 { 1761 filters: map[string]string{"common": "1"}, 1762 services: structs.ServiceNodes{ 1763 &structs.ServiceNode{Node: "bar", ServiceID: "db2"}, 1764 &structs.ServiceNode{Node: "foo", ServiceID: "db"}, 1765 }, 1766 }, 1767 // Common meta filter, tag 1768 { 1769 filters: map[string]string{"common": "1"}, 1770 tags: []string{"secondary"}, 1771 services: structs.ServiceNodes{ 1772 &structs.ServiceNode{Node: "bar", ServiceID: "db2"}, 1773 }, 1774 }, 1775 // Invalid meta filter 1776 { 1777 filters: map[string]string{"invalid": "nope"}, 1778 services: structs.ServiceNodes{}, 1779 }, 1780 // Multiple filter values 1781 { 1782 filters: map[string]string{"somekey": "somevalue", "common": "1"}, 1783 services: structs.ServiceNodes{&structs.ServiceNode{Node: "foo", ServiceID: "db"}}, 1784 }, 1785 // Multiple filter values, tag 1786 { 1787 filters: map[string]string{"somekey": "somevalue", "common": "1"}, 1788 tags: []string{"primary"}, 1789 services: structs.ServiceNodes{&structs.ServiceNode{Node: "foo", ServiceID: "db"}}, 1790 }, 1791 // Common meta filter, single tag 1792 { 1793 filters: map[string]string{"common": "1"}, 1794 tags: []string{"v2"}, 1795 services: structs.ServiceNodes{ 1796 &structs.ServiceNode{Node: "bar", ServiceID: "db2"}, 1797 &structs.ServiceNode{Node: "foo", ServiceID: "db"}, 1798 }, 1799 }, 1800 // Common meta filter, multiple tags 1801 { 1802 filters: map[string]string{"common": "1"}, 1803 tags: []string{"v2", "primary"}, 1804 services: structs.ServiceNodes{&structs.ServiceNode{Node: "foo", ServiceID: "db"}}, 1805 }, 1806 } 1807 1808 for _, tc := range cases { 1809 args := structs.ServiceSpecificRequest{ 1810 Datacenter: "dc1", 1811 NodeMetaFilters: tc.filters, 1812 ServiceName: "db", 1813 ServiceTags: tc.tags, 1814 TagFilter: len(tc.tags) > 0, 1815 } 1816 var out structs.IndexedServiceNodes 1817 require.NoError(t, msgpackrpc.CallWithCodec(codec, "Catalog.ServiceNodes", &args, &out)) 1818 require.Len(t, out.ServiceNodes, len(tc.services)) 1819 1820 for i, serviceNode := range out.ServiceNodes { 1821 if serviceNode.Node != tc.services[i].Node || serviceNode.ServiceID != tc.services[i].ServiceID { 1822 t.Fatalf("bad: %v, %v filters: %v", serviceNode, tc.services[i], tc.filters) 1823 } 1824 } 1825 } 1826 } 1827 1828 func TestCatalog_ListServiceNodes_DistanceSort(t *testing.T) { 1829 t.Parallel() 1830 dir1, s1 := testServer(t) 1831 defer os.RemoveAll(dir1) 1832 defer s1.Shutdown() 1833 codec := rpcClient(t, s1) 1834 defer codec.Close() 1835 1836 args := structs.ServiceSpecificRequest{ 1837 Datacenter: "dc1", 1838 ServiceName: "db", 1839 } 1840 var out structs.IndexedServiceNodes 1841 err := msgpackrpc.CallWithCodec(codec, "Catalog.ServiceNodes", &args, &out) 1842 if err != nil { 1843 t.Fatalf("err: %v", err) 1844 } 1845 1846 testrpc.WaitForLeader(t, s1.RPC, "dc1") 1847 1848 // Add a few nodes for the associated services. 1849 s1.fsm.State().EnsureNode(1, &structs.Node{Node: "aaa", Address: "127.0.0.1"}) 1850 s1.fsm.State().EnsureService(2, "aaa", &structs.NodeService{ID: "db", Service: "db", Tags: []string{"primary"}, Address: "127.0.0.1", Port: 5000}) 1851 s1.fsm.State().EnsureNode(3, &structs.Node{Node: "foo", Address: "127.0.0.2"}) 1852 s1.fsm.State().EnsureService(4, "foo", &structs.NodeService{ID: "db", Service: "db", Tags: []string{"primary"}, Address: "127.0.0.2", Port: 5000}) 1853 s1.fsm.State().EnsureNode(5, &structs.Node{Node: "bar", Address: "127.0.0.3"}) 1854 s1.fsm.State().EnsureService(6, "bar", &structs.NodeService{ID: "db", Service: "db", Tags: []string{"primary"}, Address: "127.0.0.3", Port: 5000}) 1855 s1.fsm.State().EnsureNode(7, &structs.Node{Node: "baz", Address: "127.0.0.4"}) 1856 s1.fsm.State().EnsureService(8, "baz", &structs.NodeService{ID: "db", Service: "db", Tags: []string{"primary"}, Address: "127.0.0.4", Port: 5000}) 1857 1858 // Set all but one of the nodes to known coordinates. 1859 updates := structs.Coordinates{ 1860 {Node: "foo", Coord: lib.GenerateCoordinate(2 * time.Millisecond)}, 1861 {Node: "bar", Coord: lib.GenerateCoordinate(5 * time.Millisecond)}, 1862 {Node: "baz", Coord: lib.GenerateCoordinate(1 * time.Millisecond)}, 1863 } 1864 if err := s1.fsm.State().CoordinateBatchUpdate(9, updates); err != nil { 1865 t.Fatalf("err: %v", err) 1866 } 1867 1868 // Query with no given source node, should get the natural order from 1869 // the index. 1870 if err := msgpackrpc.CallWithCodec(codec, "Catalog.ServiceNodes", &args, &out); err != nil { 1871 t.Fatalf("err: %v", err) 1872 } 1873 if len(out.ServiceNodes) != 4 { 1874 t.Fatalf("bad: %v", out) 1875 } 1876 if out.ServiceNodes[0].Node != "aaa" { 1877 t.Fatalf("bad: %v", out) 1878 } 1879 if out.ServiceNodes[1].Node != "bar" { 1880 t.Fatalf("bad: %v", out) 1881 } 1882 if out.ServiceNodes[2].Node != "baz" { 1883 t.Fatalf("bad: %v", out) 1884 } 1885 if out.ServiceNodes[3].Node != "foo" { 1886 t.Fatalf("bad: %v", out) 1887 } 1888 1889 // Query relative to foo, note that there's no known coordinate for "aaa" 1890 // so it will go at the end. 1891 args = structs.ServiceSpecificRequest{ 1892 Datacenter: "dc1", 1893 ServiceName: "db", 1894 Source: structs.QuerySource{Datacenter: "dc1", Node: "foo"}, 1895 } 1896 if err := msgpackrpc.CallWithCodec(codec, "Catalog.ServiceNodes", &args, &out); err != nil { 1897 t.Fatalf("err: %v", err) 1898 } 1899 if len(out.ServiceNodes) != 4 { 1900 t.Fatalf("bad: %v", out) 1901 } 1902 if out.ServiceNodes[0].Node != "foo" { 1903 t.Fatalf("bad: %v", out) 1904 } 1905 if out.ServiceNodes[1].Node != "baz" { 1906 t.Fatalf("bad: %v", out) 1907 } 1908 if out.ServiceNodes[2].Node != "bar" { 1909 t.Fatalf("bad: %v", out) 1910 } 1911 if out.ServiceNodes[3].Node != "aaa" { 1912 t.Fatalf("bad: %v", out) 1913 } 1914 } 1915 1916 func TestCatalog_ListServiceNodes_ConnectProxy(t *testing.T) { 1917 t.Parallel() 1918 1919 assert := assert.New(t) 1920 dir1, s1 := testServer(t) 1921 defer os.RemoveAll(dir1) 1922 defer s1.Shutdown() 1923 codec := rpcClient(t, s1) 1924 defer codec.Close() 1925 1926 testrpc.WaitForLeader(t, s1.RPC, "dc1") 1927 1928 // Register the service 1929 args := structs.TestRegisterRequestProxy(t) 1930 var out struct{} 1931 assert.Nil(msgpackrpc.CallWithCodec(codec, "Catalog.Register", args, &out)) 1932 1933 // List 1934 req := structs.ServiceSpecificRequest{ 1935 Datacenter: "dc1", 1936 ServiceName: args.Service.Service, 1937 TagFilter: false, 1938 } 1939 var resp structs.IndexedServiceNodes 1940 assert.Nil(msgpackrpc.CallWithCodec(codec, "Catalog.ServiceNodes", &req, &resp)) 1941 assert.Len(resp.ServiceNodes, 1) 1942 v := resp.ServiceNodes[0] 1943 assert.Equal(structs.ServiceKindConnectProxy, v.ServiceKind) 1944 assert.Equal(args.Service.Proxy.DestinationServiceName, v.ServiceProxy.DestinationServiceName) 1945 } 1946 1947 func TestCatalog_ListServiceNodes_ConnectDestination(t *testing.T) { 1948 t.Parallel() 1949 1950 assert := assert.New(t) 1951 dir1, s1 := testServer(t) 1952 defer os.RemoveAll(dir1) 1953 defer s1.Shutdown() 1954 codec := rpcClient(t, s1) 1955 defer codec.Close() 1956 1957 testrpc.WaitForLeader(t, s1.RPC, "dc1") 1958 1959 // Register the proxy service 1960 args := structs.TestRegisterRequestProxy(t) 1961 var out struct{} 1962 assert.Nil(msgpackrpc.CallWithCodec(codec, "Catalog.Register", args, &out)) 1963 1964 // Register the service 1965 { 1966 dst := args.Service.Proxy.DestinationServiceName 1967 args := structs.TestRegisterRequest(t) 1968 args.Service.Service = dst 1969 var out struct{} 1970 assert.Nil(msgpackrpc.CallWithCodec(codec, "Catalog.Register", args, &out)) 1971 } 1972 1973 // List 1974 req := structs.ServiceSpecificRequest{ 1975 Connect: true, 1976 Datacenter: "dc1", 1977 ServiceName: args.Service.Proxy.DestinationServiceName, 1978 } 1979 var resp structs.IndexedServiceNodes 1980 assert.Nil(msgpackrpc.CallWithCodec(codec, "Catalog.ServiceNodes", &req, &resp)) 1981 assert.Len(resp.ServiceNodes, 1) 1982 v := resp.ServiceNodes[0] 1983 assert.Equal(structs.ServiceKindConnectProxy, v.ServiceKind) 1984 assert.Equal(args.Service.Proxy.DestinationServiceName, v.ServiceProxy.DestinationServiceName) 1985 1986 // List by non-Connect 1987 req = structs.ServiceSpecificRequest{ 1988 Datacenter: "dc1", 1989 ServiceName: args.Service.Proxy.DestinationServiceName, 1990 } 1991 assert.Nil(msgpackrpc.CallWithCodec(codec, "Catalog.ServiceNodes", &req, &resp)) 1992 assert.Len(resp.ServiceNodes, 1) 1993 v = resp.ServiceNodes[0] 1994 assert.Equal(args.Service.Proxy.DestinationServiceName, v.ServiceName) 1995 assert.Equal("", v.ServiceProxy.DestinationServiceName) 1996 } 1997 1998 // Test that calling ServiceNodes with Connect: true will return 1999 // Connect native services. 2000 func TestCatalog_ListServiceNodes_ConnectDestinationNative(t *testing.T) { 2001 t.Parallel() 2002 2003 require := require.New(t) 2004 dir1, s1 := testServer(t) 2005 defer os.RemoveAll(dir1) 2006 defer s1.Shutdown() 2007 codec := rpcClient(t, s1) 2008 defer codec.Close() 2009 2010 testrpc.WaitForLeader(t, s1.RPC, "dc1") 2011 2012 // Register the native service 2013 args := structs.TestRegisterRequest(t) 2014 args.Service.Connect.Native = true 2015 var out struct{} 2016 require.Nil(msgpackrpc.CallWithCodec(codec, "Catalog.Register", args, &out)) 2017 2018 // List 2019 req := structs.ServiceSpecificRequest{ 2020 Connect: true, 2021 Datacenter: "dc1", 2022 ServiceName: args.Service.Service, 2023 } 2024 var resp structs.IndexedServiceNodes 2025 require.Nil(msgpackrpc.CallWithCodec(codec, "Catalog.ServiceNodes", &req, &resp)) 2026 require.Len(resp.ServiceNodes, 1) 2027 v := resp.ServiceNodes[0] 2028 require.Equal(args.Service.Service, v.ServiceName) 2029 2030 // List by non-Connect 2031 req = structs.ServiceSpecificRequest{ 2032 Datacenter: "dc1", 2033 ServiceName: args.Service.Service, 2034 } 2035 require.Nil(msgpackrpc.CallWithCodec(codec, "Catalog.ServiceNodes", &req, &resp)) 2036 require.Len(resp.ServiceNodes, 1) 2037 v = resp.ServiceNodes[0] 2038 require.Equal(args.Service.Service, v.ServiceName) 2039 } 2040 2041 func TestCatalog_ListServiceNodes_ConnectProxy_ACL(t *testing.T) { 2042 t.Parallel() 2043 2044 assert := assert.New(t) 2045 dir1, s1 := testServerWithConfig(t, func(c *Config) { 2046 c.ACLDatacenter = "dc1" 2047 c.ACLsEnabled = true 2048 c.ACLMasterToken = "root" 2049 c.ACLDefaultPolicy = "deny" 2050 }) 2051 defer os.RemoveAll(dir1) 2052 defer s1.Shutdown() 2053 codec := rpcClient(t, s1) 2054 defer codec.Close() 2055 2056 testrpc.WaitForLeader(t, s1.RPC, "dc1") 2057 2058 // Create the ACL. 2059 arg := structs.ACLRequest{ 2060 Datacenter: "dc1", 2061 Op: structs.ACLSet, 2062 ACL: structs.ACL{ 2063 Name: "User token", 2064 Type: structs.ACLTokenTypeClient, 2065 Rules: ` 2066 service "foo" { 2067 policy = "write" 2068 } 2069 `, 2070 }, 2071 WriteRequest: structs.WriteRequest{Token: "root"}, 2072 } 2073 var token string 2074 assert.Nil(msgpackrpc.CallWithCodec(codec, "ACL.Apply", &arg, &token)) 2075 2076 { 2077 // Register a proxy 2078 args := structs.TestRegisterRequestProxy(t) 2079 args.Service.Service = "foo-proxy" 2080 args.Service.Proxy.DestinationServiceName = "bar" 2081 args.WriteRequest.Token = "root" 2082 var out struct{} 2083 assert.Nil(msgpackrpc.CallWithCodec(codec, "Catalog.Register", &args, &out)) 2084 2085 // Register a proxy 2086 args = structs.TestRegisterRequestProxy(t) 2087 args.Service.Service = "foo-proxy" 2088 args.Service.Proxy.DestinationServiceName = "foo" 2089 args.WriteRequest.Token = "root" 2090 assert.Nil(msgpackrpc.CallWithCodec(codec, "Catalog.Register", &args, &out)) 2091 2092 // Register a proxy 2093 args = structs.TestRegisterRequestProxy(t) 2094 args.Service.Service = "another-proxy" 2095 args.Service.Proxy.DestinationServiceName = "foo" 2096 args.WriteRequest.Token = "root" 2097 assert.Nil(msgpackrpc.CallWithCodec(codec, "Catalog.Register", &args, &out)) 2098 } 2099 2100 // List w/ token. This should disallow because we don't have permission 2101 // to read "bar" 2102 req := structs.ServiceSpecificRequest{ 2103 Connect: true, 2104 Datacenter: "dc1", 2105 ServiceName: "bar", 2106 QueryOptions: structs.QueryOptions{Token: token}, 2107 } 2108 var resp structs.IndexedServiceNodes 2109 assert.Nil(msgpackrpc.CallWithCodec(codec, "Catalog.ServiceNodes", &req, &resp)) 2110 assert.Len(resp.ServiceNodes, 0) 2111 2112 // List w/ token. This should work since we're requesting "foo", but should 2113 // also only contain the proxies with names that adhere to our ACL. 2114 req = structs.ServiceSpecificRequest{ 2115 Connect: true, 2116 Datacenter: "dc1", 2117 ServiceName: "foo", 2118 QueryOptions: structs.QueryOptions{Token: token}, 2119 } 2120 assert.Nil(msgpackrpc.CallWithCodec(codec, "Catalog.ServiceNodes", &req, &resp)) 2121 assert.Len(resp.ServiceNodes, 1) 2122 v := resp.ServiceNodes[0] 2123 assert.Equal("foo-proxy", v.ServiceName) 2124 } 2125 2126 func TestCatalog_ListServiceNodes_ConnectNative(t *testing.T) { 2127 t.Parallel() 2128 2129 assert := assert.New(t) 2130 dir1, s1 := testServer(t) 2131 defer os.RemoveAll(dir1) 2132 defer s1.Shutdown() 2133 codec := rpcClient(t, s1) 2134 defer codec.Close() 2135 2136 testrpc.WaitForLeader(t, s1.RPC, "dc1") 2137 2138 // Register the service 2139 args := structs.TestRegisterRequest(t) 2140 args.Service.Connect.Native = true 2141 var out struct{} 2142 assert.Nil(msgpackrpc.CallWithCodec(codec, "Catalog.Register", args, &out)) 2143 2144 // List 2145 req := structs.ServiceSpecificRequest{ 2146 Datacenter: "dc1", 2147 ServiceName: args.Service.Service, 2148 TagFilter: false, 2149 } 2150 var resp structs.IndexedServiceNodes 2151 assert.Nil(msgpackrpc.CallWithCodec(codec, "Catalog.ServiceNodes", &req, &resp)) 2152 assert.Len(resp.ServiceNodes, 1) 2153 v := resp.ServiceNodes[0] 2154 assert.Equal(args.Service.Connect.Native, v.ServiceConnect.Native) 2155 } 2156 2157 func TestCatalog_NodeServices(t *testing.T) { 2158 t.Parallel() 2159 dir1, s1 := testServer(t) 2160 defer os.RemoveAll(dir1) 2161 defer s1.Shutdown() 2162 codec := rpcClient(t, s1) 2163 defer codec.Close() 2164 testrpc.WaitForTestAgent(t, s1.RPC, "dc1") 2165 2166 args := structs.NodeSpecificRequest{ 2167 Datacenter: "dc1", 2168 Node: "foo", 2169 } 2170 var out structs.IndexedNodeServices 2171 err := msgpackrpc.CallWithCodec(codec, "Catalog.NodeServices", &args, &out) 2172 if err != nil { 2173 t.Fatalf("err: %v", err) 2174 } 2175 2176 testrpc.WaitForLeader(t, s1.RPC, "dc1") 2177 2178 // Just add a node 2179 if err := s1.fsm.State().EnsureNode(1, &structs.Node{Node: "foo", Address: "127.0.0.1"}); err != nil { 2180 t.Fatalf("err: %v", err) 2181 } 2182 if err := s1.fsm.State().EnsureService(2, "foo", &structs.NodeService{ID: "db", Service: "db", Tags: []string{"primary"}, Address: "127.0.0.1", Port: 5000}); err != nil { 2183 t.Fatalf("err: %v", err) 2184 } 2185 if err := s1.fsm.State().EnsureService(3, "foo", &structs.NodeService{ID: "web", Service: "web", Tags: nil, Address: "127.0.0.1", Port: 80}); err != nil { 2186 t.Fatalf("err: %v", err) 2187 } 2188 2189 if err := msgpackrpc.CallWithCodec(codec, "Catalog.NodeServices", &args, &out); err != nil { 2190 t.Fatalf("err: %v", err) 2191 } 2192 2193 if out.NodeServices.Node.Address != "127.0.0.1" { 2194 t.Fatalf("bad: %v", out) 2195 } 2196 if len(out.NodeServices.Services) != 2 { 2197 t.Fatalf("bad: %v", out) 2198 } 2199 services := out.NodeServices.Services 2200 if !lib.StrContains(services["db"].Tags, "primary") || services["db"].Port != 5000 { 2201 t.Fatalf("bad: %v", out) 2202 } 2203 if len(services["web"].Tags) != 0 || services["web"].Port != 80 { 2204 t.Fatalf("bad: %v", out) 2205 } 2206 } 2207 2208 func TestCatalog_NodeServices_ConnectProxy(t *testing.T) { 2209 t.Parallel() 2210 2211 assert := assert.New(t) 2212 dir1, s1 := testServer(t) 2213 defer os.RemoveAll(dir1) 2214 defer s1.Shutdown() 2215 codec := rpcClient(t, s1) 2216 defer codec.Close() 2217 2218 testrpc.WaitForTestAgent(t, s1.RPC, "dc1") 2219 2220 // Register the service 2221 args := structs.TestRegisterRequestProxy(t) 2222 var out struct{} 2223 assert.Nil(msgpackrpc.CallWithCodec(codec, "Catalog.Register", args, &out)) 2224 2225 // List 2226 req := structs.NodeSpecificRequest{ 2227 Datacenter: "dc1", 2228 Node: args.Node, 2229 } 2230 var resp structs.IndexedNodeServices 2231 assert.Nil(msgpackrpc.CallWithCodec(codec, "Catalog.NodeServices", &req, &resp)) 2232 2233 assert.Len(resp.NodeServices.Services, 1) 2234 v := resp.NodeServices.Services[args.Service.Service] 2235 assert.Equal(structs.ServiceKindConnectProxy, v.Kind) 2236 assert.Equal(args.Service.Proxy.DestinationServiceName, v.Proxy.DestinationServiceName) 2237 } 2238 2239 func TestCatalog_NodeServices_ConnectNative(t *testing.T) { 2240 t.Parallel() 2241 2242 assert := assert.New(t) 2243 dir1, s1 := testServer(t) 2244 defer os.RemoveAll(dir1) 2245 defer s1.Shutdown() 2246 codec := rpcClient(t, s1) 2247 defer codec.Close() 2248 2249 testrpc.WaitForTestAgent(t, s1.RPC, "dc1") 2250 2251 // Register the service 2252 args := structs.TestRegisterRequest(t) 2253 var out struct{} 2254 assert.Nil(msgpackrpc.CallWithCodec(codec, "Catalog.Register", args, &out)) 2255 2256 // List 2257 req := structs.NodeSpecificRequest{ 2258 Datacenter: "dc1", 2259 Node: args.Node, 2260 } 2261 var resp structs.IndexedNodeServices 2262 assert.Nil(msgpackrpc.CallWithCodec(codec, "Catalog.NodeServices", &req, &resp)) 2263 2264 assert.Len(resp.NodeServices.Services, 1) 2265 v := resp.NodeServices.Services[args.Service.Service] 2266 assert.Equal(args.Service.Connect.Native, v.Connect.Native) 2267 } 2268 2269 // Used to check for a regression against a known bug 2270 func TestCatalog_Register_FailedCase1(t *testing.T) { 2271 t.Parallel() 2272 dir1, s1 := testServer(t) 2273 defer os.RemoveAll(dir1) 2274 defer s1.Shutdown() 2275 codec := rpcClient(t, s1) 2276 defer codec.Close() 2277 2278 arg := structs.RegisterRequest{ 2279 Datacenter: "dc1", 2280 Node: "bar", 2281 Address: "127.0.0.2", 2282 Service: &structs.NodeService{ 2283 Service: "web", 2284 Tags: nil, 2285 Port: 8000, 2286 }, 2287 } 2288 var out struct{} 2289 2290 err := msgpackrpc.CallWithCodec(codec, "Catalog.Register", &arg, &out) 2291 if err != nil { 2292 t.Fatalf("err: %v", err) 2293 } 2294 2295 testrpc.WaitForLeader(t, s1.RPC, "dc1") 2296 2297 if err := msgpackrpc.CallWithCodec(codec, "Catalog.Register", &arg, &out); err != nil { 2298 t.Fatalf("err: %v", err) 2299 } 2300 2301 // Check we can get this back 2302 query := &structs.ServiceSpecificRequest{ 2303 Datacenter: "dc1", 2304 ServiceName: "web", 2305 } 2306 var out2 structs.IndexedServiceNodes 2307 if err := msgpackrpc.CallWithCodec(codec, "Catalog.ServiceNodes", query, &out2); err != nil { 2308 t.Fatalf("err: %v", err) 2309 } 2310 2311 // Check the output 2312 if len(out2.ServiceNodes) != 1 { 2313 t.Fatalf("Bad: %v", out2) 2314 } 2315 } 2316 2317 func testACLFilterServer(t *testing.T) (dir, token string, srv *Server, codec rpc.ClientCodec) { 2318 dir, srv = testServerWithConfig(t, func(c *Config) { 2319 c.ACLDatacenter = "dc1" 2320 c.ACLsEnabled = true 2321 c.ACLMasterToken = "root" 2322 c.ACLDefaultPolicy = "deny" 2323 c.ACLEnforceVersion8 = false 2324 }) 2325 2326 codec = rpcClient(t, srv) 2327 testrpc.WaitForLeader(t, srv.RPC, "dc1") 2328 2329 // Create a new token 2330 arg := structs.ACLRequest{ 2331 Datacenter: "dc1", 2332 Op: structs.ACLSet, 2333 ACL: structs.ACL{ 2334 Name: "User token", 2335 Type: structs.ACLTokenTypeClient, 2336 Rules: ` 2337 service "foo" { 2338 policy = "write" 2339 } 2340 `, 2341 }, 2342 WriteRequest: structs.WriteRequest{Token: "root"}, 2343 } 2344 if err := msgpackrpc.CallWithCodec(codec, "ACL.Apply", &arg, &token); err != nil { 2345 t.Fatalf("err: %v", err) 2346 } 2347 2348 // Register a service 2349 regArg := structs.RegisterRequest{ 2350 Datacenter: "dc1", 2351 Node: srv.config.NodeName, 2352 Address: "127.0.0.1", 2353 Service: &structs.NodeService{ 2354 ID: "foo", 2355 Service: "foo", 2356 }, 2357 Check: &structs.HealthCheck{ 2358 CheckID: "service:foo", 2359 Name: "service:foo", 2360 ServiceID: "foo", 2361 Status: api.HealthPassing, 2362 }, 2363 WriteRequest: structs.WriteRequest{Token: "root"}, 2364 } 2365 if err := msgpackrpc.CallWithCodec(codec, "Catalog.Register", ®Arg, nil); err != nil { 2366 t.Fatalf("err: %s", err) 2367 } 2368 2369 // Register a service which should be denied 2370 regArg = structs.RegisterRequest{ 2371 Datacenter: "dc1", 2372 Node: srv.config.NodeName, 2373 Address: "127.0.0.1", 2374 Service: &structs.NodeService{ 2375 ID: "bar", 2376 Service: "bar", 2377 }, 2378 Check: &structs.HealthCheck{ 2379 CheckID: "service:bar", 2380 Name: "service:bar", 2381 ServiceID: "bar", 2382 }, 2383 WriteRequest: structs.WriteRequest{Token: "root"}, 2384 } 2385 if err := msgpackrpc.CallWithCodec(codec, "Catalog.Register", ®Arg, nil); err != nil { 2386 t.Fatalf("err: %s", err) 2387 } 2388 return 2389 } 2390 2391 func TestCatalog_ListServices_FilterACL(t *testing.T) { 2392 t.Parallel() 2393 dir, token, srv, codec := testACLFilterServer(t) 2394 defer os.RemoveAll(dir) 2395 defer srv.Shutdown() 2396 defer codec.Close() 2397 testrpc.WaitForTestAgent(t, srv.RPC, "dc1") 2398 2399 opt := structs.DCSpecificRequest{ 2400 Datacenter: "dc1", 2401 QueryOptions: structs.QueryOptions{Token: token}, 2402 } 2403 reply := structs.IndexedServices{} 2404 if err := msgpackrpc.CallWithCodec(codec, "Catalog.ListServices", &opt, &reply); err != nil { 2405 t.Fatalf("err: %s", err) 2406 } 2407 if _, ok := reply.Services["foo"]; !ok { 2408 t.Fatalf("bad: %#v", reply.Services) 2409 } 2410 if _, ok := reply.Services["bar"]; ok { 2411 t.Fatalf("bad: %#v", reply.Services) 2412 } 2413 } 2414 2415 func TestCatalog_ServiceNodes_FilterACL(t *testing.T) { 2416 t.Parallel() 2417 dir, token, srv, codec := testACLFilterServer(t) 2418 defer os.RemoveAll(dir) 2419 defer srv.Shutdown() 2420 defer codec.Close() 2421 2422 opt := structs.ServiceSpecificRequest{ 2423 Datacenter: "dc1", 2424 ServiceName: "foo", 2425 QueryOptions: structs.QueryOptions{Token: token}, 2426 } 2427 reply := structs.IndexedServiceNodes{} 2428 if err := msgpackrpc.CallWithCodec(codec, "Catalog.ServiceNodes", &opt, &reply); err != nil { 2429 t.Fatalf("err: %s", err) 2430 } 2431 found := false 2432 for _, sn := range reply.ServiceNodes { 2433 if sn.ServiceID == "foo" { 2434 found = true 2435 break 2436 } 2437 } 2438 if !found { 2439 t.Fatalf("bad: %#v", reply.ServiceNodes) 2440 } 2441 2442 // Filters services we can't access 2443 opt = structs.ServiceSpecificRequest{ 2444 Datacenter: "dc1", 2445 ServiceName: "bar", 2446 QueryOptions: structs.QueryOptions{Token: token}, 2447 } 2448 reply = structs.IndexedServiceNodes{} 2449 if err := msgpackrpc.CallWithCodec(codec, "Catalog.ServiceNodes", &opt, &reply); err != nil { 2450 t.Fatalf("err: %s", err) 2451 } 2452 for _, sn := range reply.ServiceNodes { 2453 if sn.ServiceID == "bar" { 2454 t.Fatalf("bad: %#v", reply.ServiceNodes) 2455 } 2456 } 2457 2458 // We've already proven that we call the ACL filtering function so we 2459 // test node filtering down in acl.go for node cases. This also proves 2460 // that we respect the version 8 ACL flag, since the test server sets 2461 // that to false (the regression value of *not* changing this is better 2462 // for now until we change the sense of the version 8 ACL flag). 2463 } 2464 2465 func TestCatalog_NodeServices_ACLDeny(t *testing.T) { 2466 t.Parallel() 2467 dir1, s1 := testServerWithConfig(t, func(c *Config) { 2468 c.ACLDatacenter = "dc1" 2469 c.ACLsEnabled = true 2470 c.ACLMasterToken = "root" 2471 c.ACLDefaultPolicy = "deny" 2472 c.ACLEnforceVersion8 = false 2473 }) 2474 defer os.RemoveAll(dir1) 2475 defer s1.Shutdown() 2476 codec := rpcClient(t, s1) 2477 defer codec.Close() 2478 2479 testrpc.WaitForTestAgent(t, s1.RPC, "dc1") 2480 2481 // Prior to version 8, the node policy should be ignored. 2482 args := structs.NodeSpecificRequest{ 2483 Datacenter: "dc1", 2484 Node: s1.config.NodeName, 2485 } 2486 reply := structs.IndexedNodeServices{} 2487 if err := msgpackrpc.CallWithCodec(codec, "Catalog.NodeServices", &args, &reply); err != nil { 2488 t.Fatalf("err: %v", err) 2489 } 2490 if reply.NodeServices == nil { 2491 t.Fatalf("should not be nil") 2492 } 2493 2494 // Now turn on version 8 enforcement and try again. 2495 s1.config.ACLEnforceVersion8 = true 2496 if err := msgpackrpc.CallWithCodec(codec, "Catalog.NodeServices", &args, &reply); err != nil { 2497 t.Fatalf("err: %v", err) 2498 } 2499 if reply.NodeServices != nil { 2500 t.Fatalf("should not nil") 2501 } 2502 2503 // Create an ACL that can read the node. 2504 arg := structs.ACLRequest{ 2505 Datacenter: "dc1", 2506 Op: structs.ACLSet, 2507 ACL: structs.ACL{ 2508 Name: "User token", 2509 Type: structs.ACLTokenTypeClient, 2510 Rules: fmt.Sprintf(` 2511 node "%s" { 2512 policy = "read" 2513 } 2514 `, s1.config.NodeName), 2515 }, 2516 WriteRequest: structs.WriteRequest{Token: "root"}, 2517 } 2518 var id string 2519 if err := msgpackrpc.CallWithCodec(codec, "ACL.Apply", &arg, &id); err != nil { 2520 t.Fatalf("err: %v", err) 2521 } 2522 2523 // Now try with the token and it will go through. 2524 args.Token = id 2525 if err := msgpackrpc.CallWithCodec(codec, "Catalog.NodeServices", &args, &reply); err != nil { 2526 t.Fatalf("err: %v", err) 2527 } 2528 if reply.NodeServices == nil { 2529 t.Fatalf("should not be nil") 2530 } 2531 2532 // Make sure an unknown node doesn't cause trouble. 2533 args.Node = "nope" 2534 if err := msgpackrpc.CallWithCodec(codec, "Catalog.NodeServices", &args, &reply); err != nil { 2535 t.Fatalf("err: %v", err) 2536 } 2537 if reply.NodeServices != nil { 2538 t.Fatalf("should not nil") 2539 } 2540 } 2541 2542 func TestCatalog_NodeServices_FilterACL(t *testing.T) { 2543 t.Parallel() 2544 dir, token, srv, codec := testACLFilterServer(t) 2545 defer os.RemoveAll(dir) 2546 defer srv.Shutdown() 2547 defer codec.Close() 2548 testrpc.WaitForTestAgent(t, srv.RPC, "dc1") 2549 2550 opt := structs.NodeSpecificRequest{ 2551 Datacenter: "dc1", 2552 Node: srv.config.NodeName, 2553 QueryOptions: structs.QueryOptions{Token: token}, 2554 } 2555 reply := structs.IndexedNodeServices{} 2556 if err := msgpackrpc.CallWithCodec(codec, "Catalog.NodeServices", &opt, &reply); err != nil { 2557 t.Fatalf("err: %s", err) 2558 } 2559 found := false 2560 for _, svc := range reply.NodeServices.Services { 2561 if svc.ID == "bar" { 2562 t.Fatalf("bad: %#v", reply.NodeServices.Services) 2563 } 2564 if svc.ID == "foo" { 2565 found = true 2566 break 2567 } 2568 } 2569 if !found { 2570 t.Fatalf("bad: %#v", reply.NodeServices) 2571 } 2572 }