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