github.com/kjdelisle/consul@v1.4.5/api/agent_test.go (about) 1 package api 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "os" 7 "path/filepath" 8 "strings" 9 "testing" 10 "time" 11 12 "github.com/hashicorp/consul/testutil" 13 "github.com/hashicorp/consul/testutil/retry" 14 "github.com/hashicorp/serf/serf" 15 "github.com/stretchr/testify/require" 16 ) 17 18 func TestAPI_AgentSelf(t *testing.T) { 19 t.Parallel() 20 c, s := makeClient(t) 21 defer s.Stop() 22 23 agent := c.Agent() 24 25 info, err := agent.Self() 26 if err != nil { 27 t.Fatalf("err: %v", err) 28 } 29 30 name := info["Config"]["NodeName"].(string) 31 if name == "" { 32 t.Fatalf("bad: %v", info) 33 } 34 } 35 36 func TestAPI_AgentMetrics(t *testing.T) { 37 t.Parallel() 38 c, s := makeClient(t) 39 defer s.Stop() 40 41 agent := c.Agent() 42 timer := &retry.Timer{Timeout: 10 * time.Second, Wait: 500 * time.Millisecond} 43 retry.RunWith(timer, t, func(r *retry.R) { 44 metrics, err := agent.Metrics() 45 if err != nil { 46 r.Fatalf("err: %v", err) 47 } 48 for _, g := range metrics.Gauges { 49 if g.Name == "consul.runtime.alloc_bytes" { 50 return 51 } 52 } 53 r.Fatalf("missing runtime metrics") 54 }) 55 } 56 57 func TestAPI_AgentHost(t *testing.T) { 58 t.Parallel() 59 c, s := makeClient(t) 60 defer s.Stop() 61 62 agent := c.Agent() 63 timer := &retry.Timer{} 64 retry.RunWith(timer, t, func(r *retry.R) { 65 host, err := agent.Host() 66 if err != nil { 67 r.Fatalf("err: %v", err) 68 } 69 70 // CollectionTime should exist on all responses 71 if host["CollectionTime"] == nil { 72 r.Fatalf("missing host response") 73 } 74 }) 75 } 76 77 func TestAPI_AgentReload(t *testing.T) { 78 t.Parallel() 79 80 // Create our initial empty config file, to be overwritten later 81 cfgDir := testutil.TempDir(t, "consul-config") 82 defer os.RemoveAll(cfgDir) 83 84 cfgFilePath := filepath.Join(cfgDir, "reload.json") 85 configFile, err := os.Create(cfgFilePath) 86 if err != nil { 87 t.Fatalf("Unable to create file %v, got error:%v", cfgFilePath, err) 88 } 89 90 c, s := makeClientWithConfig(t, nil, func(conf *testutil.TestServerConfig) { 91 conf.Args = []string{"-config-file", configFile.Name()} 92 }) 93 defer s.Stop() 94 95 agent := c.Agent() 96 97 // Update the config file with a service definition 98 config := `{"service":{"name":"redis", "port":1234, "Meta": {"some": "meta"}}}` 99 err = ioutil.WriteFile(configFile.Name(), []byte(config), 0644) 100 if err != nil { 101 t.Fatalf("err: %v", err) 102 } 103 104 if err = agent.Reload(); err != nil { 105 t.Fatalf("err: %v", err) 106 } 107 108 services, err := agent.Services() 109 if err != nil { 110 t.Fatalf("err: %v", err) 111 } 112 113 service, ok := services["redis"] 114 if !ok { 115 t.Fatalf("bad: %v", ok) 116 } 117 if service.Port != 1234 { 118 t.Fatalf("bad: %v", service.Port) 119 } 120 if service.Meta["some"] != "meta" { 121 t.Fatalf("Missing metadata some:=meta in %v", service) 122 } 123 } 124 125 func TestAPI_AgentMembersOpts(t *testing.T) { 126 t.Parallel() 127 c, s1 := makeClient(t) 128 _, s2 := makeClientWithConfig(t, nil, func(c *testutil.TestServerConfig) { 129 c.Datacenter = "dc2" 130 }) 131 defer s1.Stop() 132 defer s2.Stop() 133 134 agent := c.Agent() 135 136 s2.JoinWAN(t, s1.WANAddr) 137 138 members, err := agent.MembersOpts(MembersOpts{WAN: true}) 139 if err != nil { 140 t.Fatalf("err: %v", err) 141 } 142 143 if len(members) != 2 { 144 t.Fatalf("bad: %v", members) 145 } 146 } 147 148 func TestAPI_AgentMembers(t *testing.T) { 149 t.Parallel() 150 c, s := makeClient(t) 151 defer s.Stop() 152 153 agent := c.Agent() 154 155 members, err := agent.Members(false) 156 if err != nil { 157 t.Fatalf("err: %v", err) 158 } 159 160 if len(members) != 1 { 161 t.Fatalf("bad: %v", members) 162 } 163 } 164 165 func TestAPI_AgentServices(t *testing.T) { 166 t.Parallel() 167 c, s := makeClient(t) 168 defer s.Stop() 169 170 agent := c.Agent() 171 172 reg := &AgentServiceRegistration{ 173 Name: "foo", 174 ID: "foo", 175 Tags: []string{"bar", "baz"}, 176 Port: 8000, 177 Check: &AgentServiceCheck{ 178 TTL: "15s", 179 }, 180 } 181 if err := agent.ServiceRegister(reg); err != nil { 182 t.Fatalf("err: %v", err) 183 } 184 185 services, err := agent.Services() 186 if err != nil { 187 t.Fatalf("err: %v", err) 188 } 189 if _, ok := services["foo"]; !ok { 190 t.Fatalf("missing service: %#v", services) 191 } 192 checks, err := agent.Checks() 193 if err != nil { 194 t.Fatalf("err: %v", err) 195 } 196 chk, ok := checks["service:foo"] 197 if !ok { 198 t.Fatalf("missing check: %v", checks) 199 } 200 201 // Checks should default to critical 202 if chk.Status != HealthCritical { 203 t.Fatalf("Bad: %#v", chk) 204 } 205 206 state, out, err := agent.AgentHealthServiceByID("foo2") 207 require.Nil(t, err) 208 require.Nil(t, out) 209 require.Equal(t, HealthCritical, state) 210 211 state, out, err = agent.AgentHealthServiceByID("foo") 212 require.Nil(t, err) 213 require.NotNil(t, out) 214 require.Equal(t, HealthCritical, state) 215 require.Equal(t, 8000, out.Service.Port) 216 217 state, outs, err := agent.AgentHealthServiceByName("foo") 218 require.Nil(t, err) 219 require.NotNil(t, outs) 220 require.Equal(t, HealthCritical, state) 221 require.Equal(t, 8000, out.Service.Port) 222 223 if err := agent.ServiceDeregister("foo"); err != nil { 224 t.Fatalf("err: %v", err) 225 } 226 } 227 228 func TestAPI_AgentServices_ManagedConnectProxy(t *testing.T) { 229 t.Parallel() 230 c, s := makeClient(t) 231 defer s.Stop() 232 233 agent := c.Agent() 234 235 reg := &AgentServiceRegistration{ 236 Name: "foo", 237 Tags: []string{"bar", "baz"}, 238 Port: 8000, 239 Check: &AgentServiceCheck{ 240 TTL: "15s", 241 }, 242 Connect: &AgentServiceConnect{ 243 Proxy: &AgentServiceConnectProxy{ 244 ExecMode: ProxyExecModeScript, 245 Command: []string{"foo.rb"}, 246 Config: map[string]interface{}{ 247 "foo": "bar", 248 }, 249 Upstreams: []Upstream{{ 250 DestinationType: "prepared_query", 251 DestinationName: "bar", 252 LocalBindPort: 9191, 253 }}, 254 }, 255 }, 256 } 257 if err := agent.ServiceRegister(reg); err != nil { 258 t.Fatalf("err: %v", err) 259 } 260 261 services, err := agent.Services() 262 if err != nil { 263 t.Fatalf("err: %v", err) 264 } 265 if _, ok := services["foo"]; !ok { 266 t.Fatalf("missing service: %v", services) 267 } 268 checks, err := agent.Checks() 269 if err != nil { 270 t.Fatalf("err: %v", err) 271 } 272 chk, ok := checks["service:foo"] 273 if !ok { 274 t.Fatalf("missing check: %v", checks) 275 } 276 277 // Checks should default to critical 278 if chk.Status != HealthCritical { 279 t.Fatalf("Bad: %#v", chk) 280 } 281 282 // Proxy config should be correct 283 require.Equal(t, reg.Connect, services["foo"].Connect) 284 285 if err := agent.ServiceDeregister("foo"); err != nil { 286 t.Fatalf("err: %v", err) 287 } 288 } 289 290 func TestAPI_AgentServices_ManagedConnectProxyDeprecatedUpstreams(t *testing.T) { 291 t.Parallel() 292 c, s := makeClient(t) 293 defer s.Stop() 294 295 agent := c.Agent() 296 297 reg := &AgentServiceRegistration{ 298 Name: "foo", 299 Tags: []string{"bar", "baz"}, 300 Port: 8000, 301 Check: &AgentServiceCheck{ 302 TTL: "15s", 303 }, 304 Connect: &AgentServiceConnect{ 305 Proxy: &AgentServiceConnectProxy{ 306 ExecMode: ProxyExecModeScript, 307 Command: []string{"foo.rb"}, 308 Config: map[string]interface{}{ 309 "foo": "bar", 310 "upstreams": []interface{}{ 311 map[string]interface{}{ 312 "destination_type": "prepared_query", 313 "destination_name": "bar", 314 "local_bind_port": 9191, 315 "connect_timeout_ms": 1000, 316 }, 317 }, 318 }, 319 }, 320 }, 321 } 322 if err := agent.ServiceRegister(reg); err != nil { 323 t.Fatalf("err: %v", err) 324 } 325 326 services, err := agent.Services() 327 if err != nil { 328 t.Fatalf("err: %v", err) 329 } 330 if _, ok := services["foo"]; !ok { 331 t.Fatalf("missing service: %v", services) 332 } 333 checks, err := agent.Checks() 334 if err != nil { 335 t.Fatalf("err: %v", err) 336 } 337 chk, ok := checks["service:foo"] 338 if !ok { 339 t.Fatalf("missing check: %v", checks) 340 } 341 342 // Checks should default to critical 343 if chk.Status != HealthCritical { 344 t.Fatalf("Bad: %#v", chk) 345 } 346 347 // Proxy config should be present in response, minus the upstreams 348 delete(reg.Connect.Proxy.Config, "upstreams") 349 // Upstreams should be translated into proper field 350 reg.Connect.Proxy.Upstreams = []Upstream{{ 351 DestinationType: "prepared_query", 352 DestinationName: "bar", 353 LocalBindPort: 9191, 354 Config: map[string]interface{}{ 355 "connect_timeout_ms": float64(1000), 356 }, 357 }} 358 require.Equal(t, reg.Connect, services["foo"].Connect) 359 360 if err := agent.ServiceDeregister("foo"); err != nil { 361 t.Fatalf("err: %v", err) 362 } 363 } 364 365 func TestAPI_AgentServices_SidecarService(t *testing.T) { 366 t.Parallel() 367 c, s := makeClient(t) 368 defer s.Stop() 369 370 agent := c.Agent() 371 372 // Register service 373 reg := &AgentServiceRegistration{ 374 Name: "foo", 375 Port: 8000, 376 Connect: &AgentServiceConnect{ 377 SidecarService: &AgentServiceRegistration{}, 378 }, 379 } 380 if err := agent.ServiceRegister(reg); err != nil { 381 t.Fatalf("err: %v", err) 382 } 383 384 services, err := agent.Services() 385 if err != nil { 386 t.Fatalf("err: %v", err) 387 } 388 if _, ok := services["foo"]; !ok { 389 t.Fatalf("missing service: %v", services) 390 } 391 if _, ok := services["foo-sidecar-proxy"]; !ok { 392 t.Fatalf("missing sidecar service: %v", services) 393 } 394 395 if err := agent.ServiceDeregister("foo"); err != nil { 396 t.Fatalf("err: %v", err) 397 } 398 399 // Deregister should have removed both service and it's sidecar 400 services, err = agent.Services() 401 require.NoError(t, err) 402 403 if _, ok := services["foo"]; ok { 404 t.Fatalf("didn't remove service: %v", services) 405 } 406 if _, ok := services["foo-sidecar-proxy"]; ok { 407 t.Fatalf("didn't remove sidecar service: %v", services) 408 } 409 } 410 411 func TestAPI_AgentServices_ExternalConnectProxy(t *testing.T) { 412 t.Parallel() 413 c, s := makeClient(t) 414 defer s.Stop() 415 416 agent := c.Agent() 417 418 // Register service 419 reg := &AgentServiceRegistration{ 420 Name: "foo", 421 Port: 8000, 422 } 423 if err := agent.ServiceRegister(reg); err != nil { 424 t.Fatalf("err: %v", err) 425 } 426 // Register proxy 427 reg = &AgentServiceRegistration{ 428 Kind: ServiceKindConnectProxy, 429 Name: "foo-proxy", 430 Port: 8001, 431 Proxy: &AgentServiceConnectProxyConfig{ 432 DestinationServiceName: "foo", 433 }, 434 } 435 if err := agent.ServiceRegister(reg); err != nil { 436 t.Fatalf("err: %v", err) 437 } 438 439 services, err := agent.Services() 440 if err != nil { 441 t.Fatalf("err: %v", err) 442 } 443 if _, ok := services["foo"]; !ok { 444 t.Fatalf("missing service: %v", services) 445 } 446 if _, ok := services["foo-proxy"]; !ok { 447 t.Fatalf("missing proxy service: %v", services) 448 } 449 450 if err := agent.ServiceDeregister("foo"); err != nil { 451 t.Fatalf("err: %v", err) 452 } 453 if err := agent.ServiceDeregister("foo-proxy"); err != nil { 454 t.Fatalf("err: %v", err) 455 } 456 } 457 458 func TestAPI_AgentServices_CheckPassing(t *testing.T) { 459 t.Parallel() 460 c, s := makeClient(t) 461 defer s.Stop() 462 463 agent := c.Agent() 464 reg := &AgentServiceRegistration{ 465 Name: "foo", 466 Tags: []string{"bar", "baz"}, 467 Port: 8000, 468 Check: &AgentServiceCheck{ 469 TTL: "15s", 470 Status: HealthPassing, 471 }, 472 } 473 if err := agent.ServiceRegister(reg); err != nil { 474 t.Fatalf("err: %v", err) 475 } 476 477 services, err := agent.Services() 478 if err != nil { 479 t.Fatalf("err: %v", err) 480 } 481 if _, ok := services["foo"]; !ok { 482 t.Fatalf("missing service: %v", services) 483 } 484 485 checks, err := agent.Checks() 486 if err != nil { 487 t.Fatalf("err: %v", err) 488 } 489 chk, ok := checks["service:foo"] 490 if !ok { 491 t.Fatalf("missing check: %v", checks) 492 } 493 494 if chk.Status != HealthPassing { 495 t.Fatalf("Bad: %#v", chk) 496 } 497 if err := agent.ServiceDeregister("foo"); err != nil { 498 t.Fatalf("err: %v", err) 499 } 500 } 501 502 func TestAPI_AgentServices_CheckBadStatus(t *testing.T) { 503 t.Parallel() 504 c, s := makeClient(t) 505 defer s.Stop() 506 507 agent := c.Agent() 508 reg := &AgentServiceRegistration{ 509 Name: "foo", 510 Tags: []string{"bar", "baz"}, 511 Port: 8000, 512 Check: &AgentServiceCheck{ 513 TTL: "15s", 514 Status: "fluffy", 515 }, 516 } 517 if err := agent.ServiceRegister(reg); err == nil { 518 t.Fatalf("bad status accepted") 519 } 520 } 521 522 func TestAPI_AgentServices_CheckID(t *testing.T) { 523 t.Parallel() 524 c, s := makeClient(t) 525 defer s.Stop() 526 527 agent := c.Agent() 528 reg := &AgentServiceRegistration{ 529 Name: "foo", 530 Tags: []string{"bar", "baz"}, 531 Port: 8000, 532 Check: &AgentServiceCheck{ 533 CheckID: "foo-ttl", 534 TTL: "15s", 535 }, 536 } 537 if err := agent.ServiceRegister(reg); err != nil { 538 t.Fatalf("err: %v", err) 539 } 540 541 checks, err := agent.Checks() 542 if err != nil { 543 t.Fatalf("err: %v", err) 544 } 545 if _, ok := checks["foo-ttl"]; !ok { 546 t.Fatalf("missing check: %v", checks) 547 } 548 } 549 550 func TestAPI_AgentServiceAddress(t *testing.T) { 551 t.Parallel() 552 c, s := makeClient(t) 553 defer s.Stop() 554 555 agent := c.Agent() 556 557 reg1 := &AgentServiceRegistration{ 558 Name: "foo1", 559 Port: 8000, 560 Address: "192.168.0.42", 561 } 562 reg2 := &AgentServiceRegistration{ 563 Name: "foo2", 564 Port: 8000, 565 } 566 if err := agent.ServiceRegister(reg1); err != nil { 567 t.Fatalf("err: %v", err) 568 } 569 if err := agent.ServiceRegister(reg2); err != nil { 570 t.Fatalf("err: %v", err) 571 } 572 573 services, err := agent.Services() 574 if err != nil { 575 t.Fatalf("err: %v", err) 576 } 577 578 if _, ok := services["foo1"]; !ok { 579 t.Fatalf("missing service: %v", services) 580 } 581 if _, ok := services["foo2"]; !ok { 582 t.Fatalf("missing service: %v", services) 583 } 584 585 if services["foo1"].Address != "192.168.0.42" { 586 t.Fatalf("missing Address field in service foo1: %v", services) 587 } 588 if services["foo2"].Address != "" { 589 t.Fatalf("missing Address field in service foo2: %v", services) 590 } 591 592 if err := agent.ServiceDeregister("foo"); err != nil { 593 t.Fatalf("err: %v", err) 594 } 595 } 596 597 func TestAPI_AgentEnableTagOverride(t *testing.T) { 598 t.Parallel() 599 c, s := makeClient(t) 600 defer s.Stop() 601 602 agent := c.Agent() 603 604 reg1 := &AgentServiceRegistration{ 605 Name: "foo1", 606 Port: 8000, 607 Address: "192.168.0.42", 608 EnableTagOverride: true, 609 } 610 reg2 := &AgentServiceRegistration{ 611 Name: "foo2", 612 Port: 8000, 613 } 614 if err := agent.ServiceRegister(reg1); err != nil { 615 t.Fatalf("err: %v", err) 616 } 617 if err := agent.ServiceRegister(reg2); err != nil { 618 t.Fatalf("err: %v", err) 619 } 620 621 services, err := agent.Services() 622 if err != nil { 623 t.Fatalf("err: %v", err) 624 } 625 626 if _, ok := services["foo1"]; !ok { 627 t.Fatalf("missing service: %v", services) 628 } 629 if services["foo1"].EnableTagOverride != true { 630 t.Fatalf("tag override not set on service foo1: %v", services) 631 } 632 if _, ok := services["foo2"]; !ok { 633 t.Fatalf("missing service: %v", services) 634 } 635 if services["foo2"].EnableTagOverride != false { 636 t.Fatalf("tag override set on service foo2: %v", services) 637 } 638 } 639 640 func TestAPI_AgentServices_MultipleChecks(t *testing.T) { 641 t.Parallel() 642 c, s := makeClient(t) 643 defer s.Stop() 644 645 agent := c.Agent() 646 647 reg := &AgentServiceRegistration{ 648 Name: "foo", 649 Tags: []string{"bar", "baz"}, 650 Port: 8000, 651 Checks: AgentServiceChecks{ 652 &AgentServiceCheck{ 653 TTL: "15s", 654 }, 655 &AgentServiceCheck{ 656 TTL: "30s", 657 }, 658 }, 659 } 660 if err := agent.ServiceRegister(reg); err != nil { 661 t.Fatalf("err: %v", err) 662 } 663 664 services, err := agent.Services() 665 if err != nil { 666 t.Fatalf("err: %v", err) 667 } 668 if _, ok := services["foo"]; !ok { 669 t.Fatalf("missing service: %v", services) 670 } 671 672 checks, err := agent.Checks() 673 if err != nil { 674 t.Fatalf("err: %v", err) 675 } 676 if _, ok := checks["service:foo:1"]; !ok { 677 t.Fatalf("missing check: %v", checks) 678 } 679 if _, ok := checks["service:foo:2"]; !ok { 680 t.Fatalf("missing check: %v", checks) 681 } 682 } 683 684 func TestAPI_AgentService(t *testing.T) { 685 t.Parallel() 686 c, s := makeClient(t) 687 defer s.Stop() 688 689 agent := c.Agent() 690 691 require := require.New(t) 692 693 reg := &AgentServiceRegistration{ 694 Name: "foo", 695 Tags: []string{"bar", "baz"}, 696 Port: 8000, 697 Checks: AgentServiceChecks{ 698 &AgentServiceCheck{ 699 TTL: "15s", 700 }, 701 &AgentServiceCheck{ 702 TTL: "30s", 703 }, 704 }, 705 } 706 require.NoError(agent.ServiceRegister(reg)) 707 708 got, qm, err := agent.Service("foo", nil) 709 require.NoError(err) 710 711 expect := &AgentService{ 712 ID: "foo", 713 Service: "foo", 714 Tags: []string{"bar", "baz"}, 715 ContentHash: "ad8c7a278470d1e8", 716 Port: 8000, 717 Weights: AgentWeights{ 718 Passing: 1, 719 Warning: 1, 720 }, 721 } 722 require.Equal(expect, got) 723 require.Equal(expect.ContentHash, qm.LastContentHash) 724 725 // Sanity check blocking behavior - this is more thoroughly tested in the 726 // agent endpoint tests but this ensures that the API package is at least 727 // passing the hash param properly. 728 opts := QueryOptions{ 729 WaitHash: qm.LastContentHash, 730 WaitTime: 100 * time.Millisecond, // Just long enough to be reliably measurable 731 } 732 start := time.Now() 733 got, qm, err = agent.Service("foo", &opts) 734 elapsed := time.Since(start) 735 require.NoError(err) 736 require.True(elapsed >= opts.WaitTime) 737 } 738 739 func TestAPI_AgentSetTTLStatus(t *testing.T) { 740 t.Parallel() 741 c, s := makeClient(t) 742 defer s.Stop() 743 744 agent := c.Agent() 745 746 reg := &AgentServiceRegistration{ 747 Name: "foo", 748 Check: &AgentServiceCheck{ 749 TTL: "15s", 750 }, 751 } 752 if err := agent.ServiceRegister(reg); err != nil { 753 t.Fatalf("err: %v", err) 754 } 755 756 verify := func(status, output string) { 757 checks, err := agent.Checks() 758 if err != nil { 759 t.Fatalf("err: %v", err) 760 } 761 chk, ok := checks["service:foo"] 762 if !ok { 763 t.Fatalf("missing check: %v", checks) 764 } 765 if chk.Status != status { 766 t.Fatalf("Bad: %#v", chk) 767 } 768 if chk.Output != output { 769 t.Fatalf("Bad: %#v", chk) 770 } 771 } 772 773 if err := agent.WarnTTL("service:foo", "foo"); err != nil { 774 t.Fatalf("err: %v", err) 775 } 776 verify(HealthWarning, "foo") 777 778 if err := agent.PassTTL("service:foo", "bar"); err != nil { 779 t.Fatalf("err: %v", err) 780 } 781 verify(HealthPassing, "bar") 782 783 if err := agent.FailTTL("service:foo", "baz"); err != nil { 784 t.Fatalf("err: %v", err) 785 } 786 verify(HealthCritical, "baz") 787 788 if err := agent.UpdateTTL("service:foo", "foo", "warn"); err != nil { 789 t.Fatalf("err: %v", err) 790 } 791 verify(HealthWarning, "foo") 792 793 if err := agent.UpdateTTL("service:foo", "bar", "pass"); err != nil { 794 t.Fatalf("err: %v", err) 795 } 796 verify(HealthPassing, "bar") 797 798 if err := agent.UpdateTTL("service:foo", "baz", "fail"); err != nil { 799 t.Fatalf("err: %v", err) 800 } 801 verify(HealthCritical, "baz") 802 803 if err := agent.UpdateTTL("service:foo", "foo", HealthWarning); err != nil { 804 t.Fatalf("err: %v", err) 805 } 806 verify(HealthWarning, "foo") 807 808 if err := agent.UpdateTTL("service:foo", "bar", HealthPassing); err != nil { 809 t.Fatalf("err: %v", err) 810 } 811 verify(HealthPassing, "bar") 812 813 if err := agent.UpdateTTL("service:foo", "baz", HealthCritical); err != nil { 814 t.Fatalf("err: %v", err) 815 } 816 verify(HealthCritical, "baz") 817 818 if err := agent.ServiceDeregister("foo"); err != nil { 819 t.Fatalf("err: %v", err) 820 } 821 } 822 823 func TestAPI_AgentChecks(t *testing.T) { 824 t.Parallel() 825 c, s := makeClient(t) 826 defer s.Stop() 827 828 agent := c.Agent() 829 830 reg := &AgentCheckRegistration{ 831 Name: "foo", 832 } 833 reg.TTL = "15s" 834 if err := agent.CheckRegister(reg); err != nil { 835 t.Fatalf("err: %v", err) 836 } 837 838 checks, err := agent.Checks() 839 if err != nil { 840 t.Fatalf("err: %v", err) 841 } 842 chk, ok := checks["foo"] 843 if !ok { 844 t.Fatalf("missing check: %v", checks) 845 } 846 if chk.Status != HealthCritical { 847 t.Fatalf("check not critical: %v", chk) 848 } 849 850 if err := agent.CheckDeregister("foo"); err != nil { 851 t.Fatalf("err: %v", err) 852 } 853 } 854 855 func TestAPI_AgentScriptCheck(t *testing.T) { 856 t.Parallel() 857 c, s := makeClientWithConfig(t, nil, func(c *testutil.TestServerConfig) { 858 c.EnableScriptChecks = true 859 }) 860 defer s.Stop() 861 862 agent := c.Agent() 863 864 t.Run("node script check", func(t *testing.T) { 865 reg := &AgentCheckRegistration{ 866 Name: "foo", 867 AgentServiceCheck: AgentServiceCheck{ 868 Interval: "10s", 869 Args: []string{"sh", "-c", "false"}, 870 }, 871 } 872 if err := agent.CheckRegister(reg); err != nil { 873 t.Fatalf("err: %v", err) 874 } 875 876 checks, err := agent.Checks() 877 if err != nil { 878 t.Fatalf("err: %v", err) 879 } 880 if _, ok := checks["foo"]; !ok { 881 t.Fatalf("missing check: %v", checks) 882 } 883 }) 884 885 t.Run("service script check", func(t *testing.T) { 886 reg := &AgentServiceRegistration{ 887 Name: "bar", 888 Port: 1234, 889 Checks: AgentServiceChecks{ 890 &AgentServiceCheck{ 891 Interval: "10s", 892 Args: []string{"sh", "-c", "false"}, 893 }, 894 }, 895 } 896 if err := agent.ServiceRegister(reg); err != nil { 897 t.Fatalf("err: %v", err) 898 } 899 900 services, err := agent.Services() 901 if err != nil { 902 t.Fatalf("err: %v", err) 903 } 904 if _, ok := services["bar"]; !ok { 905 t.Fatalf("missing service: %v", services) 906 } 907 908 checks, err := agent.Checks() 909 if err != nil { 910 t.Fatalf("err: %v", err) 911 } 912 if _, ok := checks["service:bar"]; !ok { 913 t.Fatalf("missing check: %v", checks) 914 } 915 }) 916 } 917 918 func TestAPI_AgentCheckStartPassing(t *testing.T) { 919 t.Parallel() 920 c, s := makeClient(t) 921 defer s.Stop() 922 923 agent := c.Agent() 924 925 reg := &AgentCheckRegistration{ 926 Name: "foo", 927 AgentServiceCheck: AgentServiceCheck{ 928 Status: HealthPassing, 929 }, 930 } 931 reg.TTL = "15s" 932 if err := agent.CheckRegister(reg); err != nil { 933 t.Fatalf("err: %v", err) 934 } 935 936 checks, err := agent.Checks() 937 if err != nil { 938 t.Fatalf("err: %v", err) 939 } 940 chk, ok := checks["foo"] 941 if !ok { 942 t.Fatalf("missing check: %v", checks) 943 } 944 if chk.Status != HealthPassing { 945 t.Fatalf("check not passing: %v", chk) 946 } 947 948 if err := agent.CheckDeregister("foo"); err != nil { 949 t.Fatalf("err: %v", err) 950 } 951 } 952 953 func TestAPI_AgentChecks_serviceBound(t *testing.T) { 954 t.Parallel() 955 c, s := makeClient(t) 956 defer s.Stop() 957 958 agent := c.Agent() 959 960 // First register a service 961 serviceReg := &AgentServiceRegistration{ 962 Name: "redis", 963 } 964 if err := agent.ServiceRegister(serviceReg); err != nil { 965 t.Fatalf("err: %v", err) 966 } 967 968 // Register a check bound to the service 969 reg := &AgentCheckRegistration{ 970 Name: "redischeck", 971 ServiceID: "redis", 972 } 973 reg.TTL = "15s" 974 reg.DeregisterCriticalServiceAfter = "nope" 975 err := agent.CheckRegister(reg) 976 if err == nil || !strings.Contains(err.Error(), "invalid duration") { 977 t.Fatalf("err: %v", err) 978 } 979 980 reg.DeregisterCriticalServiceAfter = "90m" 981 if err := agent.CheckRegister(reg); err != nil { 982 t.Fatalf("err: %v", err) 983 } 984 985 checks, err := agent.Checks() 986 if err != nil { 987 t.Fatalf("err: %v", err) 988 } 989 990 check, ok := checks["redischeck"] 991 if !ok { 992 t.Fatalf("missing check: %v", checks) 993 } 994 if check.ServiceID != "redis" { 995 t.Fatalf("missing service association for check: %v", check) 996 } 997 } 998 999 func TestAPI_AgentChecks_Docker(t *testing.T) { 1000 t.Parallel() 1001 c, s := makeClientWithConfig(t, nil, func(c *testutil.TestServerConfig) { 1002 c.EnableScriptChecks = true 1003 }) 1004 defer s.Stop() 1005 1006 agent := c.Agent() 1007 1008 // First register a service 1009 serviceReg := &AgentServiceRegistration{ 1010 Name: "redis", 1011 } 1012 if err := agent.ServiceRegister(serviceReg); err != nil { 1013 t.Fatalf("err: %v", err) 1014 } 1015 1016 // Register a check bound to the service 1017 reg := &AgentCheckRegistration{ 1018 Name: "redischeck", 1019 ServiceID: "redis", 1020 AgentServiceCheck: AgentServiceCheck{ 1021 DockerContainerID: "f972c95ebf0e", 1022 Args: []string{"/bin/true"}, 1023 Shell: "/bin/bash", 1024 Interval: "10s", 1025 }, 1026 } 1027 if err := agent.CheckRegister(reg); err != nil { 1028 t.Fatalf("err: %v", err) 1029 } 1030 1031 checks, err := agent.Checks() 1032 if err != nil { 1033 t.Fatalf("err: %v", err) 1034 } 1035 1036 check, ok := checks["redischeck"] 1037 if !ok { 1038 t.Fatalf("missing check: %v", checks) 1039 } 1040 if check.ServiceID != "redis" { 1041 t.Fatalf("missing service association for check: %v", check) 1042 } 1043 } 1044 1045 func TestAPI_AgentJoin(t *testing.T) { 1046 t.Parallel() 1047 c, s := makeClient(t) 1048 defer s.Stop() 1049 1050 agent := c.Agent() 1051 1052 info, err := agent.Self() 1053 if err != nil { 1054 t.Fatalf("err: %v", err) 1055 } 1056 1057 // Join ourself 1058 addr := info["DebugConfig"]["SerfAdvertiseAddrLAN"].(string) 1059 // strip off 'tcp://' 1060 addr = addr[len("tcp://"):] 1061 err = agent.Join(addr, false) 1062 if err != nil { 1063 t.Fatalf("err: %v", err) 1064 } 1065 } 1066 1067 func TestAPI_AgentLeave(t *testing.T) { 1068 t.Parallel() 1069 c1, s1 := makeClient(t) 1070 defer s1.Stop() 1071 1072 c2, s2 := makeClientWithConfig(t, nil, func(conf *testutil.TestServerConfig) { 1073 conf.Server = false 1074 conf.Bootstrap = false 1075 }) 1076 defer s2.Stop() 1077 1078 if err := c2.Agent().Join(s1.LANAddr, false); err != nil { 1079 t.Fatalf("err: %v", err) 1080 } 1081 1082 // We sometimes see an EOF response to this one, depending on timing. 1083 err := c2.Agent().Leave() 1084 if err != nil && !strings.Contains(err.Error(), "EOF") { 1085 t.Fatalf("err: %v", err) 1086 } 1087 1088 // Make sure the second agent's status is 'Left' 1089 members, err := c1.Agent().Members(false) 1090 if err != nil { 1091 t.Fatalf("err: %v", err) 1092 } 1093 member := members[0] 1094 if member.Name == s1.Config.NodeName { 1095 member = members[1] 1096 } 1097 if member.Status != int(serf.StatusLeft) { 1098 t.Fatalf("bad: %v", *member) 1099 } 1100 } 1101 1102 func TestAPI_AgentForceLeave(t *testing.T) { 1103 t.Parallel() 1104 c, s := makeClient(t) 1105 defer s.Stop() 1106 1107 agent := c.Agent() 1108 1109 // Eject somebody 1110 err := agent.ForceLeave("foo") 1111 if err != nil { 1112 t.Fatalf("err: %v", err) 1113 } 1114 } 1115 1116 func TestAPI_AgentMonitor(t *testing.T) { 1117 t.Parallel() 1118 c, s := makeClient(t) 1119 defer s.Stop() 1120 1121 agent := c.Agent() 1122 1123 logCh, err := agent.Monitor("info", nil, nil) 1124 if err != nil { 1125 t.Fatalf("err: %v", err) 1126 } 1127 1128 // Wait for the first log message and validate it 1129 select { 1130 case log := <-logCh: 1131 if !strings.Contains(log, "[INFO]") { 1132 t.Fatalf("bad: %q", log) 1133 } 1134 case <-time.After(10 * time.Second): 1135 t.Fatalf("failed to get a log message") 1136 } 1137 } 1138 1139 func TestAPI_ServiceMaintenance(t *testing.T) { 1140 t.Parallel() 1141 c, s := makeClient(t) 1142 defer s.Stop() 1143 1144 agent := c.Agent() 1145 1146 // First register a service 1147 serviceReg := &AgentServiceRegistration{ 1148 Name: "redis", 1149 } 1150 if err := agent.ServiceRegister(serviceReg); err != nil { 1151 t.Fatalf("err: %v", err) 1152 } 1153 1154 // Enable maintenance mode 1155 if err := agent.EnableServiceMaintenance("redis", "broken"); err != nil { 1156 t.Fatalf("err: %s", err) 1157 } 1158 1159 // Ensure a critical check was added 1160 checks, err := agent.Checks() 1161 if err != nil { 1162 t.Fatalf("err: %v", err) 1163 } 1164 found := false 1165 for _, check := range checks { 1166 if strings.Contains(check.CheckID, "maintenance") { 1167 found = true 1168 if check.Status != HealthCritical || check.Notes != "broken" { 1169 t.Fatalf("bad: %#v", checks) 1170 } 1171 } 1172 } 1173 if !found { 1174 t.Fatalf("bad: %#v", checks) 1175 } 1176 1177 // Disable maintenance mode 1178 if err := agent.DisableServiceMaintenance("redis"); err != nil { 1179 t.Fatalf("err: %s", err) 1180 } 1181 1182 // Ensure the critical health check was removed 1183 checks, err = agent.Checks() 1184 if err != nil { 1185 t.Fatalf("err: %s", err) 1186 } 1187 for _, check := range checks { 1188 if strings.Contains(check.CheckID, "maintenance") { 1189 t.Fatalf("should have removed health check") 1190 } 1191 } 1192 } 1193 1194 func TestAPI_NodeMaintenance(t *testing.T) { 1195 t.Parallel() 1196 c, s := makeClient(t) 1197 defer s.Stop() 1198 1199 agent := c.Agent() 1200 1201 // Enable maintenance mode 1202 if err := agent.EnableNodeMaintenance("broken"); err != nil { 1203 t.Fatalf("err: %s", err) 1204 } 1205 1206 // Check that a critical check was added 1207 checks, err := agent.Checks() 1208 if err != nil { 1209 t.Fatalf("err: %s", err) 1210 } 1211 found := false 1212 for _, check := range checks { 1213 if strings.Contains(check.CheckID, "maintenance") { 1214 found = true 1215 if check.Status != HealthCritical || check.Notes != "broken" { 1216 t.Fatalf("bad: %#v", checks) 1217 } 1218 } 1219 } 1220 if !found { 1221 t.Fatalf("bad: %#v", checks) 1222 } 1223 1224 // Disable maintenance mode 1225 if err := agent.DisableNodeMaintenance(); err != nil { 1226 t.Fatalf("err: %s", err) 1227 } 1228 1229 // Ensure the check was removed 1230 checks, err = agent.Checks() 1231 if err != nil { 1232 t.Fatalf("err: %s", err) 1233 } 1234 for _, check := range checks { 1235 if strings.Contains(check.CheckID, "maintenance") { 1236 t.Fatalf("should have removed health check") 1237 } 1238 } 1239 } 1240 1241 func TestAPI_AgentUpdateToken(t *testing.T) { 1242 t.Parallel() 1243 c, s := makeACLClient(t) 1244 defer s.Stop() 1245 1246 agent := c.Agent() 1247 1248 if _, err := agent.UpdateACLToken("root", nil); err != nil { 1249 t.Fatalf("err: %v", err) 1250 } 1251 1252 if _, err := agent.UpdateACLAgentToken("root", nil); err != nil { 1253 t.Fatalf("err: %v", err) 1254 } 1255 1256 if _, err := agent.UpdateACLAgentMasterToken("root", nil); err != nil { 1257 t.Fatalf("err: %v", err) 1258 } 1259 1260 if _, err := agent.UpdateACLReplicationToken("root", nil); err != nil { 1261 t.Fatalf("err: %v", err) 1262 } 1263 1264 if _, err := agent.UpdateDefaultACLToken("root", nil); err != nil { 1265 t.Fatalf("err: %v", err) 1266 } 1267 1268 if _, err := agent.UpdateAgentACLToken("root", nil); err != nil { 1269 t.Fatalf("err: %v", err) 1270 } 1271 1272 if _, err := agent.UpdateAgentMasterACLToken("root", nil); err != nil { 1273 t.Fatalf("err: %v", err) 1274 } 1275 1276 if _, err := agent.UpdateReplicationACLToken("root", nil); err != nil { 1277 t.Fatalf("err: %v", err) 1278 } 1279 } 1280 1281 func TestAPI_AgentConnectCARoots_empty(t *testing.T) { 1282 t.Parallel() 1283 1284 require := require.New(t) 1285 c, s := makeClientWithConfig(t, nil, func(c *testutil.TestServerConfig) { 1286 c.Connect = nil // disable connect to prevent CA being bootstrapped 1287 }) 1288 defer s.Stop() 1289 1290 agent := c.Agent() 1291 _, _, err := agent.ConnectCARoots(nil) 1292 require.Error(err) 1293 require.Contains(err.Error(), "Connect must be enabled") 1294 } 1295 1296 func TestAPI_AgentConnectCARoots_list(t *testing.T) { 1297 t.Parallel() 1298 1299 require := require.New(t) 1300 c, s := makeClient(t) 1301 defer s.Stop() 1302 1303 agent := c.Agent() 1304 s.WaitForSerfCheck(t) 1305 list, meta, err := agent.ConnectCARoots(nil) 1306 require.NoError(err) 1307 require.True(meta.LastIndex > 0) 1308 require.Len(list.Roots, 1) 1309 } 1310 1311 func TestAPI_AgentConnectCALeaf(t *testing.T) { 1312 t.Parallel() 1313 1314 require := require.New(t) 1315 c, s := makeClient(t) 1316 defer s.Stop() 1317 1318 agent := c.Agent() 1319 // Setup service 1320 reg := &AgentServiceRegistration{ 1321 Name: "foo", 1322 Tags: []string{"bar", "baz"}, 1323 Port: 8000, 1324 } 1325 require.NoError(agent.ServiceRegister(reg)) 1326 1327 leaf, meta, err := agent.ConnectCALeaf("foo", nil) 1328 require.NoError(err) 1329 require.True(meta.LastIndex > 0) 1330 // Sanity checks here as we have actual certificate validation checks at many 1331 // other levels. 1332 require.NotEmpty(leaf.SerialNumber) 1333 require.NotEmpty(leaf.CertPEM) 1334 require.NotEmpty(leaf.PrivateKeyPEM) 1335 require.Equal("foo", leaf.Service) 1336 require.True(strings.HasSuffix(leaf.ServiceURI, "/svc/foo")) 1337 require.True(leaf.ModifyIndex > 0) 1338 require.True(leaf.ValidAfter.Before(time.Now())) 1339 require.True(leaf.ValidBefore.After(time.Now())) 1340 } 1341 1342 func TestAPI_AgentConnectAuthorize(t *testing.T) { 1343 t.Parallel() 1344 require := require.New(t) 1345 c, s := makeClient(t) 1346 defer s.Stop() 1347 1348 agent := c.Agent() 1349 s.WaitForSerfCheck(t) 1350 params := &AgentAuthorizeParams{ 1351 Target: "foo", 1352 ClientCertSerial: "fake", 1353 // Importing connect.TestSpiffeIDService creates an import cycle 1354 ClientCertURI: "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/ny1/svc/web", 1355 } 1356 auth, err := agent.ConnectAuthorize(params) 1357 require.Nil(err) 1358 require.True(auth.Authorized) 1359 require.Equal(auth.Reason, "ACLs disabled, access is allowed by default") 1360 } 1361 1362 func TestAPI_AgentConnectProxyConfig(t *testing.T) { 1363 t.Parallel() 1364 c, s := makeClientWithConfig(t, nil, func(c *testutil.TestServerConfig) { 1365 // Force auto port range to 1 port so we have deterministic response. 1366 c.Ports.ProxyMinPort = 20000 1367 c.Ports.ProxyMaxPort = 20000 1368 }) 1369 defer s.Stop() 1370 1371 agent := c.Agent() 1372 reg := &AgentServiceRegistration{ 1373 Name: "foo", 1374 Tags: []string{"bar", "baz"}, 1375 Port: 8000, 1376 Connect: &AgentServiceConnect{ 1377 Proxy: &AgentServiceConnectProxy{ 1378 Command: []string{"consul", "connect", "proxy"}, 1379 Config: map[string]interface{}{ 1380 "foo": "bar", 1381 }, 1382 Upstreams: testUpstreams(t), 1383 }, 1384 }, 1385 } 1386 if err := agent.ServiceRegister(reg); err != nil { 1387 t.Fatalf("err: %v", err) 1388 } 1389 1390 config, qm, err := agent.ConnectProxyConfig("foo-proxy", nil) 1391 require.NoError(t, err) 1392 expectConfig := &ConnectProxyConfig{ 1393 ProxyServiceID: "foo-proxy", 1394 TargetServiceID: "foo", 1395 TargetServiceName: "foo", 1396 ContentHash: "acdf5eb6f5794a14", 1397 ExecMode: "daemon", 1398 Command: []string{"consul", "connect", "proxy"}, 1399 Config: map[string]interface{}{ 1400 "bind_address": "127.0.0.1", 1401 "bind_port": float64(20000), 1402 "foo": "bar", 1403 "local_service_address": "127.0.0.1:8000", 1404 }, 1405 Upstreams: testExpectUpstreamsWithDefaults(t, reg.Connect.Proxy.Upstreams), 1406 } 1407 require.Equal(t, expectConfig, config) 1408 require.Equal(t, expectConfig.ContentHash, qm.LastContentHash) 1409 } 1410 1411 func TestAPI_AgentHealthService(t *testing.T) { 1412 t.Parallel() 1413 c, s := makeClient(t) 1414 defer s.Stop() 1415 1416 agent := c.Agent() 1417 1418 requireServiceHealthID := func(t *testing.T, serviceID, expected string, shouldExist bool) { 1419 msg := fmt.Sprintf("service id:%s, shouldExist:%v, expectedStatus:%s : bad %%s", serviceID, shouldExist, expected) 1420 1421 state, out, err := agent.AgentHealthServiceByID(serviceID) 1422 require.Nil(t, err, msg, "err") 1423 require.Equal(t, expected, state, msg, "state") 1424 if !shouldExist { 1425 require.Nil(t, out, msg, "shouldExist") 1426 } else { 1427 require.NotNil(t, out, msg, "output") 1428 require.Equal(t, serviceID, out.Service.ID, msg, "output") 1429 } 1430 } 1431 requireServiceHealthName := func(t *testing.T, serviceName, expected string, shouldExist bool) { 1432 msg := fmt.Sprintf("service name:%s, shouldExist:%v, expectedStatus:%s : bad %%s", serviceName, shouldExist, expected) 1433 1434 state, outs, err := agent.AgentHealthServiceByName(serviceName) 1435 require.Nil(t, err, msg, "err") 1436 require.Equal(t, expected, state, msg, "state") 1437 if !shouldExist { 1438 require.Equal(t, 0, len(outs), msg, "output") 1439 } else { 1440 require.True(t, len(outs) > 0, msg, "output") 1441 for _, o := range outs { 1442 require.Equal(t, serviceName, o.Service.Service, msg, "output") 1443 } 1444 } 1445 } 1446 1447 requireServiceHealthID(t, "_i_do_not_exist_", HealthCritical, false) 1448 requireServiceHealthName(t, "_i_do_not_exist_", HealthCritical, false) 1449 1450 testServiceID1 := "foo" 1451 testServiceID2 := "foofoo" 1452 testServiceName := "bar" 1453 1454 // register service 1455 reg := &AgentServiceRegistration{ 1456 Name: testServiceName, 1457 ID: testServiceID1, 1458 Port: 8000, 1459 Check: &AgentServiceCheck{ 1460 TTL: "15s", 1461 }, 1462 } 1463 err := agent.ServiceRegister(reg) 1464 require.Nil(t, err) 1465 requireServiceHealthID(t, testServiceID1, HealthCritical, true) 1466 requireServiceHealthName(t, testServiceName, HealthCritical, true) 1467 1468 err = agent.WarnTTL(fmt.Sprintf("service:%s", testServiceID1), "I am warn") 1469 require.Nil(t, err) 1470 requireServiceHealthName(t, testServiceName, HealthWarning, true) 1471 requireServiceHealthID(t, testServiceID1, HealthWarning, true) 1472 1473 err = agent.PassTTL(fmt.Sprintf("service:%s", testServiceID1), "I am good :)") 1474 require.Nil(t, err) 1475 requireServiceHealthName(t, testServiceName, HealthPassing, true) 1476 requireServiceHealthID(t, testServiceID1, HealthPassing, true) 1477 1478 err = agent.FailTTL(fmt.Sprintf("service:%s", testServiceID1), "I am dead.") 1479 require.Nil(t, err) 1480 requireServiceHealthName(t, testServiceName, HealthCritical, true) 1481 requireServiceHealthID(t, testServiceID1, HealthCritical, true) 1482 1483 // register another service 1484 reg = &AgentServiceRegistration{ 1485 Name: testServiceName, 1486 ID: testServiceID2, 1487 Port: 8000, 1488 Check: &AgentServiceCheck{ 1489 TTL: "15s", 1490 }, 1491 } 1492 err = agent.ServiceRegister(reg) 1493 require.Nil(t, err) 1494 requireServiceHealthName(t, testServiceName, HealthCritical, true) 1495 1496 err = agent.PassTTL(fmt.Sprintf("service:%s", testServiceID1), "I am good :)") 1497 require.Nil(t, err) 1498 requireServiceHealthName(t, testServiceName, HealthCritical, true) 1499 1500 err = agent.WarnTTL(fmt.Sprintf("service:%s", testServiceID2), "I am warn") 1501 require.Nil(t, err) 1502 requireServiceHealthName(t, testServiceName, HealthWarning, true) 1503 1504 err = agent.PassTTL(fmt.Sprintf("service:%s", testServiceID2), "I am good :)") 1505 require.Nil(t, err) 1506 requireServiceHealthName(t, testServiceName, HealthPassing, true) 1507 }