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} 625 626func TestAPI_AgentEnableTagOverride(t *testing.T) { 627 t.Parallel() 628 c, s := makeClient(t) 629 defer s.Stop() 630 631 agent := c.Agent() 632 633 reg1 := &AgentServiceRegistration{ 634 Name: "foo1", 635 Port: 8000, 636 Address: "192.168.0.42", 637 EnableTagOverride: true, 638 } 639 reg2 := &AgentServiceRegistration{ 640 Name: "foo2", 641 Port: 8000, 642 } 643 if err := agent.ServiceRegister(reg1); err != nil { 644 t.Fatalf("err: %v", err) 645 } 646 if err := agent.ServiceRegister(reg2); err != nil { 647 t.Fatalf("err: %v", err) 648 } 649 650 services, err := agent.Services() 651 if err != nil { 652 t.Fatalf("err: %v", err) 653 } 654 655 if _, ok := services["foo1"]; !ok { 656 t.Fatalf("missing service: %v", services) 657 } 658 if services["foo1"].EnableTagOverride != true { 659 t.Fatalf("tag override not set on service foo1: %v", services) 660 } 661 if _, ok := services["foo2"]; !ok { 662 t.Fatalf("missing service: %v", services) 663 } 664 if services["foo2"].EnableTagOverride != false { 665 t.Fatalf("tag override set on service foo2: %v", services) 666 } 667} 668 669func TestAPI_AgentServices_MultipleChecks(t *testing.T) { 670 t.Parallel() 671 c, s := makeClient(t) 672 defer s.Stop() 673 674 agent := c.Agent() 675 676 reg := &AgentServiceRegistration{ 677 Name: "foo", 678 Tags: []string{"bar", "baz"}, 679 Port: 8000, 680 Checks: AgentServiceChecks{ 681 &AgentServiceCheck{ 682 TTL: "15s", 683 }, 684 &AgentServiceCheck{ 685 TTL: "30s", 686 }, 687 }, 688 } 689 if err := agent.ServiceRegister(reg); err != nil { 690 t.Fatalf("err: %v", err) 691 } 692 693 services, err := agent.Services() 694 if err != nil { 695 t.Fatalf("err: %v", err) 696 } 697 if _, ok := services["foo"]; !ok { 698 t.Fatalf("missing service: %v", services) 699 } 700 701 checks, err := agent.Checks() 702 if err != nil { 703 t.Fatalf("err: %v", err) 704 } 705 if _, ok := checks["service:foo:1"]; !ok { 706 t.Fatalf("missing check: %v", checks) 707 } 708 if _, ok := checks["service:foo:2"]; !ok { 709 t.Fatalf("missing check: %v", checks) 710 } 711} 712 713func TestAPI_AgentService(t *testing.T) { 714 t.Parallel() 715 c, s := makeClient(t) 716 defer s.Stop() 717 718 agent := c.Agent() 719 720 require := require.New(t) 721 722 reg := &AgentServiceRegistration{ 723 Name: "foo", 724 Tags: []string{"bar", "baz"}, 725 Port: 8000, 726 Checks: AgentServiceChecks{ 727 &AgentServiceCheck{ 728 TTL: "15s", 729 }, 730 &AgentServiceCheck{ 731 TTL: "30s", 732 }, 733 }, 734 } 735 require.NoError(agent.ServiceRegister(reg)) 736 737 got, qm, err := agent.Service("foo", nil) 738 require.NoError(err) 739 740 expect := &AgentService{ 741 ID: "foo", 742 Service: "foo", 743 Tags: []string{"bar", "baz"}, 744 ContentHash: "f72563cae6924fb5", 745 Port: 8000, 746 Weights: AgentWeights{ 747 Passing: 1, 748 Warning: 1, 749 }, 750 Meta: map[string]string{}, 751 Namespace: defaultNamespace, 752 Datacenter: "dc1", 753 } 754 require.Equal(expect, got) 755 require.Equal(expect.ContentHash, qm.LastContentHash) 756 757 // Sanity check blocking behavior - this is more thoroughly tested in the 758 // agent endpoint tests but this ensures that the API package is at least 759 // passing the hash param properly. 760 opts := QueryOptions{ 761 WaitHash: qm.LastContentHash, 762 WaitTime: 100 * time.Millisecond, // Just long enough to be reliably measurable 763 } 764 start := time.Now() 765 _, _, err = agent.Service("foo", &opts) 766 elapsed := time.Since(start) 767 require.NoError(err) 768 require.True(elapsed >= opts.WaitTime) 769} 770 771func TestAPI_AgentSetTTLStatus(t *testing.T) { 772 t.Parallel() 773 c, s := makeClient(t) 774 defer s.Stop() 775 776 agent := c.Agent() 777 s.WaitForSerfCheck(t) 778 779 reg := &AgentServiceRegistration{ 780 Name: "foo", 781 Check: &AgentServiceCheck{ 782 TTL: "15s", 783 }, 784 } 785 if err := agent.ServiceRegister(reg); err != nil { 786 t.Fatalf("err: %v", err) 787 } 788 789 verify := func(status, output string) { 790 checks, err := agent.Checks() 791 if err != nil { 792 t.Fatalf("err: %v", err) 793 } 794 chk, ok := checks["service:foo"] 795 if !ok { 796 t.Fatalf("missing check: %v", checks) 797 } 798 if chk.Status != status { 799 t.Fatalf("Bad: %#v", chk) 800 } 801 if chk.Output != output { 802 t.Fatalf("Bad: %#v", chk) 803 } 804 } 805 806 if err := agent.WarnTTL("service:foo", "foo"); err != nil { 807 t.Fatalf("err: %v", err) 808 } 809 verify(HealthWarning, "foo") 810 811 if err := agent.PassTTL("service:foo", "bar"); err != nil { 812 t.Fatalf("err: %v", err) 813 } 814 verify(HealthPassing, "bar") 815 816 if err := agent.FailTTL("service:foo", "baz"); err != nil { 817 t.Fatalf("err: %v", err) 818 } 819 verify(HealthCritical, "baz") 820 821 if err := agent.UpdateTTL("service:foo", "foo", "warn"); err != nil { 822 t.Fatalf("err: %v", err) 823 } 824 verify(HealthWarning, "foo") 825 826 if err := agent.UpdateTTL("service:foo", "bar", "pass"); err != nil { 827 t.Fatalf("err: %v", err) 828 } 829 verify(HealthPassing, "bar") 830 831 if err := agent.UpdateTTL("service:foo", "baz", "fail"); err != nil { 832 t.Fatalf("err: %v", err) 833 } 834 verify(HealthCritical, "baz") 835 836 if err := agent.UpdateTTL("service:foo", "foo", HealthWarning); err != nil { 837 t.Fatalf("err: %v", err) 838 } 839 verify(HealthWarning, "foo") 840 841 if err := agent.UpdateTTL("service:foo", "bar", HealthPassing); err != nil { 842 t.Fatalf("err: %v", err) 843 } 844 verify(HealthPassing, "bar") 845 846 if err := agent.UpdateTTL("service:foo", "baz", HealthCritical); err != nil { 847 t.Fatalf("err: %v", err) 848 } 849 verify(HealthCritical, "baz") 850 851 if err := agent.ServiceDeregister("foo"); err != nil { 852 t.Fatalf("err: %v", err) 853 } 854} 855 856func TestAPI_AgentUpdateTTLOpts(t *testing.T) { 857 t.Parallel() 858 c, s := makeClient(t) 859 defer s.Stop() 860 861 agent := c.Agent() 862 s.WaitForSerfCheck(t) 863 864 reg := &AgentServiceRegistration{ 865 Name: "foo", 866 Check: &AgentServiceCheck{ 867 TTL: "15s", 868 }, 869 } 870 if err := agent.ServiceRegister(reg); err != nil { 871 t.Fatalf("err: %v", err) 872 } 873 874 verify := func(status, output string) { 875 checks, err := agent.Checks() 876 if err != nil { 877 t.Fatalf("err: %v", err) 878 } 879 chk, ok := checks["service:foo"] 880 if !ok { 881 t.Fatalf("missing check: %v", checks) 882 } 883 if chk.Status != status { 884 t.Fatalf("Bad: %#v", chk) 885 } 886 if chk.Output != output { 887 t.Fatalf("Bad: %#v", chk) 888 } 889 } 890 891 opts := &QueryOptions{Namespace: defaultNamespace} 892 893 if err := agent.UpdateTTLOpts("service:foo", "foo", HealthWarning, opts); err != nil { 894 t.Fatalf("err: %v", err) 895 } 896 verify(HealthWarning, "foo") 897 898 if err := agent.UpdateTTLOpts("service:foo", "bar", HealthPassing, opts); err != nil { 899 t.Fatalf("err: %v", err) 900 } 901 verify(HealthPassing, "bar") 902 903 if err := agent.UpdateTTL("service:foo", "baz", HealthCritical); err != nil { 904 t.Fatalf("err: %v", err) 905 } 906 verify(HealthCritical, "baz") 907 908 if err := agent.ServiceDeregister("foo"); err != nil { 909 t.Fatalf("err: %v", err) 910 } 911} 912 913func TestAPI_AgentChecks(t *testing.T) { 914 t.Parallel() 915 c, s := makeClient(t) 916 defer s.Stop() 917 918 agent := c.Agent() 919 920 reg := &AgentCheckRegistration{ 921 Name: "foo", 922 } 923 reg.TTL = "15s" 924 if err := agent.CheckRegister(reg); err != nil { 925 t.Fatalf("err: %v", err) 926 } 927 928 checks, err := agent.Checks() 929 if err != nil { 930 t.Fatalf("err: %v", err) 931 } 932 chk, ok := checks["foo"] 933 if !ok { 934 t.Fatalf("missing check: %v", checks) 935 } 936 if chk.Status != HealthCritical { 937 t.Fatalf("check not critical: %v", chk) 938 } 939 if chk.Type != "ttl" { 940 t.Fatalf("expected type ttl, got %s", chk.Type) 941 } 942 943 if err := agent.CheckDeregister("foo"); err != nil { 944 t.Fatalf("err: %v", err) 945 } 946} 947 948func TestAPI_AgentChecksWithFilterOpts(t *testing.T) { 949 t.Parallel() 950 c, s := makeClient(t) 951 defer s.Stop() 952 953 agent := c.Agent() 954 955 reg := &AgentCheckRegistration{ 956 Name: "foo", 957 } 958 reg.TTL = "15s" 959 require.NoError(t, agent.CheckRegister(reg)) 960 reg = &AgentCheckRegistration{ 961 Name: "bar", 962 } 963 reg.TTL = "15s" 964 require.NoError(t, agent.CheckRegister(reg)) 965 966 opts := &QueryOptions{Namespace: defaultNamespace} 967 checks, err := agent.ChecksWithFilterOpts("Name == foo", opts) 968 require.NoError(t, err) 969 require.Len(t, checks, 1) 970 _, ok := checks["foo"] 971 require.True(t, ok) 972} 973 974func TestAPI_AgentScriptCheck(t *testing.T) { 975 t.Parallel() 976 c, s := makeClientWithConfig(t, nil, func(c *testutil.TestServerConfig) { 977 c.EnableScriptChecks = true 978 }) 979 defer s.Stop() 980 981 agent := c.Agent() 982 983 t.Run("node script check", func(t *testing.T) { 984 reg := &AgentCheckRegistration{ 985 Name: "foo", 986 AgentServiceCheck: AgentServiceCheck{ 987 Interval: "10s", 988 Args: []string{"sh", "-c", "false"}, 989 }, 990 } 991 if err := agent.CheckRegister(reg); err != nil { 992 t.Fatalf("err: %v", err) 993 } 994 995 checks, err := agent.Checks() 996 if err != nil { 997 t.Fatalf("err: %v", err) 998 } 999 if _, ok := checks["foo"]; !ok { 1000 t.Fatalf("missing check: %v", checks) 1001 } 1002 }) 1003 1004 t.Run("service script check", func(t *testing.T) { 1005 reg := &AgentServiceRegistration{ 1006 Name: "bar", 1007 Port: 1234, 1008 Checks: AgentServiceChecks{ 1009 &AgentServiceCheck{ 1010 Interval: "10s", 1011 Args: []string{"sh", "-c", "false"}, 1012 }, 1013 }, 1014 } 1015 if err := agent.ServiceRegister(reg); err != nil { 1016 t.Fatalf("err: %v", err) 1017 } 1018 1019 services, err := agent.Services() 1020 if err != nil { 1021 t.Fatalf("err: %v", err) 1022 } 1023 if _, ok := services["bar"]; !ok { 1024 t.Fatalf("missing service: %v", services) 1025 } 1026 1027 checks, err := agent.Checks() 1028 if err != nil { 1029 t.Fatalf("err: %v", err) 1030 } 1031 if _, ok := checks["service:bar"]; !ok { 1032 t.Fatalf("missing check: %v", checks) 1033 } 1034 }) 1035} 1036 1037func TestAPI_AgentCheckStartPassing(t *testing.T) { 1038 t.Parallel() 1039 c, s := makeClient(t) 1040 defer s.Stop() 1041 1042 agent := c.Agent() 1043 1044 reg := &AgentCheckRegistration{ 1045 Name: "foo", 1046 AgentServiceCheck: AgentServiceCheck{ 1047 Status: HealthPassing, 1048 }, 1049 } 1050 reg.TTL = "15s" 1051 if err := agent.CheckRegister(reg); err != nil { 1052 t.Fatalf("err: %v", err) 1053 } 1054 1055 checks, err := agent.Checks() 1056 if err != nil { 1057 t.Fatalf("err: %v", err) 1058 } 1059 chk, ok := checks["foo"] 1060 if !ok { 1061 t.Fatalf("missing check: %v", checks) 1062 } 1063 if chk.Status != HealthPassing { 1064 t.Fatalf("check not passing: %v", chk) 1065 } 1066 1067 if err := agent.CheckDeregister("foo"); err != nil { 1068 t.Fatalf("err: %v", err) 1069 } 1070} 1071 1072func TestAPI_AgentChecks_serviceBound(t *testing.T) { 1073 t.Parallel() 1074 c, s := makeClient(t) 1075 defer s.Stop() 1076 1077 agent := c.Agent() 1078 s.WaitForSerfCheck(t) 1079 1080 // First register a service 1081 serviceReg := &AgentServiceRegistration{ 1082 Name: "redis", 1083 } 1084 if err := agent.ServiceRegister(serviceReg); err != nil { 1085 t.Fatalf("err: %v", err) 1086 } 1087 1088 // Register a check bound to the service 1089 reg := &AgentCheckRegistration{ 1090 Name: "redischeck", 1091 ServiceID: "redis", 1092 } 1093 reg.TTL = "15s" 1094 reg.DeregisterCriticalServiceAfter = "nope" 1095 err := agent.CheckRegister(reg) 1096 if err == nil || !strings.Contains(err.Error(), "invalid duration") { 1097 t.Fatalf("err: %v", err) 1098 } 1099 1100 reg.DeregisterCriticalServiceAfter = "90m" 1101 if err := agent.CheckRegister(reg); err != nil { 1102 t.Fatalf("err: %v", err) 1103 } 1104 1105 checks, err := agent.Checks() 1106 if err != nil { 1107 t.Fatalf("err: %v", err) 1108 } 1109 1110 check, ok := checks["redischeck"] 1111 if !ok { 1112 t.Fatalf("missing check: %v", checks) 1113 } 1114 if check.ServiceID != "redis" { 1115 t.Fatalf("missing service association for check: %v", check) 1116 } 1117 if check.Type != "ttl" { 1118 t.Fatalf("expected type ttl, got %s", check.Type) 1119 } 1120} 1121 1122func TestAPI_AgentChecks_Docker(t *testing.T) { 1123 t.Parallel() 1124 c, s := makeClientWithConfig(t, nil, func(c *testutil.TestServerConfig) { 1125 c.EnableScriptChecks = true 1126 }) 1127 defer s.Stop() 1128 1129 agent := c.Agent() 1130 1131 // First register a service 1132 serviceReg := &AgentServiceRegistration{ 1133 Name: "redis", 1134 } 1135 if err := agent.ServiceRegister(serviceReg); err != nil { 1136 t.Fatalf("err: %v", err) 1137 } 1138 1139 // Register a check bound to the service 1140 reg := &AgentCheckRegistration{ 1141 Name: "redischeck", 1142 ServiceID: "redis", 1143 AgentServiceCheck: AgentServiceCheck{ 1144 DockerContainerID: "f972c95ebf0e", 1145 Args: []string{"/bin/true"}, 1146 Shell: "/bin/bash", 1147 Interval: "10s", 1148 }, 1149 } 1150 if err := agent.CheckRegister(reg); err != nil { 1151 t.Fatalf("err: %v", err) 1152 } 1153 1154 checks, err := agent.Checks() 1155 if err != nil { 1156 t.Fatalf("err: %v", err) 1157 } 1158 1159 check, ok := checks["redischeck"] 1160 if !ok { 1161 t.Fatalf("missing check: %v", checks) 1162 } 1163 if check.ServiceID != "redis" { 1164 t.Fatalf("missing service association for check: %v", check) 1165 } 1166 if check.Type != "docker" { 1167 t.Fatalf("expected type docker, got %s", check.Type) 1168 } 1169} 1170 1171func TestAPI_AgentJoin(t *testing.T) { 1172 t.Parallel() 1173 c, s := makeClient(t) 1174 defer s.Stop() 1175 1176 agent := c.Agent() 1177 1178 info, err := agent.Self() 1179 if err != nil { 1180 t.Fatalf("err: %v", err) 1181 } 1182 1183 // Join ourself 1184 addr := info["DebugConfig"]["SerfAdvertiseAddrLAN"].(string) 1185 // strip off 'tcp://' 1186 addr = addr[len("tcp://"):] 1187 err = agent.Join(addr, false) 1188 if err != nil { 1189 t.Fatalf("err: %v", err) 1190 } 1191} 1192 1193func TestAPI_AgentLeave(t *testing.T) { 1194 t.Parallel() 1195 c1, s1 := makeClient(t) 1196 defer s1.Stop() 1197 1198 c2, s2 := makeClientWithConfig(t, nil, func(conf *testutil.TestServerConfig) { 1199 conf.Server = false 1200 conf.Bootstrap = false 1201 }) 1202 defer s2.Stop() 1203 1204 if err := c2.Agent().Join(s1.LANAddr, false); err != nil { 1205 t.Fatalf("err: %v", err) 1206 } 1207 1208 // We sometimes see an EOF response to this one, depending on timing. 1209 err := c2.Agent().Leave() 1210 if err != nil && !strings.Contains(err.Error(), "EOF") { 1211 t.Fatalf("err: %v", err) 1212 } 1213 1214 // Make sure the second agent's status is 'Left' 1215 members, err := c1.Agent().Members(false) 1216 if err != nil { 1217 t.Fatalf("err: %v", err) 1218 } 1219 member := members[0] 1220 if member.Name == s1.Config.NodeName { 1221 member = members[1] 1222 } 1223 if member.Status != int(serf.StatusLeft) { 1224 t.Fatalf("bad: %v", *member) 1225 } 1226} 1227 1228func TestAPI_AgentForceLeave(t *testing.T) { 1229 t.Parallel() 1230 c, s := makeClient(t) 1231 defer s.Stop() 1232 1233 agent := c.Agent() 1234 1235 // Eject somebody 1236 err := agent.ForceLeave(s.Config.NodeName) 1237 if err != nil { 1238 t.Fatalf("err: %v", err) 1239 } 1240} 1241 1242func TestAPI_AgentForceLeavePrune(t *testing.T) { 1243 t.Parallel() 1244 c, s := makeClient(t) 1245 defer s.Stop() 1246 1247 agent := c.Agent() 1248 1249 // Eject somebody 1250 err := agent.ForceLeavePrune(s.Config.NodeName) 1251 if err != nil { 1252 t.Fatalf("err: %v", err) 1253 } 1254} 1255 1256func TestAPI_AgentMonitor(t *testing.T) { 1257 t.Parallel() 1258 c, s := makeClient(t) 1259 defer s.Stop() 1260 1261 agent := c.Agent() 1262 1263 logCh, err := agent.Monitor("debug", nil, nil) 1264 if err != nil { 1265 t.Fatalf("err: %v", err) 1266 } 1267 1268 retry.Run(t, func(r *retry.R) { 1269 { 1270 // Register a service to be sure something happens in secs 1271 serviceReg := &AgentServiceRegistration{ 1272 Name: "redis", 1273 } 1274 if err := agent.ServiceRegister(serviceReg); err != nil { 1275 r.Fatalf("err: %v", err) 1276 } 1277 } 1278 // Wait for the first log message and validate it 1279 select { 1280 case log := <-logCh: 1281 if !(strings.Contains(log, "[INFO]") || strings.Contains(log, "[DEBUG]")) { 1282 r.Fatalf("bad: %q", log) 1283 } 1284 case <-time.After(10 * time.Second): 1285 r.Fatalf("failed to get a log message") 1286 } 1287 }) 1288} 1289 1290func TestAPI_AgentMonitorJSON(t *testing.T) { 1291 t.Parallel() 1292 c, s := makeClient(t) 1293 defer s.Stop() 1294 1295 agent := c.Agent() 1296 1297 logCh, err := agent.MonitorJSON("debug", nil, nil) 1298 if err != nil { 1299 t.Fatalf("err: %v", err) 1300 } 1301 1302 retry.Run(t, func(r *retry.R) { 1303 { 1304 // Register a service to be sure something happens in secs 1305 serviceReg := &AgentServiceRegistration{ 1306 Name: "redis", 1307 } 1308 if err := agent.ServiceRegister(serviceReg); err != nil { 1309 r.Fatalf("err: %v", err) 1310 } 1311 } 1312 // Wait for the first log message and validate it is valid JSON 1313 select { 1314 case log := <-logCh: 1315 var output map[string]interface{} 1316 if err := json.Unmarshal([]byte(log), &output); err != nil { 1317 r.Fatalf("log output was not JSON: %q", log) 1318 } 1319 case <-time.After(10 * time.Second): 1320 r.Fatalf("failed to get a log message") 1321 } 1322 }) 1323} 1324 1325func TestAPI_ServiceMaintenance(t *testing.T) { 1326 t.Parallel() 1327 c, s := makeClient(t) 1328 defer s.Stop() 1329 1330 agent := c.Agent() 1331 1332 // First register a service 1333 serviceReg := &AgentServiceRegistration{ 1334 Name: "redis", 1335 } 1336 if err := agent.ServiceRegister(serviceReg); err != nil { 1337 t.Fatalf("err: %v", err) 1338 } 1339 1340 // Enable maintenance mode 1341 if err := agent.EnableServiceMaintenance("redis", "broken"); err != nil { 1342 t.Fatalf("err: %s", err) 1343 } 1344 1345 // Ensure a critical check was added 1346 checks, err := agent.Checks() 1347 if err != nil { 1348 t.Fatalf("err: %v", err) 1349 } 1350 found := false 1351 for _, check := range checks { 1352 if strings.Contains(check.CheckID, "maintenance") { 1353 found = true 1354 if check.Status != HealthCritical || check.Notes != "broken" { 1355 t.Fatalf("bad: %#v", checks) 1356 } 1357 } 1358 } 1359 if !found { 1360 t.Fatalf("bad: %#v", checks) 1361 } 1362 1363 // Disable maintenance mode 1364 if err := agent.DisableServiceMaintenance("redis"); err != nil { 1365 t.Fatalf("err: %s", err) 1366 } 1367 1368 // Ensure the critical health check was removed 1369 checks, err = agent.Checks() 1370 if err != nil { 1371 t.Fatalf("err: %s", err) 1372 } 1373 for _, check := range checks { 1374 if strings.Contains(check.CheckID, "maintenance") { 1375 t.Fatalf("should have removed health check") 1376 } 1377 if check.Type != "maintenance" { 1378 t.Fatalf("expected type 'maintenance', got %s", check.Type) 1379 } 1380 } 1381} 1382 1383func TestAPI_NodeMaintenance(t *testing.T) { 1384 t.Parallel() 1385 c, s := makeClient(t) 1386 defer s.Stop() 1387 1388 agent := c.Agent() 1389 s.WaitForSerfCheck(t) 1390 1391 // Enable maintenance mode 1392 if err := agent.EnableNodeMaintenance("broken"); err != nil { 1393 t.Fatalf("err: %s", err) 1394 } 1395 1396 // Check that a critical check was added 1397 checks, err := agent.Checks() 1398 if err != nil { 1399 t.Fatalf("err: %s", err) 1400 } 1401 found := false 1402 for _, check := range checks { 1403 if strings.Contains(check.CheckID, "maintenance") { 1404 found = true 1405 if check.Status != HealthCritical || check.Notes != "broken" { 1406 t.Fatalf("bad: %#v", checks) 1407 } 1408 } 1409 } 1410 if !found { 1411 t.Fatalf("bad: %#v", checks) 1412 } 1413 1414 // Disable maintenance mode 1415 if err := agent.DisableNodeMaintenance(); err != nil { 1416 t.Fatalf("err: %s", err) 1417 } 1418 1419 // Ensure the check was removed 1420 checks, err = agent.Checks() 1421 if err != nil { 1422 t.Fatalf("err: %s", err) 1423 } 1424 for _, check := range checks { 1425 if strings.Contains(check.CheckID, "maintenance") { 1426 t.Fatalf("should have removed health check") 1427 } 1428 if check.Type != "maintenance" { 1429 t.Fatalf("expected type 'maintenance', got %s", check.Type) 1430 } 1431 } 1432} 1433 1434func TestAPI_AgentUpdateToken(t *testing.T) { 1435 t.Parallel() 1436 c, s := makeACLClient(t) 1437 defer s.Stop() 1438 1439 t.Run("deprecated", func(t *testing.T) { 1440 agent := c.Agent() 1441 if _, err := agent.UpdateACLToken("root", nil); err != nil { 1442 t.Fatalf("err: %v", err) 1443 } 1444 1445 if _, err := agent.UpdateACLAgentToken("root", nil); err != nil { 1446 t.Fatalf("err: %v", err) 1447 } 1448 1449 if _, err := agent.UpdateACLAgentMasterToken("root", nil); err != nil { 1450 t.Fatalf("err: %v", err) 1451 } 1452 1453 if _, err := agent.UpdateACLReplicationToken("root", nil); err != nil { 1454 t.Fatalf("err: %v", err) 1455 } 1456 }) 1457 1458 t.Run("new with no fallback", func(t *testing.T) { 1459 agent := c.Agent() 1460 if _, err := agent.UpdateDefaultACLToken("root", nil); err != nil { 1461 t.Fatalf("err: %v", err) 1462 } 1463 1464 if _, err := agent.UpdateAgentACLToken("root", nil); err != nil { 1465 t.Fatalf("err: %v", err) 1466 } 1467 1468 if _, err := agent.UpdateAgentMasterACLToken("root", nil); err != nil { 1469 t.Fatalf("err: %v", err) 1470 } 1471 1472 if _, err := agent.UpdateReplicationACLToken("root", nil); err != nil { 1473 t.Fatalf("err: %v", err) 1474 } 1475 }) 1476 1477 t.Run("new with fallback", func(t *testing.T) { 1478 // Respond with 404 for the new paths to trigger fallback. 1479 failer := func(w http.ResponseWriter, req *http.Request) { 1480 w.WriteHeader(404) 1481 } 1482 notfound := httptest.NewServer(http.HandlerFunc(failer)) 1483 defer notfound.Close() 1484 1485 raw := c // real consul client 1486 1487 // Set up a reverse proxy that will send some requests to the 1488 // 404 server and pass everything else through to the real Consul 1489 // server. 1490 director := func(req *http.Request) { 1491 req.URL.Scheme = "http" 1492 1493 switch req.URL.Path { 1494 case "/v1/agent/token/default", 1495 "/v1/agent/token/agent", 1496 "/v1/agent/token/agent_master", 1497 "/v1/agent/token/replication": 1498 req.URL.Host = notfound.URL[7:] // Strip off "http://". 1499 default: 1500 req.URL.Host = raw.config.Address 1501 } 1502 } 1503 proxy := httptest.NewServer(&httputil.ReverseProxy{Director: director}) 1504 defer proxy.Close() 1505 1506 // Make another client that points at the proxy instead of the real 1507 // Consul server. 1508 config := raw.config 1509 config.Address = proxy.URL[7:] // Strip off "http://". 1510 c, err := NewClient(&config) 1511 require.NoError(t, err) 1512 1513 agent := c.Agent() 1514 1515 _, err = agent.UpdateDefaultACLToken("root", nil) 1516 require.NoError(t, err) 1517 1518 _, err = agent.UpdateAgentACLToken("root", nil) 1519 require.NoError(t, err) 1520 1521 _, err = agent.UpdateAgentMasterACLToken("root", nil) 1522 require.NoError(t, err) 1523 1524 _, err = agent.UpdateReplicationACLToken("root", nil) 1525 require.NoError(t, err) 1526 }) 1527 1528 t.Run("new with 403s", func(t *testing.T) { 1529 failer := func(w http.ResponseWriter, req *http.Request) { 1530 w.WriteHeader(403) 1531 } 1532 authdeny := httptest.NewServer(http.HandlerFunc(failer)) 1533 defer authdeny.Close() 1534 1535 raw := c // real consul client 1536 1537 // Make another client that points at the proxy instead of the real 1538 // Consul server. 1539 config := raw.config 1540 config.Address = authdeny.URL[7:] // Strip off "http://". 1541 c, err := NewClient(&config) 1542 require.NoError(t, err) 1543 1544 agent := c.Agent() 1545 1546 _, err = agent.UpdateDefaultACLToken("root", nil) 1547 require.Error(t, err) 1548 1549 _, err = agent.UpdateAgentACLToken("root", nil) 1550 require.Error(t, err) 1551 1552 _, err = agent.UpdateAgentMasterACLToken("root", nil) 1553 require.Error(t, err) 1554 1555 _, err = agent.UpdateReplicationACLToken("root", nil) 1556 require.Error(t, err) 1557 }) 1558} 1559 1560func TestAPI_AgentConnectCARoots_empty(t *testing.T) { 1561 t.Parallel() 1562 1563 require := require.New(t) 1564 c, s := makeClientWithConfig(t, nil, func(c *testutil.TestServerConfig) { 1565 c.Connect = nil // disable connect to prevent CA being bootstrapped 1566 }) 1567 defer s.Stop() 1568 1569 agent := c.Agent() 1570 _, _, err := agent.ConnectCARoots(nil) 1571 require.Error(err) 1572 require.Contains(err.Error(), "Connect must be enabled") 1573} 1574 1575func TestAPI_AgentConnectCARoots_list(t *testing.T) { 1576 t.Parallel() 1577 1578 require := require.New(t) 1579 c, s := makeClient(t) 1580 defer s.Stop() 1581 1582 agent := c.Agent() 1583 s.WaitForSerfCheck(t) 1584 list, meta, err := agent.ConnectCARoots(nil) 1585 require.NoError(err) 1586 require.True(meta.LastIndex > 0) 1587 require.Len(list.Roots, 1) 1588} 1589 1590func TestAPI_AgentConnectCALeaf(t *testing.T) { 1591 t.Parallel() 1592 1593 require := require.New(t) 1594 c, s := makeClient(t) 1595 defer s.Stop() 1596 1597 // ensure we don't try to sign a leaf cert before connect has been initialized 1598 s.WaitForActiveCARoot(t) 1599 1600 agent := c.Agent() 1601 // Setup service 1602 reg := &AgentServiceRegistration{ 1603 Name: "foo", 1604 Tags: []string{"bar", "baz"}, 1605 Port: 8000, 1606 } 1607 require.NoError(agent.ServiceRegister(reg)) 1608 1609 leaf, meta, err := agent.ConnectCALeaf("foo", nil) 1610 require.NoError(err) 1611 require.True(meta.LastIndex > 0) 1612 // Sanity checks here as we have actual certificate validation checks at many 1613 // other levels. 1614 require.NotEmpty(leaf.SerialNumber) 1615 require.NotEmpty(leaf.CertPEM) 1616 require.NotEmpty(leaf.PrivateKeyPEM) 1617 require.Equal("foo", leaf.Service) 1618 require.True(strings.HasSuffix(leaf.ServiceURI, "/svc/foo")) 1619 require.True(leaf.ModifyIndex > 0) 1620 require.True(leaf.ValidAfter.Before(time.Now())) 1621 require.True(leaf.ValidBefore.After(time.Now())) 1622} 1623 1624func TestAPI_AgentConnectAuthorize(t *testing.T) { 1625 t.Parallel() 1626 require := require.New(t) 1627 c, s := makeClient(t) 1628 defer s.Stop() 1629 1630 agent := c.Agent() 1631 s.WaitForSerfCheck(t) 1632 params := &AgentAuthorizeParams{ 1633 Target: "foo", 1634 ClientCertSerial: "fake", 1635 // Importing connect.TestSpiffeIDService creates an import cycle 1636 ClientCertURI: "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/ny1/svc/web", 1637 } 1638 auth, err := agent.ConnectAuthorize(params) 1639 require.Nil(err) 1640 require.True(auth.Authorized) 1641 require.Equal(auth.Reason, "ACLs disabled, access is allowed by default") 1642} 1643 1644func TestAPI_AgentHealthService(t *testing.T) { 1645 t.Parallel() 1646 c, s := makeClient(t) 1647 defer s.Stop() 1648 1649 agent := c.Agent() 1650 1651 requireServiceHealthID := func(t *testing.T, serviceID, expected string, shouldExist bool) { 1652 msg := fmt.Sprintf("service id:%s, shouldExist:%v, expectedStatus:%s : bad %%s", serviceID, shouldExist, expected) 1653 1654 state, out, err := agent.AgentHealthServiceByID(serviceID) 1655 require.Nil(t, err, msg, "err") 1656 require.Equal(t, expected, state, msg, "state") 1657 if !shouldExist { 1658 require.Nil(t, out, msg, "shouldExist") 1659 } else { 1660 require.NotNil(t, out, msg, "output") 1661 require.Equal(t, serviceID, out.Service.ID, msg, "output") 1662 } 1663 } 1664 requireServiceHealthName := func(t *testing.T, serviceName, expected string, shouldExist bool) { 1665 msg := fmt.Sprintf("service name:%s, shouldExist:%v, expectedStatus:%s : bad %%s", serviceName, shouldExist, expected) 1666 1667 state, outs, err := agent.AgentHealthServiceByName(serviceName) 1668 require.Nil(t, err, msg, "err") 1669 require.Equal(t, expected, state, msg, "state") 1670 if !shouldExist { 1671 require.Equal(t, 0, len(outs), msg, "output") 1672 } else { 1673 require.True(t, len(outs) > 0, msg, "output") 1674 for _, o := range outs { 1675 require.Equal(t, serviceName, o.Service.Service, msg, "output") 1676 } 1677 } 1678 } 1679 1680 requireServiceHealthID(t, "_i_do_not_exist_", HealthCritical, false) 1681 requireServiceHealthName(t, "_i_do_not_exist_", HealthCritical, false) 1682 1683 testServiceID1 := "foo" 1684 testServiceID2 := "foofoo" 1685 testServiceName := "bar" 1686 1687 // register service 1688 reg := &AgentServiceRegistration{ 1689 Name: testServiceName, 1690 ID: testServiceID1, 1691 Port: 8000, 1692 Check: &AgentServiceCheck{ 1693 TTL: "15s", 1694 }, 1695 } 1696 err := agent.ServiceRegister(reg) 1697 require.Nil(t, err) 1698 requireServiceHealthID(t, testServiceID1, HealthCritical, true) 1699 requireServiceHealthName(t, testServiceName, HealthCritical, true) 1700 1701 err = agent.WarnTTL(fmt.Sprintf("service:%s", testServiceID1), "I am warn") 1702 require.Nil(t, err) 1703 requireServiceHealthName(t, testServiceName, HealthWarning, true) 1704 requireServiceHealthID(t, testServiceID1, HealthWarning, true) 1705 1706 err = agent.PassTTL(fmt.Sprintf("service:%s", testServiceID1), "I am good :)") 1707 require.Nil(t, err) 1708 requireServiceHealthName(t, testServiceName, HealthPassing, true) 1709 requireServiceHealthID(t, testServiceID1, HealthPassing, true) 1710 1711 err = agent.FailTTL(fmt.Sprintf("service:%s", testServiceID1), "I am dead.") 1712 require.Nil(t, err) 1713 requireServiceHealthName(t, testServiceName, HealthCritical, true) 1714 requireServiceHealthID(t, testServiceID1, HealthCritical, true) 1715 1716 // register another service 1717 reg = &AgentServiceRegistration{ 1718 Name: testServiceName, 1719 ID: testServiceID2, 1720 Port: 8000, 1721 Check: &AgentServiceCheck{ 1722 TTL: "15s", 1723 }, 1724 } 1725 err = agent.ServiceRegister(reg) 1726 require.Nil(t, err) 1727 requireServiceHealthName(t, testServiceName, HealthCritical, true) 1728 1729 err = agent.PassTTL(fmt.Sprintf("service:%s", testServiceID1), "I am good :)") 1730 require.Nil(t, err) 1731 requireServiceHealthName(t, testServiceName, HealthCritical, true) 1732 1733 err = agent.WarnTTL(fmt.Sprintf("service:%s", testServiceID2), "I am warn") 1734 require.Nil(t, err) 1735 requireServiceHealthName(t, testServiceName, HealthWarning, true) 1736 1737 err = agent.PassTTL(fmt.Sprintf("service:%s", testServiceID2), "I am good :)") 1738 require.Nil(t, err) 1739 requireServiceHealthName(t, testServiceName, HealthPassing, true) 1740} 1741 1742func TestAgentService_JSON_OmitTaggedAdddresses(t *testing.T) { 1743 t.Parallel() 1744 cases := []struct { 1745 name string 1746 as AgentService 1747 }{ 1748 { 1749 "nil", 1750 AgentService{ 1751 TaggedAddresses: nil, 1752 }, 1753 }, 1754 { 1755 "empty", 1756 AgentService{ 1757 TaggedAddresses: make(map[string]ServiceAddress), 1758 }, 1759 }, 1760 } 1761 1762 for _, tc := range cases { 1763 name := tc.name 1764 as := tc.as 1765 t.Run(name, func(t *testing.T) { 1766 t.Parallel() 1767 data, err := json.Marshal(as) 1768 require.NoError(t, err) 1769 var raw map[string]interface{} 1770 err = json.Unmarshal(data, &raw) 1771 require.NoError(t, err) 1772 require.NotContains(t, raw, "TaggedAddresses") 1773 require.NotContains(t, raw, "tagged_addresses") 1774 }) 1775 } 1776} 1777 1778func TestAgentService_Register_MeshGateway(t *testing.T) { 1779 t.Parallel() 1780 c, s := makeClient(t) 1781 defer s.Stop() 1782 1783 agent := c.Agent() 1784 1785 reg := AgentServiceRegistration{ 1786 Kind: ServiceKindMeshGateway, 1787 Name: "mesh-gateway", 1788 Address: "10.1.2.3", 1789 Port: 8443, 1790 Proxy: &AgentServiceConnectProxyConfig{ 1791 Config: map[string]interface{}{ 1792 "foo": "bar", 1793 }, 1794 }, 1795 } 1796 1797 err := agent.ServiceRegister(®) 1798 require.NoError(t, err) 1799 1800 svc, _, err := agent.Service("mesh-gateway", nil) 1801 require.NoError(t, err) 1802 require.NotNil(t, svc) 1803 require.Equal(t, ServiceKindMeshGateway, svc.Kind) 1804 require.NotNil(t, svc.Proxy) 1805 require.Contains(t, svc.Proxy.Config, "foo") 1806 require.Equal(t, "bar", svc.Proxy.Config["foo"]) 1807} 1808 1809func TestAgentService_Register_TerminatingGateway(t *testing.T) { 1810 t.Parallel() 1811 c, s := makeClient(t) 1812 defer s.Stop() 1813 1814 agent := c.Agent() 1815 1816 reg := AgentServiceRegistration{ 1817 Kind: ServiceKindTerminatingGateway, 1818 Name: "terminating-gateway", 1819 Address: "10.1.2.3", 1820 Port: 8443, 1821 Proxy: &AgentServiceConnectProxyConfig{ 1822 Config: map[string]interface{}{ 1823 "foo": "bar", 1824 }, 1825 }, 1826 } 1827 1828 err := agent.ServiceRegister(®) 1829 require.NoError(t, err) 1830 1831 svc, _, err := agent.Service("terminating-gateway", nil) 1832 require.NoError(t, err) 1833 require.NotNil(t, svc) 1834 require.Equal(t, ServiceKindTerminatingGateway, svc.Kind) 1835 require.NotNil(t, svc.Proxy) 1836 require.Contains(t, svc.Proxy.Config, "foo") 1837 require.Equal(t, "bar", svc.Proxy.Config["foo"]) 1838} 1839 1840func TestAgentService_ExposeChecks(t *testing.T) { 1841 t.Parallel() 1842 c, s := makeClient(t) 1843 defer s.Stop() 1844 1845 agent := c.Agent() 1846 1847 path := ExposePath{ 1848 LocalPathPort: 8080, 1849 ListenerPort: 21500, 1850 Path: "/metrics", 1851 Protocol: "http2", 1852 } 1853 reg := AgentServiceRegistration{ 1854 Kind: ServiceKindConnectProxy, 1855 Name: "expose-proxy", 1856 Address: "10.1.2.3", 1857 Port: 8443, 1858 Proxy: &AgentServiceConnectProxyConfig{ 1859 DestinationServiceName: "expose", 1860 Expose: ExposeConfig{ 1861 Checks: true, 1862 Paths: []ExposePath{ 1863 path, 1864 }, 1865 }, 1866 }, 1867 } 1868 1869 err := agent.ServiceRegister(®) 1870 require.NoError(t, err) 1871 1872 svc, _, err := agent.Service("expose-proxy", nil) 1873 require.NoError(t, err) 1874 require.NotNil(t, svc) 1875 require.Equal(t, ServiceKindConnectProxy, svc.Kind) 1876 require.NotNil(t, svc.Proxy) 1877 require.Len(t, svc.Proxy.Expose.Paths, 1) 1878 require.True(t, svc.Proxy.Expose.Checks) 1879 require.Equal(t, path, svc.Proxy.Expose.Paths[0]) 1880} 1881 1882func TestMemberACLMode(t *testing.T) { 1883 type testCase struct { 1884 tagValue string 1885 expectedMode MemberACLMode 1886 } 1887 1888 cases := map[string]testCase{ 1889 "disabled": { 1890 tagValue: "0", 1891 expectedMode: ACLModeDisabled, 1892 }, 1893 "enabled": { 1894 tagValue: "1", 1895 expectedMode: ACLModeEnabled, 1896 }, 1897 "legacy": { 1898 tagValue: "2", 1899 expectedMode: ACLModeLegacy, 1900 }, 1901 "unknown-3": { 1902 tagValue: "3", 1903 expectedMode: ACLModeUnknown, 1904 }, 1905 "unknown-other": { 1906 tagValue: "77", 1907 expectedMode: ACLModeUnknown, 1908 }, 1909 "unknown-not-present": { 1910 tagValue: "", 1911 expectedMode: ACLModeUnknown, 1912 }, 1913 } 1914 1915 for name, tcase := range cases { 1916 t.Run(name, func(t *testing.T) { 1917 tags := map[string]string{} 1918 1919 if tcase.tagValue != "" { 1920 tags[MemberTagKeyACLMode] = tcase.tagValue 1921 } 1922 1923 m := AgentMember{ 1924 Tags: tags, 1925 } 1926 1927 require.Equal(t, tcase.expectedMode, m.ACLMode()) 1928 }) 1929 } 1930} 1931 1932func TestMemberIsConsulServer(t *testing.T) { 1933 type testCase struct { 1934 tagValue string 1935 isServer bool 1936 } 1937 1938 cases := map[string]testCase{ 1939 "not-present": { 1940 tagValue: "", 1941 isServer: false, 1942 }, 1943 "server": { 1944 tagValue: MemberTagValueRoleServer, 1945 isServer: true, 1946 }, 1947 "client": { 1948 tagValue: "client", 1949 isServer: false, 1950 }, 1951 } 1952 1953 for name, tcase := range cases { 1954 t.Run(name, func(t *testing.T) { 1955 tags := map[string]string{} 1956 1957 if tcase.tagValue != "" { 1958 tags[MemberTagKeyRole] = tcase.tagValue 1959 } 1960 1961 m := AgentMember{ 1962 Tags: tags, 1963 } 1964 1965 require.Equal(t, tcase.isServer, m.IsConsulServer()) 1966 }) 1967 } 1968} 1969