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