github.com/kjdelisle/consul@v1.4.5/api/catalog_test.go (about)

     1  package api
     2  
     3  import (
     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  
    14  func 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  
    31  func 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  
    76  func 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  
   130  func 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  
   152  func 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  
   194  func 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  
   221  func 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  
   258  func 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  
   297  func 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  
   324  func 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  
   375  func 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  
   404  func 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  
   421  func 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.
   435  func 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.
   453  func 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  
   462  func 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  
   541  func 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  
   600  func 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  
   651  func 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-a",
   668  		Name:      "Redis health check",
   669  		Notes:     "Script based health check",
   670  		Status:    HealthPassing,
   671  		ServiceID: "redis1",
   672  	}
   673  
   674  	checks := HealthChecks{
   675  		&HealthCheck{
   676  			Node:      "foobar",
   677  			CheckID:   "service:redis1-b",
   678  			Name:      "Redis health check",
   679  			Notes:     "Script based health check",
   680  			Status:    HealthPassing,
   681  			ServiceID: "redis1",
   682  		},
   683  	}
   684  
   685  	reg := &CatalogRegistration{
   686  		Datacenter: "dc1",
   687  		Node:       "foobar",
   688  		Address:    "192.168.10.10",
   689  		NodeMeta:   map[string]string{"somekey": "somevalue"},
   690  		Service:    service,
   691  		// Specifying both Check and Checks is accepted by Consul
   692  		Check:  check,
   693  		Checks: checks,
   694  	}
   695  	// Register a connect proxy for that service too
   696  	proxy := &AgentService{
   697  		ID:      "redis-proxy1",
   698  		Service: "redis-proxy",
   699  		Port:    8001,
   700  		Kind:    ServiceKindConnectProxy,
   701  		Proxy: &AgentServiceConnectProxyConfig{
   702  			DestinationServiceName: service.Service,
   703  		},
   704  	}
   705  	proxyReg := &CatalogRegistration{
   706  		Datacenter: "dc1",
   707  		Node:       "foobar",
   708  		Address:    "192.168.10.10",
   709  		NodeMeta:   map[string]string{"somekey": "somevalue"},
   710  		Service:    proxy,
   711  	}
   712  	retry.Run(t, func(r *retry.R) {
   713  		if _, err := catalog.Register(reg, nil); err != nil {
   714  			r.Fatal(err)
   715  		}
   716  		if _, err := catalog.Register(proxyReg, nil); err != nil {
   717  			r.Fatal(err)
   718  		}
   719  
   720  		node, _, err := catalog.Node("foobar", nil)
   721  		if err != nil {
   722  			r.Fatal(err)
   723  		}
   724  
   725  		if _, ok := node.Services["redis1"]; !ok {
   726  			r.Fatal("missing service: redis1")
   727  		}
   728  
   729  		if _, ok := node.Services["redis-proxy1"]; !ok {
   730  			r.Fatal("missing service: redis-proxy1")
   731  		}
   732  
   733  		health, _, err := c.Health().Node("foobar", nil)
   734  		if err != nil {
   735  			r.Fatal(err)
   736  		}
   737  
   738  		if health[0].CheckID != "service:redis1-a" {
   739  			r.Fatal("missing checkid service:redis1-a")
   740  		}
   741  
   742  		if health[1].CheckID != "service:redis1-b" {
   743  			r.Fatal("missing checkid service:redis1-b")
   744  		}
   745  
   746  		if v, ok := node.Node.Meta["somekey"]; !ok || v != "somevalue" {
   747  			r.Fatal("missing node meta pair somekey:somevalue")
   748  		}
   749  	})
   750  
   751  	// Test catalog deregistration of the previously registered service
   752  	dereg := &CatalogDeregistration{
   753  		Datacenter: "dc1",
   754  		Node:       "foobar",
   755  		Address:    "192.168.10.10",
   756  		ServiceID:  "redis1",
   757  	}
   758  
   759  	// ... and proxy
   760  	deregProxy := &CatalogDeregistration{
   761  		Datacenter: "dc1",
   762  		Node:       "foobar",
   763  		Address:    "192.168.10.10",
   764  		ServiceID:  "redis-proxy1",
   765  	}
   766  
   767  	if _, err := catalog.Deregister(dereg, nil); err != nil {
   768  		t.Fatalf("err: %v", err)
   769  	}
   770  
   771  	if _, err := catalog.Deregister(deregProxy, nil); err != nil {
   772  		t.Fatalf("err: %v", err)
   773  	}
   774  
   775  	retry.Run(t, func(r *retry.R) {
   776  		node, _, err := catalog.Node("foobar", nil)
   777  		if err != nil {
   778  			r.Fatal(err)
   779  		}
   780  
   781  		if _, ok := node.Services["redis1"]; ok {
   782  			r.Fatal("ServiceID:redis1 is not deregistered")
   783  		}
   784  
   785  		if _, ok := node.Services["redis-proxy1"]; ok {
   786  			r.Fatal("ServiceID:redis-proxy1 is not deregistered")
   787  		}
   788  	})
   789  
   790  	// Test deregistration of the previously registered check
   791  	dereg = &CatalogDeregistration{
   792  		Datacenter: "dc1",
   793  		Node:       "foobar",
   794  		Address:    "192.168.10.10",
   795  		CheckID:    "service:redis1-a",
   796  	}
   797  
   798  	if _, err := catalog.Deregister(dereg, nil); err != nil {
   799  		t.Fatalf("err: %v", err)
   800  	}
   801  
   802  	dereg = &CatalogDeregistration{
   803  		Datacenter: "dc1",
   804  		Node:       "foobar",
   805  		Address:    "192.168.10.10",
   806  		CheckID:    "service:redis1-b",
   807  	}
   808  
   809  	if _, err := catalog.Deregister(dereg, nil); err != nil {
   810  		t.Fatalf("err: %v", err)
   811  	}
   812  
   813  	retry.Run(t, func(r *retry.R) {
   814  		health, _, err := c.Health().Node("foobar", nil)
   815  		if err != nil {
   816  			r.Fatal(err)
   817  		}
   818  
   819  		if len(health) != 0 {
   820  			r.Fatal("CheckID:service:redis1-a or CheckID:service:redis1-a is not deregistered")
   821  		}
   822  	})
   823  
   824  	// Test node deregistration of the previously registered node
   825  	dereg = &CatalogDeregistration{
   826  		Datacenter: "dc1",
   827  		Node:       "foobar",
   828  		Address:    "192.168.10.10",
   829  	}
   830  
   831  	if _, err := catalog.Deregister(dereg, nil); err != nil {
   832  		t.Fatalf("err: %v", err)
   833  	}
   834  
   835  	retry.Run(t, func(r *retry.R) {
   836  		node, _, err := catalog.Node("foobar", nil)
   837  		if err != nil {
   838  			r.Fatal(err)
   839  		}
   840  
   841  		if node != nil {
   842  			r.Fatalf("node is not deregistered: %v", node)
   843  		}
   844  	})
   845  }
   846  
   847  func TestAPI_CatalogEnableTagOverride(t *testing.T) {
   848  	t.Parallel()
   849  	c, s := makeClient(t)
   850  	defer s.Stop()
   851  	s.WaitForSerfCheck(t)
   852  
   853  	catalog := c.Catalog()
   854  
   855  	service := &AgentService{
   856  		ID:      "redis1",
   857  		Service: "redis",
   858  		Tags:    []string{"master", "v1"},
   859  		Port:    8000,
   860  	}
   861  
   862  	reg := &CatalogRegistration{
   863  		Datacenter: "dc1",
   864  		Node:       "foobar",
   865  		Address:    "192.168.10.10",
   866  		Service:    service,
   867  	}
   868  
   869  	retry.Run(t, func(r *retry.R) {
   870  		if _, err := catalog.Register(reg, nil); err != nil {
   871  			r.Fatal(err)
   872  		}
   873  
   874  		node, _, err := catalog.Node("foobar", nil)
   875  		if err != nil {
   876  			r.Fatal(err)
   877  		}
   878  
   879  		if _, ok := node.Services["redis1"]; !ok {
   880  			r.Fatal("missing service: redis1")
   881  		}
   882  		if node.Services["redis1"].EnableTagOverride != false {
   883  			r.Fatal("tag override set")
   884  		}
   885  
   886  		services, _, err := catalog.Service("redis", "", nil)
   887  		if err != nil {
   888  			r.Fatal(err)
   889  		}
   890  
   891  		if len(services) < 1 || services[0].ServiceName != "redis" {
   892  			r.Fatal("missing service: redis")
   893  		}
   894  		if services[0].ServiceEnableTagOverride != false {
   895  			r.Fatal("tag override set")
   896  		}
   897  	})
   898  
   899  	service.EnableTagOverride = true
   900  
   901  	retry.Run(t, func(r *retry.R) {
   902  		if _, err := catalog.Register(reg, nil); err != nil {
   903  			r.Fatal(err)
   904  		}
   905  
   906  		node, _, err := catalog.Node("foobar", nil)
   907  		if err != nil {
   908  			r.Fatal(err)
   909  		}
   910  
   911  		if _, ok := node.Services["redis1"]; !ok {
   912  			r.Fatal("missing service: redis1")
   913  		}
   914  		if node.Services["redis1"].EnableTagOverride != true {
   915  			r.Fatal("tag override not set")
   916  		}
   917  
   918  		services, _, err := catalog.Service("redis", "", nil)
   919  		if err != nil {
   920  			r.Fatal(err)
   921  		}
   922  
   923  		if len(services) < 1 || services[0].ServiceName != "redis" {
   924  			r.Fatal("missing service: redis")
   925  		}
   926  		if services[0].ServiceEnableTagOverride != true {
   927  			r.Fatal("tag override not set")
   928  		}
   929  	})
   930  }