1package api 2 3import ( 4 "context" 5 "encoding/json" 6 "errors" 7 "fmt" 8 "io/ioutil" 9 "net/http" 10 "net/http/httptest" 11 "net/http/httputil" 12 "os" 13 "path/filepath" 14 "strings" 15 "testing" 16 "time" 17 18 "github.com/hashicorp/consul/sdk/testutil" 19 "github.com/hashicorp/consul/sdk/testutil/retry" 20 "github.com/hashicorp/serf/serf" 21 "github.com/stretchr/testify/require" 22) 23 24func TestAPI_AgentSelf(t *testing.T) { 25 t.Parallel() 26 c, s := makeClient(t) 27 defer s.Stop() 28 29 agent := c.Agent() 30 31 info, err := agent.Self() 32 if err != nil { 33 t.Fatalf("err: %v", err) 34 } 35 36 name := info["Config"]["NodeName"].(string) 37 if name == "" { 38 t.Fatalf("bad: %v", info) 39 } 40} 41 42func TestAPI_AgentMetrics(t *testing.T) { 43 t.Parallel() 44 c, s := makeClient(t) 45 defer s.Stop() 46 47 agent := c.Agent() 48 s.WaitForSerfCheck(t) 49 50 timer := &retry.Timer{Timeout: 10 * time.Second, Wait: 500 * time.Millisecond} 51 retry.RunWith(timer, t, func(r *retry.R) { 52 metrics, err := agent.Metrics() 53 if err != nil { 54 r.Fatalf("err: %v", err) 55 } 56 for _, g := range metrics.Gauges { 57 if g.Name == "consul.runtime.alloc_bytes" { 58 return 59 } 60 } 61 r.Fatalf("missing runtime metrics") 62 }) 63} 64 65func TestAPI_AgentHost(t *testing.T) { 66 t.Parallel() 67 c, s := makeClient(t) 68 defer s.Stop() 69 70 agent := c.Agent() 71 timer := &retry.Timer{} 72 retry.RunWith(timer, t, func(r *retry.R) { 73 host, err := agent.Host() 74 if err != nil { 75 r.Fatalf("err: %v", err) 76 } 77 78 // CollectionTime should exist on all responses 79 if host["CollectionTime"] == nil { 80 r.Fatalf("missing host response") 81 } 82 }) 83} 84 85func TestAPI_AgentReload(t *testing.T) { 86 t.Parallel() 87 88 // Create our initial empty config file, to be overwritten later 89 cfgDir := testutil.TempDir(t, "consul-config") 90 91 cfgFilePath := filepath.Join(cfgDir, "reload.json") 92 configFile, err := os.Create(cfgFilePath) 93 if err != nil { 94 t.Fatalf("Unable to create file %v, got error:%v", cfgFilePath, err) 95 } 96 97 c, s := makeClientWithConfig(t, nil, func(conf *testutil.TestServerConfig) { 98 conf.Args = []string{"-config-file", configFile.Name()} 99 }) 100 defer s.Stop() 101 102 agent := c.Agent() 103 104 // Update the config file with a service definition 105 config := `{"service":{"name":"redis", "port":1234, "Meta": {"some": "meta"}}}` 106 err = ioutil.WriteFile(configFile.Name(), []byte(config), 0644) 107 if err != nil { 108 t.Fatalf("err: %v", err) 109 } 110 111 if err = agent.Reload(); err != nil { 112 t.Fatalf("err: %v", err) 113 } 114 115 services, err := agent.Services() 116 if err != nil { 117 t.Fatalf("err: %v", err) 118 } 119 120 service, ok := services["redis"] 121 if !ok { 122 t.Fatalf("bad: %v", ok) 123 } 124 if service.Port != 1234 { 125 t.Fatalf("bad: %v", service.Port) 126 } 127 if service.Meta["some"] != "meta" { 128 t.Fatalf("Missing metadata some:=meta in %v", service) 129 } 130} 131 132func TestAPI_AgentMembersOpts(t *testing.T) { 133 t.Parallel() 134 c, s1 := makeClient(t) 135 _, s2 := makeClientWithConfig(t, nil, func(c *testutil.TestServerConfig) { 136 c.Datacenter = "dc2" 137 }) 138 defer s1.Stop() 139 defer s2.Stop() 140 141 agent := c.Agent() 142 143 s2.JoinWAN(t, s1.WANAddr) 144 145 members, err := agent.MembersOpts(MembersOpts{WAN: true}) 146 if err != nil { 147 t.Fatalf("err: %v", err) 148 } 149 150 if len(members) != 2 { 151 t.Fatalf("bad: %v", members) 152 } 153} 154 155func TestAPI_AgentMembers(t *testing.T) { 156 t.Parallel() 157 c, s := makeClient(t) 158 defer s.Stop() 159 160 agent := c.Agent() 161 162 members, err := agent.Members(false) 163 if err != nil { 164 t.Fatalf("err: %v", err) 165 } 166 167 if len(members) != 1 { 168 t.Fatalf("bad: %v", members) 169 } 170} 171 172func TestAPI_AgentServiceAndReplaceChecks(t *testing.T) { 173 t.Parallel() 174 c, s := makeClient(t) 175 defer s.Stop() 176 177 agent := c.Agent() 178 s.WaitForSerfCheck(t) 179 180 reg := &AgentServiceRegistration{ 181 Name: "foo", 182 ID: "foo", 183 Tags: []string{"bar", "baz"}, 184 TaggedAddresses: map[string]ServiceAddress{ 185 "lan": { 186 Address: "198.18.0.1", 187 Port: 80, 188 }, 189 }, 190 Port: 8000, 191 Check: &AgentServiceCheck{ 192 TTL: "15s", 193 }, 194 } 195 196 regupdate := &AgentServiceRegistration{ 197 Name: "foo", 198 ID: "foo", 199 Tags: []string{"bar", "baz"}, 200 TaggedAddresses: map[string]ServiceAddress{ 201 "lan": { 202 Address: "198.18.0.1", 203 Port: 80, 204 }, 205 }, 206 Port: 9000, 207 } 208 209 if err := agent.ServiceRegister(reg); err != nil { 210 t.Fatalf("err: %v", err) 211 } 212 213 ctx := context.Background() 214 opts := ServiceRegisterOpts{ReplaceExistingChecks: true}.WithContext(ctx) 215 if err := agent.ServiceRegisterOpts(regupdate, opts); err != nil { 216 t.Fatalf("err: %v", err) 217 } 218 219 services, err := agent.Services() 220 if err != nil { 221 t.Fatalf("err: %v", err) 222 } 223 224 if _, ok := services["foo"]; !ok { 225 t.Fatalf("missing service: %#v", services) 226 } 227 228 checks, err := agent.Checks() 229 if err != nil { 230 t.Fatalf("err: %v", err) 231 } 232 233 if len(checks) != 0 { 234 t.Fatalf("checks are not removed: %v", checks) 235 } 236 237 state, out, err := agent.AgentHealthServiceByID("foo") 238 require.Nil(t, err) 239 require.NotNil(t, out) 240 require.Equal(t, HealthPassing, state) 241 require.Equal(t, 9000, out.Service.Port) 242 243 state, outs, err := agent.AgentHealthServiceByName("foo") 244 require.Nil(t, err) 245 require.NotNil(t, outs) 246 require.Equal(t, HealthPassing, state) 247 require.Equal(t, 9000, outs[0].Service.Port) 248 249 if err := agent.ServiceDeregister("foo"); err != nil { 250 t.Fatalf("err: %v", err) 251 } 252} 253 254func TestAgent_ServiceRegisterOpts_WithContextTimeout(t *testing.T) { 255 c, err := NewClient(DefaultConfig()) 256 require.NoError(t, err) 257 258 ctx, cancel := context.WithTimeout(context.Background(), time.Nanosecond) 259 t.Cleanup(cancel) 260 261 opts := ServiceRegisterOpts{}.WithContext(ctx) 262 err = c.Agent().ServiceRegisterOpts(&AgentServiceRegistration{}, opts) 263 require.True(t, errors.Is(err, context.DeadlineExceeded), "expected timeout") 264} 265 266func TestAPI_AgentServices(t *testing.T) { 267 t.Parallel() 268 c, s := makeClient(t) 269 defer s.Stop() 270 271 agent := c.Agent() 272 s.WaitForSerfCheck(t) 273 274 reg := &AgentServiceRegistration{ 275 Name: "foo", 276 ID: "foo", 277 Tags: []string{"bar", "baz"}, 278 TaggedAddresses: map[string]ServiceAddress{ 279 "lan": { 280 Address: "198.18.0.1", 281 Port: 80, 282 }, 283 }, 284 Port: 8000, 285 Check: &AgentServiceCheck{ 286 TTL: "15s", 287 }, 288 } 289 if err := agent.ServiceRegister(reg); err != nil { 290 t.Fatalf("err: %v", err) 291 } 292 293 services, err := agent.Services() 294 if err != nil { 295 t.Fatalf("err: %v", err) 296 } 297 if _, ok := services["foo"]; !ok { 298 t.Fatalf("missing service: %#v", services) 299 } 300 checks, err := agent.Checks() 301 if err != nil { 302 t.Fatalf("err: %v", err) 303 } 304 chk, ok := checks["service:foo"] 305 if !ok { 306 t.Fatalf("missing check: %v", checks) 307 } 308 309 // Checks should default to critical 310 if chk.Status != HealthCritical { 311 t.Fatalf("Bad: %#v", chk) 312 } 313 314 state, out, err := agent.AgentHealthServiceByID("foo2") 315 require.Nil(t, err) 316 require.Nil(t, out) 317 require.Equal(t, HealthCritical, state) 318 319 state, out, err = agent.AgentHealthServiceByID("foo") 320 require.Nil(t, err) 321 require.NotNil(t, out) 322 require.Equal(t, HealthCritical, state) 323 require.Equal(t, 8000, out.Service.Port) 324 325 state, outs, err := agent.AgentHealthServiceByName("foo") 326 require.Nil(t, err) 327 require.NotNil(t, outs) 328 require.Equal(t, HealthCritical, state) 329 require.Equal(t, 8000, outs[0].Service.Port) 330 331 if err := agent.ServiceDeregister("foo"); err != nil { 332 t.Fatalf("err: %v", err) 333 } 334} 335 336func TestAPI_AgentServicesWithFilterOpts(t *testing.T) { 337 t.Parallel() 338 c, s := makeClient(t) 339 defer s.Stop() 340 341 agent := c.Agent() 342 343 reg := &AgentServiceRegistration{ 344 Name: "foo", 345 ID: "foo", 346 Tags: []string{"bar", "baz"}, 347 Port: 8000, 348 Check: &AgentServiceCheck{ 349 TTL: "15s", 350 }, 351 } 352 require.NoError(t, agent.ServiceRegister(reg)) 353 354 reg = &AgentServiceRegistration{ 355 Name: "foo", 356 ID: "foo2", 357 Tags: []string{"foo", "baz"}, 358 Port: 8001, 359 Check: &AgentServiceCheck{ 360 TTL: "15s", 361 }, 362 } 363 require.NoError(t, agent.ServiceRegister(reg)) 364 365 opts := &QueryOptions{Namespace: defaultNamespace} 366 services, err := agent.ServicesWithFilterOpts("foo in Tags", opts) 367 require.NoError(t, err) 368 require.Len(t, services, 1) 369 _, ok := services["foo2"] 370 require.True(t, ok) 371} 372 373func TestAPI_AgentServices_SidecarService(t *testing.T) { 374 t.Parallel() 375 c, s := makeClient(t) 376 defer s.Stop() 377 378 agent := c.Agent() 379 380 // Register service 381 reg := &AgentServiceRegistration{ 382 Name: "foo", 383 Port: 8000, 384 Connect: &AgentServiceConnect{ 385 SidecarService: &AgentServiceRegistration{}, 386 }, 387 } 388 if err := agent.ServiceRegister(reg); err != nil { 389 t.Fatalf("err: %v", err) 390 } 391 392 services, err := agent.Services() 393 if err != nil { 394 t.Fatalf("err: %v", err) 395 } 396 if _, ok := services["foo"]; !ok { 397 t.Fatalf("missing service: %v", services) 398 } 399 if _, ok := services["foo-sidecar-proxy"]; !ok { 400 t.Fatalf("missing sidecar service: %v", services) 401 } 402 403 if err := agent.ServiceDeregister("foo"); err != nil { 404 t.Fatalf("err: %v", err) 405 } 406 407 // Deregister should have removed both service and it's sidecar 408 services, err = agent.Services() 409 require.NoError(t, err) 410 411 if _, ok := services["foo"]; ok { 412 t.Fatalf("didn't remove service: %v", services) 413 } 414 if _, ok := services["foo-sidecar-proxy"]; ok { 415 t.Fatalf("didn't remove sidecar service: %v", services) 416 } 417} 418 419func TestAPI_AgentServices_ExternalConnectProxy(t *testing.T) { 420 t.Parallel() 421 c, s := makeClient(t) 422 defer s.Stop() 423 424 agent := c.Agent() 425 426 // Register service 427 reg := &AgentServiceRegistration{ 428 Name: "foo", 429 Port: 8000, 430 } 431 if err := agent.ServiceRegister(reg); err != nil { 432 t.Fatalf("err: %v", err) 433 } 434 // Register proxy 435 reg = &AgentServiceRegistration{ 436 Kind: ServiceKindConnectProxy, 437 Name: "foo-proxy", 438 Port: 8001, 439 Proxy: &AgentServiceConnectProxyConfig{ 440 DestinationServiceName: "foo", 441 Mode: ProxyModeTransparent, 442 }, 443 } 444 if err := agent.ServiceRegister(reg); err != nil { 445 t.Fatalf("err: %v", err) 446 } 447 448 services, err := agent.Services() 449 if err != nil { 450 t.Fatalf("err: %v", err) 451 } 452 if _, ok := services["foo"]; !ok { 453 t.Fatalf("missing service: %v", services) 454 } 455 if _, ok := services["foo-proxy"]; !ok { 456 t.Fatalf("missing proxy service: %v", services) 457 } 458 if services["foo-proxy"].Proxy.Mode != ProxyModeTransparent { 459 t.Fatalf("expected transparent proxy mode to be enabled") 460 } 461 462 if err := agent.ServiceDeregister("foo"); err != nil { 463 t.Fatalf("err: %v", err) 464 } 465 if err := agent.ServiceDeregister("foo-proxy"); err != nil { 466 t.Fatalf("err: %v", err) 467 } 468} 469 470func TestAPI_AgentServices_CheckPassing(t *testing.T) { 471 t.Parallel() 472 c, s := makeClient(t) 473 defer s.Stop() 474 475 agent := c.Agent() 476 reg := &AgentServiceRegistration{ 477 Name: "foo", 478 Tags: []string{"bar", "baz"}, 479 Port: 8000, 480 Check: &AgentServiceCheck{ 481 TTL: "15s", 482 Status: HealthPassing, 483 }, 484 } 485 if err := agent.ServiceRegister(reg); err != nil { 486 t.Fatalf("err: %v", err) 487 } 488 489 services, err := agent.Services() 490 if err != nil { 491 t.Fatalf("err: %v", err) 492 } 493 if _, ok := services["foo"]; !ok { 494 t.Fatalf("missing service: %v", services) 495 } 496 497 checks, err := agent.Checks() 498 if err != nil { 499 t.Fatalf("err: %v", err) 500 } 501 chk, ok := checks["service:foo"] 502 if !ok { 503 t.Fatalf("missing check: %v", checks) 504 } 505 506 if chk.Status != HealthPassing { 507 t.Fatalf("Bad: %#v", chk) 508 } 509 if err := agent.ServiceDeregister("foo"); err != nil { 510 t.Fatalf("err: %v", err) 511 } 512} 513 514func TestAPI_AgentServices_CheckBadStatus(t *testing.T) { 515 t.Parallel() 516 c, s := makeClient(t) 517 defer s.Stop() 518 519 agent := c.Agent() 520 reg := &AgentServiceRegistration{ 521 Name: "foo", 522 Tags: []string{"bar", "baz"}, 523 Port: 8000, 524 Check: &AgentServiceCheck{ 525 TTL: "15s", 526 Status: "fluffy", 527 }, 528 } 529 if err := agent.ServiceRegister(reg); err == nil { 530 t.Fatalf("bad status accepted") 531 } 532} 533 534func TestAPI_AgentServices_CheckID(t *testing.T) { 535 t.Parallel() 536 c, s := makeClient(t) 537 defer s.Stop() 538 539 agent := c.Agent() 540 reg := &AgentServiceRegistration{ 541 Name: "foo", 542 Tags: []string{"bar", "baz"}, 543 Port: 8000, 544 Check: &AgentServiceCheck{ 545 CheckID: "foo-ttl", 546 TTL: "15s", 547 }, 548 } 549 if err := agent.ServiceRegister(reg); err != nil { 550 t.Fatalf("err: %v", err) 551 } 552 553 checks, err := agent.Checks() 554 if err != nil { 555 t.Fatalf("err: %v", err) 556 } 557 if _, ok := checks["foo-ttl"]; !ok { 558 t.Fatalf("missing check: %v", checks) 559 } 560} 561 562func TestAPI_AgentServiceAddress(t *testing.T) { 563 t.Parallel() 564 c, s := makeClient(t) 565 defer s.Stop() 566 567 agent := c.Agent() 568 569 reg1 := &AgentServiceRegistration{ 570 Name: "foo1", 571 Port: 8000, 572 Address: "192.168.0.42", 573 } 574 reg2 := &AgentServiceRegistration{ 575 Name: "foo2", 576 Port: 8000, 577 TaggedAddresses: map[string]ServiceAddress{ 578 "lan": { 579 Address: "192.168.0.43", 580 Port: 8000, 581 }, 582 "wan": { 583 Address: "198.18.0.1", 584 Port: 80, 585 }, 586 }, 587 } 588 if err := agent.ServiceRegister(reg1); err != nil { 589 t.Fatalf("err: %v", err) 590 } 591 if err := agent.ServiceRegister(reg2); err != nil { 592 t.Fatalf("err: %v", err) 593 } 594 595 services, err := agent.Services() 596 if err != nil { 597 t.Fatalf("err: %v", err) 598 } 599 600 if _, ok := services["foo1"]; !ok { 601 t.Fatalf("missing service: %v", services) 602 } 603 if _, ok := services["foo2"]; !ok { 604 t.Fatalf("missing service: %v", services) 605 } 606 607 if services["foo1"].Address != "192.168.0.42" { 608 t.Fatalf("missing Address field in service foo1: %v", services) 609 } 610 if services["foo2"].Address != "" { 611 t.Fatalf("missing Address field in service foo2: %v", services) 612 } 613 require.NotNil(t, services["foo2"].TaggedAddresses) 614 require.Contains(t, services["foo2"].TaggedAddresses, "lan") 615 require.Contains(t, services["foo2"].TaggedAddresses, "wan") 616 require.Equal(t, services["foo2"].TaggedAddresses["lan"].Address, "192.168.0.43") 617 require.Equal(t, services["foo2"].TaggedAddresses["lan"].Port, 8000) 618 require.Equal(t, services["foo2"].TaggedAddresses["wan"].Address, "198.18.0.1") 619 require.Equal(t, services["foo2"].TaggedAddresses["wan"].Port, 80) 620 621 if err := agent.ServiceDeregister("foo"); err != nil { 622 t.Fatalf("err: %v", err) 623 } 624} 625func TestAPI_AgentServiceSocket(t *testing.T) { 626 t.Parallel() 627 c, s := makeClient(t) 628 defer s.Stop() 629 630 agent := c.Agent() 631 632 reg1 := &AgentServiceRegistration{ 633 Name: "foo1", 634 Port: 8000, 635 Address: "192.168.0.42", 636 } 637 reg2 := &AgentServiceRegistration{ 638 Name: "foo2", 639 SocketPath: "/tmp/foo2.sock", 640 } 641 642 if err := agent.ServiceRegister(reg1); err != nil { 643 t.Fatalf("err: %v", err) 644 } 645 if err := agent.ServiceRegister(reg2); err != nil { 646 t.Fatalf("err: %v", err) 647 } 648 649 services, err := agent.Services() 650 if err != nil { 651 t.Fatalf("err: %v", err) 652 } 653 654 require.Contains(t, services, "foo1", "missing service foo1") 655 require.Contains(t, services, "foo2", "missing service foo2") 656 657 require.Equal(t, "192.168.0.42", services["foo1"].Address, 658 "missing Address field in service foo1: %v", services["foo1"]) 659 660 require.Equal(t, "", services["foo2"].Address, 661 "unexpected Address field in service foo1: %v", services["foo2"]) 662 require.Equal(t, "/tmp/foo2.sock", services["foo2"].SocketPath, 663 "missing SocketPath field in service foo1: %v", services["foo2"]) 664} 665 666func TestAPI_AgentEnableTagOverride(t *testing.T) { 667 t.Parallel() 668 c, s := makeClient(t) 669 defer s.Stop() 670 671 agent := c.Agent() 672 673 reg1 := &AgentServiceRegistration{ 674 Name: "foo1", 675 Port: 8000, 676 Address: "192.168.0.42", 677 EnableTagOverride: true, 678 } 679 reg2 := &AgentServiceRegistration{ 680 Name: "foo2", 681 Port: 8000, 682 } 683 if err := agent.ServiceRegister(reg1); err != nil { 684 t.Fatalf("err: %v", err) 685 } 686 if err := agent.ServiceRegister(reg2); err != nil { 687 t.Fatalf("err: %v", err) 688 } 689 690 services, err := agent.Services() 691 if err != nil { 692 t.Fatalf("err: %v", err) 693 } 694 695 if _, ok := services["foo1"]; !ok { 696 t.Fatalf("missing service: %v", services) 697 } 698 if services["foo1"].EnableTagOverride != true { 699 t.Fatalf("tag override not set on service foo1: %v", services) 700 } 701 if _, ok := services["foo2"]; !ok { 702 t.Fatalf("missing service: %v", services) 703 } 704 if services["foo2"].EnableTagOverride != false { 705 t.Fatalf("tag override set on service foo2: %v", services) 706 } 707} 708 709func TestAPI_AgentServices_MultipleChecks(t *testing.T) { 710 t.Parallel() 711 c, s := makeClient(t) 712 defer s.Stop() 713 714 agent := c.Agent() 715 716 reg := &AgentServiceRegistration{ 717 Name: "foo", 718 Tags: []string{"bar", "baz"}, 719 Port: 8000, 720 Checks: AgentServiceChecks{ 721 &AgentServiceCheck{ 722 TTL: "15s", 723 }, 724 &AgentServiceCheck{ 725 TTL: "30s", 726 }, 727 }, 728 } 729 if err := agent.ServiceRegister(reg); err != nil { 730 t.Fatalf("err: %v", err) 731 } 732 733 services, err := agent.Services() 734 if err != nil { 735 t.Fatalf("err: %v", err) 736 } 737 if _, ok := services["foo"]; !ok { 738 t.Fatalf("missing service: %v", services) 739 } 740 741 checks, err := agent.Checks() 742 if err != nil { 743 t.Fatalf("err: %v", err) 744 } 745 if _, ok := checks["service:foo:1"]; !ok { 746 t.Fatalf("missing check: %v", checks) 747 } 748 if _, ok := checks["service:foo:2"]; !ok { 749 t.Fatalf("missing check: %v", checks) 750 } 751} 752 753func TestAPI_AgentService(t *testing.T) { 754 t.Parallel() 755 c, s := makeClient(t) 756 defer s.Stop() 757 758 agent := c.Agent() 759 760 require := require.New(t) 761 762 reg := &AgentServiceRegistration{ 763 Name: "foo", 764 Tags: []string{"bar", "baz"}, 765 Port: 8000, 766 Checks: AgentServiceChecks{ 767 &AgentServiceCheck{ 768 TTL: "15s", 769 }, 770 &AgentServiceCheck{ 771 TTL: "30s", 772 }, 773 }, 774 } 775 require.NoError(agent.ServiceRegister(reg)) 776 777 got, qm, err := agent.Service("foo", nil) 778 require.NoError(err) 779 780 expect := &AgentService{ 781 ID: "foo", 782 Service: "foo", 783 Tags: []string{"bar", "baz"}, 784 ContentHash: "f72563cae6924fb5", 785 Port: 8000, 786 Weights: AgentWeights{ 787 Passing: 1, 788 Warning: 1, 789 }, 790 Meta: map[string]string{}, 791 Namespace: defaultNamespace, 792 Datacenter: "dc1", 793 } 794 require.Equal(expect, got) 795 require.Equal(expect.ContentHash, qm.LastContentHash) 796 797 // Sanity check blocking behavior - this is more thoroughly tested in the 798 // agent endpoint tests but this ensures that the API package is at least 799 // passing the hash param properly. 800 opts := QueryOptions{ 801 WaitHash: qm.LastContentHash, 802 WaitTime: 100 * time.Millisecond, // Just long enough to be reliably measurable 803 } 804 start := time.Now() 805 _, _, err = agent.Service("foo", &opts) 806 elapsed := time.Since(start) 807 require.NoError(err) 808 require.True(elapsed >= opts.WaitTime) 809} 810 811func TestAPI_AgentSetTTLStatus(t *testing.T) { 812 t.Parallel() 813 c, s := makeClient(t) 814 defer s.Stop() 815 816 agent := c.Agent() 817 s.WaitForSerfCheck(t) 818 819 reg := &AgentServiceRegistration{ 820 Name: "foo", 821 Check: &AgentServiceCheck{ 822 TTL: "15s", 823 }, 824 } 825 if err := agent.ServiceRegister(reg); err != nil { 826 t.Fatalf("err: %v", err) 827 } 828 829 verify := func(status, output string) { 830 checks, err := agent.Checks() 831 if err != nil { 832 t.Fatalf("err: %v", err) 833 } 834 chk, ok := checks["service:foo"] 835 if !ok { 836 t.Fatalf("missing check: %v", checks) 837 } 838 if chk.Status != status { 839 t.Fatalf("Bad: %#v", chk) 840 } 841 if chk.Output != output { 842 t.Fatalf("Bad: %#v", chk) 843 } 844 } 845 846 if err := agent.WarnTTL("service:foo", "foo"); err != nil { 847 t.Fatalf("err: %v", err) 848 } 849 verify(HealthWarning, "foo") 850 851 if err := agent.PassTTL("service:foo", "bar"); err != nil { 852 t.Fatalf("err: %v", err) 853 } 854 verify(HealthPassing, "bar") 855 856 if err := agent.FailTTL("service:foo", "baz"); err != nil { 857 t.Fatalf("err: %v", err) 858 } 859 verify(HealthCritical, "baz") 860 861 if err := agent.UpdateTTL("service:foo", "foo", "warn"); err != nil { 862 t.Fatalf("err: %v", err) 863 } 864 verify(HealthWarning, "foo") 865 866 if err := agent.UpdateTTL("service:foo", "bar", "pass"); err != nil { 867 t.Fatalf("err: %v", err) 868 } 869 verify(HealthPassing, "bar") 870 871 if err := agent.UpdateTTL("service:foo", "baz", "fail"); err != nil { 872 t.Fatalf("err: %v", err) 873 } 874 verify(HealthCritical, "baz") 875 876 if err := agent.UpdateTTL("service:foo", "foo", HealthWarning); err != nil { 877 t.Fatalf("err: %v", err) 878 } 879 verify(HealthWarning, "foo") 880 881 if err := agent.UpdateTTL("service:foo", "bar", HealthPassing); err != nil { 882 t.Fatalf("err: %v", err) 883 } 884 verify(HealthPassing, "bar") 885 886 if err := agent.UpdateTTL("service:foo", "baz", HealthCritical); err != nil { 887 t.Fatalf("err: %v", err) 888 } 889 verify(HealthCritical, "baz") 890 891 if err := agent.ServiceDeregister("foo"); err != nil { 892 t.Fatalf("err: %v", err) 893 } 894} 895 896func TestAPI_AgentUpdateTTLOpts(t *testing.T) { 897 t.Parallel() 898 c, s := makeClient(t) 899 defer s.Stop() 900 901 agent := c.Agent() 902 s.WaitForSerfCheck(t) 903 904 reg := &AgentServiceRegistration{ 905 Name: "foo", 906 Check: &AgentServiceCheck{ 907 TTL: "15s", 908 }, 909 } 910 if err := agent.ServiceRegister(reg); err != nil { 911 t.Fatalf("err: %v", err) 912 } 913 914 verify := func(status, output string) { 915 checks, err := agent.Checks() 916 if err != nil { 917 t.Fatalf("err: %v", err) 918 } 919 chk, ok := checks["service:foo"] 920 if !ok { 921 t.Fatalf("missing check: %v", checks) 922 } 923 if chk.Status != status { 924 t.Fatalf("Bad: %#v", chk) 925 } 926 if chk.Output != output { 927 t.Fatalf("Bad: %#v", chk) 928 } 929 } 930 931 opts := &QueryOptions{Namespace: defaultNamespace} 932 933 if err := agent.UpdateTTLOpts("service:foo", "foo", HealthWarning, opts); err != nil { 934 t.Fatalf("err: %v", err) 935 } 936 verify(HealthWarning, "foo") 937 938 if err := agent.UpdateTTLOpts("service:foo", "bar", HealthPassing, opts); err != nil { 939 t.Fatalf("err: %v", err) 940 } 941 verify(HealthPassing, "bar") 942 943 if err := agent.UpdateTTL("service:foo", "baz", HealthCritical); err != nil { 944 t.Fatalf("err: %v", err) 945 } 946 verify(HealthCritical, "baz") 947 948 if err := agent.ServiceDeregister("foo"); err != nil { 949 t.Fatalf("err: %v", err) 950 } 951} 952 953func TestAPI_AgentChecks(t *testing.T) { 954 t.Parallel() 955 c, s := makeClient(t) 956 defer s.Stop() 957 958 agent := c.Agent() 959 960 reg := &AgentCheckRegistration{ 961 Name: "foo", 962 } 963 reg.TTL = "15s" 964 if err := agent.CheckRegister(reg); err != nil { 965 t.Fatalf("err: %v", err) 966 } 967 968 checks, err := agent.Checks() 969 if err != nil { 970 t.Fatalf("err: %v", err) 971 } 972 chk, ok := checks["foo"] 973 if !ok { 974 t.Fatalf("missing check: %v", checks) 975 } 976 if chk.Status != HealthCritical { 977 t.Fatalf("check not critical: %v", chk) 978 } 979 if chk.Type != "ttl" { 980 t.Fatalf("expected type ttl, got %s", chk.Type) 981 } 982 983 if err := agent.CheckDeregister("foo"); err != nil { 984 t.Fatalf("err: %v", err) 985 } 986} 987 988func TestAPI_AgentChecksWithFilterOpts(t *testing.T) { 989 t.Parallel() 990 c, s := makeClient(t) 991 defer s.Stop() 992 993 agent := c.Agent() 994 995 reg := &AgentCheckRegistration{ 996 Name: "foo", 997 } 998 reg.TTL = "15s" 999 require.NoError(t, agent.CheckRegister(reg)) 1000 reg = &AgentCheckRegistration{ 1001 Name: "bar", 1002 } 1003 reg.TTL = "15s" 1004 require.NoError(t, agent.CheckRegister(reg)) 1005 1006 opts := &QueryOptions{Namespace: defaultNamespace} 1007 checks, err := agent.ChecksWithFilterOpts("Name == foo", opts) 1008 require.NoError(t, err) 1009 require.Len(t, checks, 1) 1010 _, ok := checks["foo"] 1011 require.True(t, ok) 1012} 1013 1014func TestAPI_AgentScriptCheck(t *testing.T) { 1015 t.Parallel() 1016 c, s := makeClientWithConfig(t, nil, func(c *testutil.TestServerConfig) { 1017 c.EnableScriptChecks = true 1018 }) 1019 defer s.Stop() 1020 1021 agent := c.Agent() 1022 1023 t.Run("node script check", func(t *testing.T) { 1024 reg := &AgentCheckRegistration{ 1025 Name: "foo", 1026 AgentServiceCheck: AgentServiceCheck{ 1027 Interval: "10s", 1028 Args: []string{"sh", "-c", "false"}, 1029 }, 1030 } 1031 if err := agent.CheckRegister(reg); err != nil { 1032 t.Fatalf("err: %v", err) 1033 } 1034 1035 checks, err := agent.Checks() 1036 if err != nil { 1037 t.Fatalf("err: %v", err) 1038 } 1039 if _, ok := checks["foo"]; !ok { 1040 t.Fatalf("missing check: %v", checks) 1041 } 1042 }) 1043 1044 t.Run("service script check", func(t *testing.T) { 1045 reg := &AgentServiceRegistration{ 1046 Name: "bar", 1047 Port: 1234, 1048 Checks: AgentServiceChecks{ 1049 &AgentServiceCheck{ 1050 Interval: "10s", 1051 Args: []string{"sh", "-c", "false"}, 1052 }, 1053 }, 1054 } 1055 if err := agent.ServiceRegister(reg); err != nil { 1056 t.Fatalf("err: %v", err) 1057 } 1058 1059 services, err := agent.Services() 1060 if err != nil { 1061 t.Fatalf("err: %v", err) 1062 } 1063 if _, ok := services["bar"]; !ok { 1064 t.Fatalf("missing service: %v", services) 1065 } 1066 1067 checks, err := agent.Checks() 1068 if err != nil { 1069 t.Fatalf("err: %v", err) 1070 } 1071 if _, ok := checks["service:bar"]; !ok { 1072 t.Fatalf("missing check: %v", checks) 1073 } 1074 }) 1075} 1076 1077func TestAPI_AgentCheckStartPassing(t *testing.T) { 1078 t.Parallel() 1079 c, s := makeClient(t) 1080 defer s.Stop() 1081 1082 agent := c.Agent() 1083 1084 reg := &AgentCheckRegistration{ 1085 Name: "foo", 1086 AgentServiceCheck: AgentServiceCheck{ 1087 Status: HealthPassing, 1088 }, 1089 } 1090 reg.TTL = "15s" 1091 if err := agent.CheckRegister(reg); err != nil { 1092 t.Fatalf("err: %v", err) 1093 } 1094 1095 checks, err := agent.Checks() 1096 if err != nil { 1097 t.Fatalf("err: %v", err) 1098 } 1099 chk, ok := checks["foo"] 1100 if !ok { 1101 t.Fatalf("missing check: %v", checks) 1102 } 1103 if chk.Status != HealthPassing { 1104 t.Fatalf("check not passing: %v", chk) 1105 } 1106 1107 if err := agent.CheckDeregister("foo"); err != nil { 1108 t.Fatalf("err: %v", err) 1109 } 1110} 1111 1112func TestAPI_AgentChecks_serviceBound(t *testing.T) { 1113 t.Parallel() 1114 c, s := makeClient(t) 1115 defer s.Stop() 1116 1117 agent := c.Agent() 1118 s.WaitForSerfCheck(t) 1119 1120 // First register a service 1121 serviceReg := &AgentServiceRegistration{ 1122 Name: "redis", 1123 } 1124 if err := agent.ServiceRegister(serviceReg); err != nil { 1125 t.Fatalf("err: %v", err) 1126 } 1127 1128 // Register a check bound to the service 1129 reg := &AgentCheckRegistration{ 1130 Name: "redischeck", 1131 ServiceID: "redis", 1132 } 1133 reg.TTL = "15s" 1134 reg.DeregisterCriticalServiceAfter = "nope" 1135 err := agent.CheckRegister(reg) 1136 if err == nil || !strings.Contains(err.Error(), "invalid duration") { 1137 t.Fatalf("err: %v", err) 1138 } 1139 1140 reg.DeregisterCriticalServiceAfter = "90m" 1141 if err := agent.CheckRegister(reg); err != nil { 1142 t.Fatalf("err: %v", err) 1143 } 1144 1145 checks, err := agent.Checks() 1146 if err != nil { 1147 t.Fatalf("err: %v", err) 1148 } 1149 1150 check, ok := checks["redischeck"] 1151 if !ok { 1152 t.Fatalf("missing check: %v", checks) 1153 } 1154 if check.ServiceID != "redis" { 1155 t.Fatalf("missing service association for check: %v", check) 1156 } 1157 if check.Type != "ttl" { 1158 t.Fatalf("expected type ttl, got %s", check.Type) 1159 } 1160} 1161 1162func TestAPI_AgentChecks_Docker(t *testing.T) { 1163 t.Parallel() 1164 c, s := makeClientWithConfig(t, nil, func(c *testutil.TestServerConfig) { 1165 c.EnableScriptChecks = true 1166 }) 1167 defer s.Stop() 1168 1169 agent := c.Agent() 1170 1171 // First register a service 1172 serviceReg := &AgentServiceRegistration{ 1173 Name: "redis", 1174 } 1175 if err := agent.ServiceRegister(serviceReg); err != nil { 1176 t.Fatalf("err: %v", err) 1177 } 1178 1179 // Register a check bound to the service 1180 reg := &AgentCheckRegistration{ 1181 Name: "redischeck", 1182 ServiceID: "redis", 1183 AgentServiceCheck: AgentServiceCheck{ 1184 DockerContainerID: "f972c95ebf0e", 1185 Args: []string{"/bin/true"}, 1186 Shell: "/bin/bash", 1187 Interval: "10s", 1188 }, 1189 } 1190 if err := agent.CheckRegister(reg); err != nil { 1191 t.Fatalf("err: %v", err) 1192 } 1193 1194 checks, err := agent.Checks() 1195 if err != nil { 1196 t.Fatalf("err: %v", err) 1197 } 1198 1199 check, ok := checks["redischeck"] 1200 if !ok { 1201 t.Fatalf("missing check: %v", checks) 1202 } 1203 if check.ServiceID != "redis" { 1204 t.Fatalf("missing service association for check: %v", check) 1205 } 1206 if check.Type != "docker" { 1207 t.Fatalf("expected type docker, got %s", check.Type) 1208 } 1209} 1210 1211func TestAPI_AgentJoin(t *testing.T) { 1212 t.Parallel() 1213 c, s := makeClient(t) 1214 defer s.Stop() 1215 1216 agent := c.Agent() 1217 1218 info, err := agent.Self() 1219 if err != nil { 1220 t.Fatalf("err: %v", err) 1221 } 1222 1223 // Join ourself 1224 addr := info["DebugConfig"]["SerfAdvertiseAddrLAN"].(string) 1225 // strip off 'tcp://' 1226 addr = addr[len("tcp://"):] 1227 err = agent.Join(addr, false) 1228 if err != nil { 1229 t.Fatalf("err: %v", err) 1230 } 1231} 1232 1233func TestAPI_AgentLeave(t *testing.T) { 1234 t.Parallel() 1235 c1, s1 := makeClient(t) 1236 defer s1.Stop() 1237 1238 c2, s2 := makeClientWithConfig(t, nil, func(conf *testutil.TestServerConfig) { 1239 conf.Server = false 1240 conf.Bootstrap = false 1241 }) 1242 defer s2.Stop() 1243 1244 if err := c2.Agent().Join(s1.LANAddr, false); err != nil { 1245 t.Fatalf("err: %v", err) 1246 } 1247 1248 // We sometimes see an EOF response to this one, depending on timing. 1249 err := c2.Agent().Leave() 1250 if err != nil && !strings.Contains(err.Error(), "EOF") { 1251 t.Fatalf("err: %v", err) 1252 } 1253 1254 // Make sure the second agent's status is 'Left' 1255 members, err := c1.Agent().Members(false) 1256 if err != nil { 1257 t.Fatalf("err: %v", err) 1258 } 1259 member := members[0] 1260 if member.Name == s1.Config.NodeName { 1261 member = members[1] 1262 } 1263 if member.Status != int(serf.StatusLeft) { 1264 t.Fatalf("bad: %v", *member) 1265 } 1266} 1267 1268func TestAPI_AgentForceLeave(t *testing.T) { 1269 t.Parallel() 1270 c, s := makeClient(t) 1271 defer s.Stop() 1272 1273 agent := c.Agent() 1274 1275 // Eject somebody 1276 err := agent.ForceLeave(s.Config.NodeName) 1277 if err != nil { 1278 t.Fatalf("err: %v", err) 1279 } 1280} 1281 1282func TestAPI_AgentForceLeavePrune(t *testing.T) { 1283 t.Parallel() 1284 c, s := makeClient(t) 1285 defer s.Stop() 1286 1287 agent := c.Agent() 1288 1289 // Eject somebody 1290 err := agent.ForceLeavePrune(s.Config.NodeName) 1291 if err != nil { 1292 t.Fatalf("err: %v", err) 1293 } 1294} 1295 1296func TestAPI_AgentMonitor(t *testing.T) { 1297 t.Parallel() 1298 c, s := makeClient(t) 1299 defer s.Stop() 1300 1301 agent := c.Agent() 1302 1303 logCh, err := agent.Monitor("debug", nil, nil) 1304 if err != nil { 1305 t.Fatalf("err: %v", err) 1306 } 1307 1308 retry.Run(t, func(r *retry.R) { 1309 { 1310 // Register a service to be sure something happens in secs 1311 serviceReg := &AgentServiceRegistration{ 1312 Name: "redis", 1313 } 1314 if err := agent.ServiceRegister(serviceReg); err != nil { 1315 r.Fatalf("err: %v", err) 1316 } 1317 } 1318 // Wait for the first log message and validate it 1319 select { 1320 case log := <-logCh: 1321 if !(strings.Contains(log, "[INFO]") || strings.Contains(log, "[DEBUG]")) { 1322 r.Fatalf("bad: %q", log) 1323 } 1324 case <-time.After(10 * time.Second): 1325 r.Fatalf("failed to get a log message") 1326 } 1327 }) 1328} 1329 1330func TestAPI_AgentMonitorJSON(t *testing.T) { 1331 t.Parallel() 1332 c, s := makeClient(t) 1333 defer s.Stop() 1334 1335 agent := c.Agent() 1336 1337 logCh, err := agent.MonitorJSON("debug", nil, nil) 1338 if err != nil { 1339 t.Fatalf("err: %v", err) 1340 } 1341 1342 retry.Run(t, func(r *retry.R) { 1343 { 1344 // Register a service to be sure something happens in secs 1345 serviceReg := &AgentServiceRegistration{ 1346 Name: "redis", 1347 } 1348 if err := agent.ServiceRegister(serviceReg); err != nil { 1349 r.Fatalf("err: %v", err) 1350 } 1351 } 1352 // Wait for the first log message and validate it is valid JSON 1353 select { 1354 case log := <-logCh: 1355 var output map[string]interface{} 1356 if err := json.Unmarshal([]byte(log), &output); err != nil { 1357 r.Fatalf("log output was not JSON: %q", log) 1358 } 1359 case <-time.After(10 * time.Second): 1360 r.Fatalf("failed to get a log message") 1361 } 1362 }) 1363} 1364 1365func TestAPI_ServiceMaintenance(t *testing.T) { 1366 t.Parallel() 1367 c, s := makeClient(t) 1368 defer s.Stop() 1369 1370 agent := c.Agent() 1371 1372 // First register a service 1373 serviceReg := &AgentServiceRegistration{ 1374 Name: "redis", 1375 } 1376 if err := agent.ServiceRegister(serviceReg); err != nil { 1377 t.Fatalf("err: %v", err) 1378 } 1379 1380 // Enable maintenance mode 1381 if err := agent.EnableServiceMaintenance("redis", "broken"); err != nil { 1382 t.Fatalf("err: %s", err) 1383 } 1384 1385 // Ensure a critical check was added 1386 checks, err := agent.Checks() 1387 if err != nil { 1388 t.Fatalf("err: %v", err) 1389 } 1390 found := false 1391 for _, check := range checks { 1392 if strings.Contains(check.CheckID, "maintenance") { 1393 found = true 1394 if check.Status != HealthCritical || check.Notes != "broken" { 1395 t.Fatalf("bad: %#v", checks) 1396 } 1397 } 1398 } 1399 if !found { 1400 t.Fatalf("bad: %#v", checks) 1401 } 1402 1403 // Disable maintenance mode 1404 if err := agent.DisableServiceMaintenance("redis"); err != nil { 1405 t.Fatalf("err: %s", err) 1406 } 1407 1408 // Ensure the critical health check was removed 1409 checks, err = agent.Checks() 1410 if err != nil { 1411 t.Fatalf("err: %s", err) 1412 } 1413 for _, check := range checks { 1414 if strings.Contains(check.CheckID, "maintenance") { 1415 t.Fatalf("should have removed health check") 1416 } 1417 if check.Type != "maintenance" { 1418 t.Fatalf("expected type 'maintenance', got %s", check.Type) 1419 } 1420 } 1421} 1422 1423func TestAPI_NodeMaintenance(t *testing.T) { 1424 t.Parallel() 1425 c, s := makeClient(t) 1426 defer s.Stop() 1427 1428 agent := c.Agent() 1429 s.WaitForSerfCheck(t) 1430 1431 // Enable maintenance mode 1432 if err := agent.EnableNodeMaintenance("broken"); err != nil { 1433 t.Fatalf("err: %s", err) 1434 } 1435 1436 // Check that a critical check was added 1437 checks, err := agent.Checks() 1438 if err != nil { 1439 t.Fatalf("err: %s", err) 1440 } 1441 found := false 1442 for _, check := range checks { 1443 if strings.Contains(check.CheckID, "maintenance") { 1444 found = true 1445 if check.Status != HealthCritical || check.Notes != "broken" { 1446 t.Fatalf("bad: %#v", checks) 1447 } 1448 } 1449 } 1450 if !found { 1451 t.Fatalf("bad: %#v", checks) 1452 } 1453 1454 // Disable maintenance mode 1455 if err := agent.DisableNodeMaintenance(); err != nil { 1456 t.Fatalf("err: %s", err) 1457 } 1458 1459 // Ensure the check was removed 1460 checks, err = agent.Checks() 1461 if err != nil { 1462 t.Fatalf("err: %s", err) 1463 } 1464 for _, check := range checks { 1465 if strings.Contains(check.CheckID, "maintenance") { 1466 t.Fatalf("should have removed health check") 1467 } 1468 if check.Type != "maintenance" { 1469 t.Fatalf("expected type 'maintenance', got %s", check.Type) 1470 } 1471 } 1472} 1473 1474func TestAPI_AgentUpdateToken(t *testing.T) { 1475 t.Parallel() 1476 c, s := makeACLClient(t) 1477 defer s.Stop() 1478 1479 t.Run("deprecated", func(t *testing.T) { 1480 agent := c.Agent() 1481 if _, err := agent.UpdateACLToken("root", nil); err != nil { 1482 t.Fatalf("err: %v", err) 1483 } 1484 1485 if _, err := agent.UpdateACLAgentToken("root", nil); err != nil { 1486 t.Fatalf("err: %v", err) 1487 } 1488 1489 if _, err := agent.UpdateACLAgentMasterToken("root", nil); err != nil { 1490 t.Fatalf("err: %v", err) 1491 } 1492 1493 if _, err := agent.UpdateACLReplicationToken("root", nil); err != nil { 1494 t.Fatalf("err: %v", err) 1495 } 1496 }) 1497 1498 t.Run("new with no fallback", func(t *testing.T) { 1499 agent := c.Agent() 1500 if _, err := agent.UpdateDefaultACLToken("root", nil); err != nil { 1501 t.Fatalf("err: %v", err) 1502 } 1503 1504 if _, err := agent.UpdateAgentACLToken("root", nil); err != nil { 1505 t.Fatalf("err: %v", err) 1506 } 1507 1508 if _, err := agent.UpdateAgentMasterACLToken("root", nil); err != nil { 1509 t.Fatalf("err: %v", err) 1510 } 1511 1512 if _, err := agent.UpdateReplicationACLToken("root", nil); err != nil { 1513 t.Fatalf("err: %v", err) 1514 } 1515 }) 1516 1517 t.Run("new with fallback", func(t *testing.T) { 1518 // Respond with 404 for the new paths to trigger fallback. 1519 failer := func(w http.ResponseWriter, req *http.Request) { 1520 w.WriteHeader(404) 1521 } 1522 notfound := httptest.NewServer(http.HandlerFunc(failer)) 1523 defer notfound.Close() 1524 1525 raw := c // real consul client 1526 1527 // Set up a reverse proxy that will send some requests to the 1528 // 404 server and pass everything else through to the real Consul 1529 // server. 1530 director := func(req *http.Request) { 1531 req.URL.Scheme = "http" 1532 1533 switch req.URL.Path { 1534 case "/v1/agent/token/default", 1535 "/v1/agent/token/agent", 1536 "/v1/agent/token/agent_master", 1537 "/v1/agent/token/replication": 1538 req.URL.Host = notfound.URL[7:] // Strip off "http://". 1539 default: 1540 req.URL.Host = raw.config.Address 1541 } 1542 } 1543 proxy := httptest.NewServer(&httputil.ReverseProxy{Director: director}) 1544 defer proxy.Close() 1545 1546 // Make another client that points at the proxy instead of the real 1547 // Consul server. 1548 config := raw.config 1549 config.Address = proxy.URL[7:] // Strip off "http://". 1550 c, err := NewClient(&config) 1551 require.NoError(t, err) 1552 1553 agent := c.Agent() 1554 1555 _, err = agent.UpdateDefaultACLToken("root", nil) 1556 require.NoError(t, err) 1557 1558 _, err = agent.UpdateAgentACLToken("root", nil) 1559 require.NoError(t, err) 1560 1561 _, err = agent.UpdateAgentMasterACLToken("root", nil) 1562 require.NoError(t, err) 1563 1564 _, err = agent.UpdateReplicationACLToken("root", nil) 1565 require.NoError(t, err) 1566 }) 1567 1568 t.Run("new with 403s", func(t *testing.T) { 1569 failer := func(w http.ResponseWriter, req *http.Request) { 1570 w.WriteHeader(403) 1571 } 1572 authdeny := httptest.NewServer(http.HandlerFunc(failer)) 1573 defer authdeny.Close() 1574 1575 raw := c // real consul client 1576 1577 // Make another client that points at the proxy instead of the real 1578 // Consul server. 1579 config := raw.config 1580 config.Address = authdeny.URL[7:] // Strip off "http://". 1581 c, err := NewClient(&config) 1582 require.NoError(t, err) 1583 1584 agent := c.Agent() 1585 1586 _, err = agent.UpdateDefaultACLToken("root", nil) 1587 require.Error(t, err) 1588 1589 _, err = agent.UpdateAgentACLToken("root", nil) 1590 require.Error(t, err) 1591 1592 _, err = agent.UpdateAgentMasterACLToken("root", nil) 1593 require.Error(t, err) 1594 1595 _, err = agent.UpdateReplicationACLToken("root", nil) 1596 require.Error(t, err) 1597 }) 1598} 1599 1600func TestAPI_AgentConnectCARoots_empty(t *testing.T) { 1601 t.Parallel() 1602 1603 require := require.New(t) 1604 c, s := makeClientWithConfig(t, nil, func(c *testutil.TestServerConfig) { 1605 c.Connect = nil // disable connect to prevent CA being bootstrapped 1606 }) 1607 defer s.Stop() 1608 1609 agent := c.Agent() 1610 _, _, err := agent.ConnectCARoots(nil) 1611 require.Error(err) 1612 require.Contains(err.Error(), "Connect must be enabled") 1613} 1614 1615func TestAPI_AgentConnectCARoots_list(t *testing.T) { 1616 t.Parallel() 1617 1618 require := require.New(t) 1619 c, s := makeClient(t) 1620 defer s.Stop() 1621 1622 agent := c.Agent() 1623 s.WaitForSerfCheck(t) 1624 list, meta, err := agent.ConnectCARoots(nil) 1625 require.NoError(err) 1626 require.True(meta.LastIndex > 0) 1627 require.Len(list.Roots, 1) 1628} 1629 1630func TestAPI_AgentConnectCALeaf(t *testing.T) { 1631 t.Parallel() 1632 1633 require := require.New(t) 1634 c, s := makeClient(t) 1635 defer s.Stop() 1636 1637 // ensure we don't try to sign a leaf cert before connect has been initialized 1638 s.WaitForActiveCARoot(t) 1639 1640 agent := c.Agent() 1641 // Setup service 1642 reg := &AgentServiceRegistration{ 1643 Name: "foo", 1644 Tags: []string{"bar", "baz"}, 1645 Port: 8000, 1646 } 1647 require.NoError(agent.ServiceRegister(reg)) 1648 1649 leaf, meta, err := agent.ConnectCALeaf("foo", nil) 1650 require.NoError(err) 1651 require.True(meta.LastIndex > 0) 1652 // Sanity checks here as we have actual certificate validation checks at many 1653 // other levels. 1654 require.NotEmpty(leaf.SerialNumber) 1655 require.NotEmpty(leaf.CertPEM) 1656 require.NotEmpty(leaf.PrivateKeyPEM) 1657 require.Equal("foo", leaf.Service) 1658 require.True(strings.HasSuffix(leaf.ServiceURI, "/svc/foo")) 1659 require.True(leaf.ModifyIndex > 0) 1660 require.True(leaf.ValidAfter.Before(time.Now())) 1661 require.True(leaf.ValidBefore.After(time.Now())) 1662} 1663 1664func TestAPI_AgentConnectAuthorize(t *testing.T) { 1665 t.Parallel() 1666 require := require.New(t) 1667 c, s := makeClient(t) 1668 defer s.Stop() 1669 1670 agent := c.Agent() 1671 s.WaitForSerfCheck(t) 1672 params := &AgentAuthorizeParams{ 1673 Target: "foo", 1674 ClientCertSerial: "fake", 1675 // Importing connect.TestSpiffeIDService creates an import cycle 1676 ClientCertURI: "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/ny1/svc/web", 1677 } 1678 auth, err := agent.ConnectAuthorize(params) 1679 require.Nil(err) 1680 require.True(auth.Authorized) 1681 require.Equal(auth.Reason, "ACLs disabled, access is allowed by default") 1682} 1683 1684func TestAPI_AgentHealthService(t *testing.T) { 1685 t.Parallel() 1686 c, s := makeClient(t) 1687 defer s.Stop() 1688 1689 agent := c.Agent() 1690 1691 requireServiceHealthID := func(t *testing.T, serviceID, expected string, shouldExist bool) { 1692 msg := fmt.Sprintf("service id:%s, shouldExist:%v, expectedStatus:%s : bad %%s", serviceID, shouldExist, expected) 1693 1694 state, out, err := agent.AgentHealthServiceByID(serviceID) 1695 require.Nil(t, err, msg, "err") 1696 require.Equal(t, expected, state, msg, "state") 1697 if !shouldExist { 1698 require.Nil(t, out, msg, "shouldExist") 1699 } else { 1700 require.NotNil(t, out, msg, "output") 1701 require.Equal(t, serviceID, out.Service.ID, msg, "output") 1702 } 1703 } 1704 requireServiceHealthName := func(t *testing.T, serviceName, expected string, shouldExist bool) { 1705 msg := fmt.Sprintf("service name:%s, shouldExist:%v, expectedStatus:%s : bad %%s", serviceName, shouldExist, expected) 1706 1707 state, outs, err := agent.AgentHealthServiceByName(serviceName) 1708 require.Nil(t, err, msg, "err") 1709 require.Equal(t, expected, state, msg, "state") 1710 if !shouldExist { 1711 require.Equal(t, 0, len(outs), msg, "output") 1712 } else { 1713 require.True(t, len(outs) > 0, msg, "output") 1714 for _, o := range outs { 1715 require.Equal(t, serviceName, o.Service.Service, msg, "output") 1716 } 1717 } 1718 } 1719 1720 requireServiceHealthID(t, "_i_do_not_exist_", HealthCritical, false) 1721 requireServiceHealthName(t, "_i_do_not_exist_", HealthCritical, false) 1722 1723 testServiceID1 := "foo" 1724 testServiceID2 := "foofoo" 1725 testServiceName := "bar" 1726 1727 // register service 1728 reg := &AgentServiceRegistration{ 1729 Name: testServiceName, 1730 ID: testServiceID1, 1731 Port: 8000, 1732 Check: &AgentServiceCheck{ 1733 TTL: "15s", 1734 }, 1735 } 1736 err := agent.ServiceRegister(reg) 1737 require.Nil(t, err) 1738 requireServiceHealthID(t, testServiceID1, HealthCritical, true) 1739 requireServiceHealthName(t, testServiceName, HealthCritical, true) 1740 1741 err = agent.WarnTTL(fmt.Sprintf("service:%s", testServiceID1), "I am warn") 1742 require.Nil(t, err) 1743 requireServiceHealthName(t, testServiceName, HealthWarning, true) 1744 requireServiceHealthID(t, testServiceID1, HealthWarning, true) 1745 1746 err = agent.PassTTL(fmt.Sprintf("service:%s", testServiceID1), "I am good :)") 1747 require.Nil(t, err) 1748 requireServiceHealthName(t, testServiceName, HealthPassing, true) 1749 requireServiceHealthID(t, testServiceID1, HealthPassing, true) 1750 1751 err = agent.FailTTL(fmt.Sprintf("service:%s", testServiceID1), "I am dead.") 1752 require.Nil(t, err) 1753 requireServiceHealthName(t, testServiceName, HealthCritical, true) 1754 requireServiceHealthID(t, testServiceID1, HealthCritical, true) 1755 1756 // register another service 1757 reg = &AgentServiceRegistration{ 1758 Name: testServiceName, 1759 ID: testServiceID2, 1760 Port: 8000, 1761 Check: &AgentServiceCheck{ 1762 TTL: "15s", 1763 }, 1764 } 1765 err = agent.ServiceRegister(reg) 1766 require.Nil(t, err) 1767 requireServiceHealthName(t, testServiceName, HealthCritical, true) 1768 1769 err = agent.PassTTL(fmt.Sprintf("service:%s", testServiceID1), "I am good :)") 1770 require.Nil(t, err) 1771 requireServiceHealthName(t, testServiceName, HealthCritical, true) 1772 1773 err = agent.WarnTTL(fmt.Sprintf("service:%s", testServiceID2), "I am warn") 1774 require.Nil(t, err) 1775 requireServiceHealthName(t, testServiceName, HealthWarning, true) 1776 1777 err = agent.PassTTL(fmt.Sprintf("service:%s", testServiceID2), "I am good :)") 1778 require.Nil(t, err) 1779 requireServiceHealthName(t, testServiceName, HealthPassing, true) 1780} 1781 1782func TestAgentService_JSON_OmitTaggedAdddresses(t *testing.T) { 1783 t.Parallel() 1784 cases := []struct { 1785 name string 1786 as AgentService 1787 }{ 1788 { 1789 "nil", 1790 AgentService{ 1791 TaggedAddresses: nil, 1792 }, 1793 }, 1794 { 1795 "empty", 1796 AgentService{ 1797 TaggedAddresses: make(map[string]ServiceAddress), 1798 }, 1799 }, 1800 } 1801 1802 for _, tc := range cases { 1803 name := tc.name 1804 as := tc.as 1805 t.Run(name, func(t *testing.T) { 1806 t.Parallel() 1807 data, err := json.Marshal(as) 1808 require.NoError(t, err) 1809 var raw map[string]interface{} 1810 err = json.Unmarshal(data, &raw) 1811 require.NoError(t, err) 1812 require.NotContains(t, raw, "TaggedAddresses") 1813 require.NotContains(t, raw, "tagged_addresses") 1814 }) 1815 } 1816} 1817 1818func TestAgentService_Register_MeshGateway(t *testing.T) { 1819 t.Parallel() 1820 c, s := makeClient(t) 1821 defer s.Stop() 1822 1823 agent := c.Agent() 1824 1825 reg := AgentServiceRegistration{ 1826 Kind: ServiceKindMeshGateway, 1827 Name: "mesh-gateway", 1828 Address: "10.1.2.3", 1829 Port: 8443, 1830 Proxy: &AgentServiceConnectProxyConfig{ 1831 Config: map[string]interface{}{ 1832 "foo": "bar", 1833 }, 1834 }, 1835 } 1836 1837 err := agent.ServiceRegister(®) 1838 require.NoError(t, err) 1839 1840 svc, _, err := agent.Service("mesh-gateway", nil) 1841 require.NoError(t, err) 1842 require.NotNil(t, svc) 1843 require.Equal(t, ServiceKindMeshGateway, svc.Kind) 1844 require.NotNil(t, svc.Proxy) 1845 require.Contains(t, svc.Proxy.Config, "foo") 1846 require.Equal(t, "bar", svc.Proxy.Config["foo"]) 1847} 1848 1849func TestAgentService_Register_TerminatingGateway(t *testing.T) { 1850 t.Parallel() 1851 c, s := makeClient(t) 1852 defer s.Stop() 1853 1854 agent := c.Agent() 1855 1856 reg := AgentServiceRegistration{ 1857 Kind: ServiceKindTerminatingGateway, 1858 Name: "terminating-gateway", 1859 Address: "10.1.2.3", 1860 Port: 8443, 1861 Proxy: &AgentServiceConnectProxyConfig{ 1862 Config: map[string]interface{}{ 1863 "foo": "bar", 1864 }, 1865 }, 1866 } 1867 1868 err := agent.ServiceRegister(®) 1869 require.NoError(t, err) 1870 1871 svc, _, err := agent.Service("terminating-gateway", nil) 1872 require.NoError(t, err) 1873 require.NotNil(t, svc) 1874 require.Equal(t, ServiceKindTerminatingGateway, svc.Kind) 1875 require.NotNil(t, svc.Proxy) 1876 require.Contains(t, svc.Proxy.Config, "foo") 1877 require.Equal(t, "bar", svc.Proxy.Config["foo"]) 1878} 1879 1880func TestAgentService_ExposeChecks(t *testing.T) { 1881 t.Parallel() 1882 c, s := makeClient(t) 1883 defer s.Stop() 1884 1885 agent := c.Agent() 1886 1887 path := ExposePath{ 1888 LocalPathPort: 8080, 1889 ListenerPort: 21500, 1890 Path: "/metrics", 1891 Protocol: "http2", 1892 } 1893 reg := AgentServiceRegistration{ 1894 Kind: ServiceKindConnectProxy, 1895 Name: "expose-proxy", 1896 Address: "10.1.2.3", 1897 Port: 8443, 1898 Proxy: &AgentServiceConnectProxyConfig{ 1899 DestinationServiceName: "expose", 1900 Expose: ExposeConfig{ 1901 Checks: true, 1902 Paths: []ExposePath{ 1903 path, 1904 }, 1905 }, 1906 }, 1907 } 1908 1909 err := agent.ServiceRegister(®) 1910 require.NoError(t, err) 1911 1912 svc, _, err := agent.Service("expose-proxy", nil) 1913 require.NoError(t, err) 1914 require.NotNil(t, svc) 1915 require.Equal(t, ServiceKindConnectProxy, svc.Kind) 1916 require.NotNil(t, svc.Proxy) 1917 require.Len(t, svc.Proxy.Expose.Paths, 1) 1918 require.True(t, svc.Proxy.Expose.Checks) 1919 require.Equal(t, path, svc.Proxy.Expose.Paths[0]) 1920} 1921 1922func TestMemberACLMode(t *testing.T) { 1923 type testCase struct { 1924 tagValue string 1925 expectedMode MemberACLMode 1926 } 1927 1928 cases := map[string]testCase{ 1929 "disabled": { 1930 tagValue: "0", 1931 expectedMode: ACLModeDisabled, 1932 }, 1933 "enabled": { 1934 tagValue: "1", 1935 expectedMode: ACLModeEnabled, 1936 }, 1937 "legacy": { 1938 tagValue: "2", 1939 expectedMode: ACLModeLegacy, 1940 }, 1941 "unknown-3": { 1942 tagValue: "3", 1943 expectedMode: ACLModeUnknown, 1944 }, 1945 "unknown-other": { 1946 tagValue: "77", 1947 expectedMode: ACLModeUnknown, 1948 }, 1949 "unknown-not-present": { 1950 tagValue: "", 1951 expectedMode: ACLModeUnknown, 1952 }, 1953 } 1954 1955 for name, tcase := range cases { 1956 t.Run(name, func(t *testing.T) { 1957 tags := map[string]string{} 1958 1959 if tcase.tagValue != "" { 1960 tags[MemberTagKeyACLMode] = tcase.tagValue 1961 } 1962 1963 m := AgentMember{ 1964 Tags: tags, 1965 } 1966 1967 require.Equal(t, tcase.expectedMode, m.ACLMode()) 1968 }) 1969 } 1970} 1971 1972func TestMemberIsConsulServer(t *testing.T) { 1973 type testCase struct { 1974 tagValue string 1975 isServer bool 1976 } 1977 1978 cases := map[string]testCase{ 1979 "not-present": { 1980 tagValue: "", 1981 isServer: false, 1982 }, 1983 "server": { 1984 tagValue: MemberTagValueRoleServer, 1985 isServer: true, 1986 }, 1987 "client": { 1988 tagValue: "client", 1989 isServer: false, 1990 }, 1991 } 1992 1993 for name, tcase := range cases { 1994 t.Run(name, func(t *testing.T) { 1995 tags := map[string]string{} 1996 1997 if tcase.tagValue != "" { 1998 tags[MemberTagKeyRole] = tcase.tagValue 1999 } 2000 2001 m := AgentMember{ 2002 Tags: tags, 2003 } 2004 2005 require.Equal(t, tcase.isServer, m.IsConsulServer()) 2006 }) 2007 } 2008} 2009