1package api
2
3import (
4	"reflect"
5	"testing"
6	"time"
7
8	"github.com/hashicorp/consul/testutil"
9	"github.com/hashicorp/consul/testutil/retry"
10	"github.com/pascaldekloe/goe/verify"
11	"github.com/stretchr/testify/require"
12)
13
14func TestAPI_CatalogDatacenters(t *testing.T) {
15	t.Parallel()
16	c, s := makeClient(t)
17	defer s.Stop()
18
19	catalog := c.Catalog()
20	retry.Run(t, func(r *retry.R) {
21		datacenters, err := catalog.Datacenters()
22		if err != nil {
23			r.Fatal(err)
24		}
25		if len(datacenters) < 1 {
26			r.Fatal("got 0 datacenters want at least one")
27		}
28	})
29}
30
31func TestAPI_CatalogNodes(t *testing.T) {
32	t.Parallel()
33	c, s := makeClient(t)
34	defer s.Stop()
35
36	catalog := c.Catalog()
37	retry.RunWith(retry.ThreeTimes(), t, func(r *retry.R) {
38		nodes, meta, err := catalog.Nodes(nil)
39		// We're not concerned about the createIndex of an agent
40		// Hence we're setting it to the default value
41		nodes[0].CreateIndex = 0
42		if err != nil {
43			r.Fatal(err)
44		}
45		if meta.LastIndex < 2 {
46			r.Fatal("Last index must be greater than 1")
47		}
48		want := []*Node{
49			{
50				ID:         s.Config.NodeID,
51				Node:       s.Config.NodeName,
52				Address:    "127.0.0.1",
53				Datacenter: "dc1",
54				TaggedAddresses: map[string]string{
55					"lan": "127.0.0.1",
56					"wan": "127.0.0.1",
57				},
58				Meta: map[string]string{
59					"consul-network-segment": "",
60				},
61				// CreateIndex will never always be meta.LastIndex - 1
62				// The purpose of this test is not to test CreateIndex value of an agent
63				// rather to check if the client agent can get the correct number
64				// of agents with a particular service, KV pair, etc...
65				// Hence reverting this to the default value here.
66				CreateIndex: 0,
67				ModifyIndex: meta.LastIndex,
68			},
69		}
70		if !verify.Values(r, "", nodes, want) {
71			r.FailNow()
72		}
73	})
74}
75
76func TestAPI_CatalogNodes_MetaFilter(t *testing.T) {
77	t.Parallel()
78	meta := map[string]string{"somekey": "somevalue"}
79	c, s := makeClientWithConfig(t, nil, func(conf *testutil.TestServerConfig) {
80		conf.NodeMeta = meta
81	})
82	defer s.Stop()
83
84	catalog := c.Catalog()
85	// Make sure we get the node back when filtering by its metadata
86	retry.Run(t, func(r *retry.R) {
87		nodes, meta, err := catalog.Nodes(&QueryOptions{NodeMeta: meta})
88		if err != nil {
89			r.Fatal(err)
90		}
91
92		if meta.LastIndex == 0 {
93			r.Fatalf("Bad: %v", meta)
94		}
95
96		if len(nodes) == 0 {
97			r.Fatalf("Bad: %v", nodes)
98		}
99
100		if _, ok := nodes[0].TaggedAddresses["wan"]; !ok {
101			r.Fatalf("Bad: %v", nodes[0])
102		}
103
104		if v, ok := nodes[0].Meta["somekey"]; !ok || v != "somevalue" {
105			r.Fatalf("Bad: %v", nodes[0].Meta)
106		}
107
108		if nodes[0].Datacenter != "dc1" {
109			r.Fatalf("Bad datacenter: %v", nodes[0])
110		}
111	})
112
113	retry.Run(t, func(r *retry.R) {
114		// Get nothing back when we use an invalid filter
115		nodes, meta, err := catalog.Nodes(&QueryOptions{NodeMeta: map[string]string{"nope": "nope"}})
116		if err != nil {
117			r.Fatal(err)
118		}
119
120		if meta.LastIndex == 0 {
121			r.Fatalf("Bad: %v", meta)
122		}
123
124		if len(nodes) != 0 {
125			r.Fatalf("Bad: %v", nodes)
126		}
127	})
128}
129
130func TestAPI_CatalogServices(t *testing.T) {
131	t.Parallel()
132	c, s := makeClient(t)
133	defer s.Stop()
134
135	catalog := c.Catalog()
136	retry.Run(t, func(r *retry.R) {
137		services, meta, err := catalog.Services(nil)
138		if err != nil {
139			r.Fatal(err)
140		}
141
142		if meta.LastIndex == 0 {
143			r.Fatalf("Bad: %v", meta)
144		}
145
146		if len(services) == 0 {
147			r.Fatalf("Bad: %v", services)
148		}
149	})
150}
151
152func TestAPI_CatalogServices_NodeMetaFilter(t *testing.T) {
153	t.Parallel()
154	meta := map[string]string{"somekey": "somevalue"}
155	c, s := makeClientWithConfig(t, nil, func(conf *testutil.TestServerConfig) {
156		conf.NodeMeta = meta
157	})
158	defer s.Stop()
159
160	catalog := c.Catalog()
161	// Make sure we get the service back when filtering by the node's metadata
162	retry.Run(t, func(r *retry.R) {
163		services, meta, err := catalog.Services(&QueryOptions{NodeMeta: meta})
164		if err != nil {
165			r.Fatal(err)
166		}
167
168		if meta.LastIndex == 0 {
169			r.Fatalf("Bad: %v", meta)
170		}
171
172		if len(services) == 0 {
173			r.Fatalf("Bad: %v", services)
174		}
175	})
176
177	retry.Run(t, func(r *retry.R) {
178		// Get nothing back when using an invalid filter
179		services, meta, err := catalog.Services(&QueryOptions{NodeMeta: map[string]string{"nope": "nope"}})
180		if err != nil {
181			r.Fatal(err)
182		}
183
184		if meta.LastIndex == 0 {
185			r.Fatalf("Bad: %v", meta)
186		}
187
188		if len(services) != 0 {
189			r.Fatalf("Bad: %v", services)
190		}
191	})
192}
193
194func TestAPI_CatalogService(t *testing.T) {
195	t.Parallel()
196	c, s := makeClient(t)
197	defer s.Stop()
198
199	catalog := c.Catalog()
200
201	retry.Run(t, func(r *retry.R) {
202		services, meta, err := catalog.Service("consul", "", nil)
203		if err != nil {
204			r.Fatal(err)
205		}
206
207		if meta.LastIndex == 0 {
208			r.Fatalf("Bad: %v", meta)
209		}
210
211		if len(services) == 0 {
212			r.Fatalf("Bad: %v", services)
213		}
214
215		if services[0].Datacenter != "dc1" {
216			r.Fatalf("Bad datacenter: %v", services[0])
217		}
218	})
219}
220
221func TestAPI_CatalogServiceUnmanagedProxy(t *testing.T) {
222	t.Parallel()
223	c, s := makeClient(t)
224	defer s.Stop()
225
226	catalog := c.Catalog()
227
228	proxyReg := testUnmanagedProxyRegistration(t)
229
230	retry.Run(t, func(r *retry.R) {
231		_, err := catalog.Register(proxyReg, nil)
232		r.Check(err)
233
234		services, meta, err := catalog.Service("web-proxy", "", nil)
235		if err != nil {
236			r.Fatal(err)
237		}
238
239		if meta.LastIndex == 0 {
240			r.Fatalf("Bad: %v", meta)
241		}
242
243		if len(services) == 0 {
244			r.Fatalf("Bad: %v", services)
245		}
246
247		if services[0].Datacenter != "dc1" {
248			r.Fatalf("Bad datacenter: %v", services[0])
249		}
250
251		if !reflect.DeepEqual(services[0].ServiceProxy, proxyReg.Service.Proxy) {
252			r.Fatalf("bad proxy.\nwant: %v\n got: %v", proxyReg.Service.Proxy,
253				services[0].ServiceProxy)
254		}
255	})
256}
257
258func TestAPI_CatalogServiceCached(t *testing.T) {
259	t.Parallel()
260	c, s := makeClient(t)
261	defer s.Stop()
262
263	catalog := c.Catalog()
264
265	q := &QueryOptions{
266		UseCache: true,
267	}
268
269	retry.Run(t, func(r *retry.R) {
270		services, meta, err := catalog.Service("consul", "", q)
271		if err != nil {
272			r.Fatal(err)
273		}
274
275		if meta.LastIndex == 0 {
276			r.Fatalf("Bad: %v", meta)
277		}
278
279		if len(services) == 0 {
280			r.Fatalf("Bad: %v", services)
281		}
282
283		if services[0].Datacenter != "dc1" {
284			r.Fatalf("Bad datacenter: %v", services[0])
285		}
286	})
287
288	require := require.New(t)
289
290	// Got success, next hit must be cache hit
291	_, meta, err := catalog.Service("consul", "", q)
292	require.NoError(err)
293	require.True(meta.CacheHit)
294	require.Equal(time.Duration(0), meta.CacheAge)
295}
296
297func TestAPI_CatalogService_SingleTag(t *testing.T) {
298	t.Parallel()
299	c, s := makeClientWithConfig(t, nil, func(conf *testutil.TestServerConfig) {
300		conf.NodeName = "node123"
301	})
302	defer s.Stop()
303
304	agent := c.Agent()
305	catalog := c.Catalog()
306
307	reg := &AgentServiceRegistration{
308		Name: "foo",
309		ID:   "foo1",
310		Tags: []string{"bar"},
311	}
312	require.NoError(t, agent.ServiceRegister(reg))
313	defer agent.ServiceDeregister("foo1")
314
315	retry.Run(t, func(r *retry.R) {
316		services, meta, err := catalog.Service("foo", "bar", nil)
317		require.NoError(t, err)
318		require.NotEqual(t, meta.LastIndex, 0)
319		require.Len(t, services, 1)
320		require.Equal(t, services[0].ServiceID, "foo1")
321	})
322}
323
324func TestAPI_CatalogService_MultipleTags(t *testing.T) {
325	t.Parallel()
326	c, s := makeClientWithConfig(t, nil, func(conf *testutil.TestServerConfig) {
327		conf.NodeName = "node123"
328	})
329	defer s.Stop()
330
331	agent := c.Agent()
332	catalog := c.Catalog()
333
334	// Make two services with a check
335	reg := &AgentServiceRegistration{
336		Name: "foo",
337		ID:   "foo1",
338		Tags: []string{"bar"},
339	}
340	require.NoError(t, agent.ServiceRegister(reg))
341	defer agent.ServiceDeregister("foo1")
342
343	reg2 := &AgentServiceRegistration{
344		Name: "foo",
345		ID:   "foo2",
346		Tags: []string{"bar", "v2"},
347	}
348	require.NoError(t, agent.ServiceRegister(reg2))
349	defer agent.ServiceDeregister("foo2")
350
351	// Test searching with one tag (two results)
352	retry.Run(t, func(r *retry.R) {
353		services, meta, err := catalog.ServiceMultipleTags("foo", []string{"bar"}, nil)
354
355		require.NoError(t, err)
356		require.NotEqual(t, meta.LastIndex, 0)
357
358		// Should be 2 services with the `bar` tag
359		require.Len(t, services, 2)
360	})
361
362	// Test searching with two tags (one result)
363	retry.Run(t, func(r *retry.R) {
364		services, meta, err := catalog.ServiceMultipleTags("foo", []string{"bar", "v2"}, nil)
365
366		require.NoError(t, err)
367		require.NotEqual(t, meta.LastIndex, 0)
368
369		// Should be exactly 1 service, named "foo2"
370		require.Len(t, services, 1)
371		require.Equal(t, services[0].ServiceID, "foo2")
372	})
373}
374
375func TestAPI_CatalogService_NodeMetaFilter(t *testing.T) {
376	t.Parallel()
377	meta := map[string]string{"somekey": "somevalue"}
378	c, s := makeClientWithConfig(t, nil, func(conf *testutil.TestServerConfig) {
379		conf.NodeMeta = meta
380	})
381	defer s.Stop()
382
383	catalog := c.Catalog()
384	retry.Run(t, func(r *retry.R) {
385		services, meta, err := catalog.Service("consul", "", &QueryOptions{NodeMeta: meta})
386		if err != nil {
387			r.Fatal(err)
388		}
389
390		if meta.LastIndex == 0 {
391			r.Fatalf("Bad: %v", meta)
392		}
393
394		if len(services) == 0 {
395			r.Fatalf("Bad: %v", services)
396		}
397
398		if services[0].Datacenter != "dc1" {
399			r.Fatalf("Bad datacenter: %v", services[0])
400		}
401	})
402}
403
404func testUpstreams(t *testing.T) []Upstream {
405	return []Upstream{
406		{
407			DestinationName: "db",
408			LocalBindPort:   9191,
409			Config: map[string]interface{}{
410				"connect_timeout_ms": float64(1000),
411			},
412		},
413		{
414			DestinationType: UpstreamDestTypePreparedQuery,
415			DestinationName: "geo-cache",
416			LocalBindPort:   8181,
417		},
418	}
419}
420
421func testExpectUpstreamsWithDefaults(t *testing.T, upstreams []Upstream) []Upstream {
422	ups := make([]Upstream, len(upstreams))
423	for i := range upstreams {
424		ups[i] = upstreams[i]
425		// Fill in default fields we expect to have back explicitly in a response
426		if ups[i].DestinationType == "" {
427			ups[i].DestinationType = UpstreamDestTypeService
428		}
429	}
430	return ups
431}
432
433// testUnmanagedProxy returns a fully configured external proxy service suitable
434// for checking that all the config fields make it back in a response intact.
435func testUnmanagedProxy(t *testing.T) *AgentService {
436	return &AgentService{
437		Kind: ServiceKindConnectProxy,
438		Proxy: &AgentServiceConnectProxyConfig{
439			DestinationServiceName: "web",
440			DestinationServiceID:   "web1",
441			LocalServiceAddress:    "127.0.0.2",
442			LocalServicePort:       8080,
443			Upstreams:              testUpstreams(t),
444		},
445		ID:      "web-proxy1",
446		Service: "web-proxy",
447		Port:    8001,
448	}
449}
450
451// testUnmanagedProxyRegistration returns a *CatalogRegistration for a fully
452// configured external proxy.
453func testUnmanagedProxyRegistration(t *testing.T) *CatalogRegistration {
454	return &CatalogRegistration{
455		Datacenter: "dc1",
456		Node:       "foobar",
457		Address:    "192.168.10.10",
458		Service:    testUnmanagedProxy(t),
459	}
460}
461
462func TestAPI_CatalogConnect(t *testing.T) {
463	t.Parallel()
464	c, s := makeClient(t)
465	defer s.Stop()
466
467	catalog := c.Catalog()
468
469	// Register service and proxy instances to test against.
470	proxyReg := testUnmanagedProxyRegistration(t)
471
472	proxy := proxyReg.Service
473
474	// DEPRECATED (ProxyDestination) - remove this case when the field is removed
475	deprecatedProxyReg := testUnmanagedProxyRegistration(t)
476	deprecatedProxyReg.Service.ProxyDestination = deprecatedProxyReg.Service.Proxy.DestinationServiceName
477	deprecatedProxyReg.Service.Proxy = nil
478
479	service := &AgentService{
480		ID:      proxyReg.Service.Proxy.DestinationServiceID,
481		Service: proxyReg.Service.Proxy.DestinationServiceName,
482		Port:    8000,
483	}
484	check := &AgentCheck{
485		Node:      "foobar",
486		CheckID:   "service:" + service.ID,
487		Name:      "Redis health check",
488		Notes:     "Script based health check",
489		Status:    HealthPassing,
490		ServiceID: service.ID,
491	}
492
493	reg := &CatalogRegistration{
494		Datacenter: "dc1",
495		Node:       "foobar",
496		Address:    "192.168.10.10",
497		Service:    service,
498		Check:      check,
499	}
500
501	retry.Run(t, func(r *retry.R) {
502		if _, err := catalog.Register(reg, nil); err != nil {
503			r.Fatal(err)
504		}
505		// First try to register deprecated proxy, shouldn't error
506		if _, err := catalog.Register(deprecatedProxyReg, nil); err != nil {
507			r.Fatal(err)
508		}
509		if _, err := catalog.Register(proxyReg, nil); err != nil {
510			r.Fatal(err)
511		}
512
513		services, meta, err := catalog.Connect(proxyReg.Service.Proxy.DestinationServiceName, "", nil)
514		if err != nil {
515			r.Fatal(err)
516		}
517
518		if meta.LastIndex == 0 {
519			r.Fatalf("Bad: %v", meta)
520		}
521
522		if len(services) == 0 {
523			r.Fatalf("Bad: %v", services)
524		}
525
526		if services[0].Datacenter != "dc1" {
527			r.Fatalf("Bad datacenter: %v", services[0])
528		}
529
530		if services[0].ServicePort != proxy.Port {
531			r.Fatalf("Returned port should be for proxy: %v", services[0])
532		}
533
534		if !reflect.DeepEqual(services[0].ServiceProxy, proxy.Proxy) {
535			r.Fatalf("Returned proxy config should match:\nWant: %v\n Got: %v",
536				proxy.Proxy, services[0].ServiceProxy)
537		}
538	})
539}
540
541func TestAPI_CatalogConnectNative(t *testing.T) {
542	t.Parallel()
543	c, s := makeClient(t)
544	defer s.Stop()
545
546	catalog := c.Catalog()
547
548	// Register service and proxy instances to test against.
549	service := &AgentService{
550		ID:      "redis1",
551		Service: "redis",
552		Port:    8000,
553		Connect: &AgentServiceConnect{Native: true},
554	}
555	check := &AgentCheck{
556		Node:      "foobar",
557		CheckID:   "service:redis1",
558		Name:      "Redis health check",
559		Notes:     "Script based health check",
560		Status:    HealthPassing,
561		ServiceID: "redis1",
562	}
563
564	reg := &CatalogRegistration{
565		Datacenter: "dc1",
566		Node:       "foobar",
567		Address:    "192.168.10.10",
568		Service:    service,
569		Check:      check,
570	}
571
572	retry.Run(t, func(r *retry.R) {
573		if _, err := catalog.Register(reg, nil); err != nil {
574			r.Fatal(err)
575		}
576
577		services, meta, err := catalog.Connect("redis", "", nil)
578		if err != nil {
579			r.Fatal(err)
580		}
581
582		if meta.LastIndex == 0 {
583			r.Fatalf("Bad: %v", meta)
584		}
585
586		if len(services) == 0 {
587			r.Fatalf("Bad: %v", services)
588		}
589
590		if services[0].Datacenter != "dc1" {
591			r.Fatalf("Bad datacenter: %v", services[0])
592		}
593
594		if services[0].ServicePort != service.Port {
595			r.Fatalf("Returned port should be for proxy: %v", services[0])
596		}
597	})
598}
599
600func TestAPI_CatalogNode(t *testing.T) {
601	t.Parallel()
602	c, s := makeClient(t)
603	defer s.Stop()
604
605	catalog := c.Catalog()
606
607	name, err := c.Agent().NodeName()
608	require.NoError(t, err)
609
610	proxyReg := testUnmanagedProxyRegistration(t)
611	proxyReg.Node = name
612	proxyReg.SkipNodeUpdate = true
613
614	retry.Run(t, func(r *retry.R) {
615		// Register a connect proxy to ensure all it's config fields are returned
616		_, err := catalog.Register(proxyReg, nil)
617		r.Check(err)
618
619		info, meta, err := catalog.Node(name, nil)
620		if err != nil {
621			r.Fatal(err)
622		}
623
624		if meta.LastIndex == 0 {
625			r.Fatalf("Bad: %v", meta)
626		}
627
628		if len(info.Services) != 2 {
629			r.Fatalf("Bad: %v (len %d)", info, len(info.Services))
630		}
631
632		if _, ok := info.Node.TaggedAddresses["wan"]; !ok {
633			r.Fatalf("Bad: %v", info.Node.TaggedAddresses)
634		}
635
636		if info.Node.Datacenter != "dc1" {
637			r.Fatalf("Bad datacenter: %v", info)
638		}
639
640		if _, ok := info.Services["web-proxy1"]; !ok {
641			r.Fatalf("Missing proxy service: %v", info.Services)
642		}
643
644		if !reflect.DeepEqual(proxyReg.Service.Proxy, info.Services["web-proxy1"].Proxy) {
645			r.Fatalf("Bad proxy config:\nwant %v\n got: %v", proxyReg.Service.Proxy,
646				info.Services["web-proxy"].Proxy)
647		}
648	})
649}
650
651func TestAPI_CatalogRegistration(t *testing.T) {
652	t.Parallel()
653	c, s := makeClient(t)
654	defer s.Stop()
655
656	catalog := c.Catalog()
657
658	service := &AgentService{
659		ID:      "redis1",
660		Service: "redis",
661		Tags:    []string{"master", "v1"},
662		Port:    8000,
663	}
664
665	check := &AgentCheck{
666		Node:      "foobar",
667		CheckID:   "service:redis1",
668		Name:      "Redis health check",
669		Notes:     "Script based health check",
670		Status:    HealthPassing,
671		ServiceID: "redis1",
672	}
673
674	reg := &CatalogRegistration{
675		Datacenter: "dc1",
676		Node:       "foobar",
677		Address:    "192.168.10.10",
678		NodeMeta:   map[string]string{"somekey": "somevalue"},
679		Service:    service,
680		Check:      check,
681	}
682	// Register a connect proxy for that service too
683	proxy := &AgentService{
684		ID:      "redis-proxy1",
685		Service: "redis-proxy",
686		Port:    8001,
687		Kind:    ServiceKindConnectProxy,
688		Proxy: &AgentServiceConnectProxyConfig{
689			DestinationServiceName: service.Service,
690		},
691	}
692	proxyReg := &CatalogRegistration{
693		Datacenter: "dc1",
694		Node:       "foobar",
695		Address:    "192.168.10.10",
696		NodeMeta:   map[string]string{"somekey": "somevalue"},
697		Service:    proxy,
698	}
699	retry.Run(t, func(r *retry.R) {
700		if _, err := catalog.Register(reg, nil); err != nil {
701			r.Fatal(err)
702		}
703		if _, err := catalog.Register(proxyReg, nil); err != nil {
704			r.Fatal(err)
705		}
706
707		node, _, err := catalog.Node("foobar", nil)
708		if err != nil {
709			r.Fatal(err)
710		}
711
712		if _, ok := node.Services["redis1"]; !ok {
713			r.Fatal("missing service: redis1")
714		}
715
716		if _, ok := node.Services["redis-proxy1"]; !ok {
717			r.Fatal("missing service: redis-proxy1")
718		}
719
720		health, _, err := c.Health().Node("foobar", nil)
721		if err != nil {
722			r.Fatal(err)
723		}
724
725		if health[0].CheckID != "service:redis1" {
726			r.Fatal("missing checkid service:redis1")
727		}
728
729		if v, ok := node.Node.Meta["somekey"]; !ok || v != "somevalue" {
730			r.Fatal("missing node meta pair somekey:somevalue")
731		}
732	})
733
734	// Test catalog deregistration of the previously registered service
735	dereg := &CatalogDeregistration{
736		Datacenter: "dc1",
737		Node:       "foobar",
738		Address:    "192.168.10.10",
739		ServiceID:  "redis1",
740	}
741
742	// ... and proxy
743	deregProxy := &CatalogDeregistration{
744		Datacenter: "dc1",
745		Node:       "foobar",
746		Address:    "192.168.10.10",
747		ServiceID:  "redis-proxy1",
748	}
749
750	if _, err := catalog.Deregister(dereg, nil); err != nil {
751		t.Fatalf("err: %v", err)
752	}
753
754	if _, err := catalog.Deregister(deregProxy, nil); err != nil {
755		t.Fatalf("err: %v", err)
756	}
757
758	retry.Run(t, func(r *retry.R) {
759		node, _, err := catalog.Node("foobar", nil)
760		if err != nil {
761			r.Fatal(err)
762		}
763
764		if _, ok := node.Services["redis1"]; ok {
765			r.Fatal("ServiceID:redis1 is not deregistered")
766		}
767
768		if _, ok := node.Services["redis-proxy1"]; ok {
769			r.Fatal("ServiceID:redis-proxy1 is not deregistered")
770		}
771	})
772
773	// Test deregistration of the previously registered check
774	dereg = &CatalogDeregistration{
775		Datacenter: "dc1",
776		Node:       "foobar",
777		Address:    "192.168.10.10",
778		CheckID:    "service:redis1",
779	}
780
781	if _, err := catalog.Deregister(dereg, nil); err != nil {
782		t.Fatalf("err: %v", err)
783	}
784
785	retry.Run(t, func(r *retry.R) {
786		health, _, err := c.Health().Node("foobar", nil)
787		if err != nil {
788			r.Fatal(err)
789		}
790
791		if len(health) != 0 {
792			r.Fatal("CheckID:service:redis1 is not deregistered")
793		}
794	})
795
796	// Test node deregistration of the previously registered node
797	dereg = &CatalogDeregistration{
798		Datacenter: "dc1",
799		Node:       "foobar",
800		Address:    "192.168.10.10",
801	}
802
803	if _, err := catalog.Deregister(dereg, nil); err != nil {
804		t.Fatalf("err: %v", err)
805	}
806
807	retry.Run(t, func(r *retry.R) {
808		node, _, err := catalog.Node("foobar", nil)
809		if err != nil {
810			r.Fatal(err)
811		}
812
813		if node != nil {
814			r.Fatalf("node is not deregistered: %v", node)
815		}
816	})
817}
818
819func TestAPI_CatalogEnableTagOverride(t *testing.T) {
820	t.Parallel()
821	c, s := makeClient(t)
822	defer s.Stop()
823
824	catalog := c.Catalog()
825
826	service := &AgentService{
827		ID:      "redis1",
828		Service: "redis",
829		Tags:    []string{"master", "v1"},
830		Port:    8000,
831	}
832
833	reg := &CatalogRegistration{
834		Datacenter: "dc1",
835		Node:       "foobar",
836		Address:    "192.168.10.10",
837		Service:    service,
838	}
839
840	retry.Run(t, func(r *retry.R) {
841		if _, err := catalog.Register(reg, nil); err != nil {
842			r.Fatal(err)
843		}
844
845		node, _, err := catalog.Node("foobar", nil)
846		if err != nil {
847			r.Fatal(err)
848		}
849
850		if _, ok := node.Services["redis1"]; !ok {
851			r.Fatal("missing service: redis1")
852		}
853		if node.Services["redis1"].EnableTagOverride != false {
854			r.Fatal("tag override set")
855		}
856
857		services, _, err := catalog.Service("redis", "", nil)
858		if err != nil {
859			r.Fatal(err)
860		}
861
862		if len(services) < 1 || services[0].ServiceName != "redis" {
863			r.Fatal("missing service: redis")
864		}
865		if services[0].ServiceEnableTagOverride != false {
866			r.Fatal("tag override set")
867		}
868	})
869
870	service.EnableTagOverride = true
871
872	retry.Run(t, func(r *retry.R) {
873		if _, err := catalog.Register(reg, nil); err != nil {
874			r.Fatal(err)
875		}
876
877		node, _, err := catalog.Node("foobar", nil)
878		if err != nil {
879			r.Fatal(err)
880		}
881
882		if _, ok := node.Services["redis1"]; !ok {
883			r.Fatal("missing service: redis1")
884		}
885		if node.Services["redis1"].EnableTagOverride != true {
886			r.Fatal("tag override not set")
887		}
888
889		services, _, err := catalog.Service("redis", "", nil)
890		if err != nil {
891			r.Fatal(err)
892		}
893
894		if len(services) < 1 || services[0].ServiceName != "redis" {
895			r.Fatal("missing service: redis")
896		}
897		if services[0].ServiceEnableTagOverride != true {
898			r.Fatal("tag override not set")
899		}
900	})
901}
902