github.com/outbrain/consul@v1.4.5/agent/catalog_endpoint_test.go (about)

     1  package agent
     2  
     3  import (
     4  	"fmt"
     5  	"net/http"
     6  	"net/http/httptest"
     7  	"testing"
     8  	"time"
     9  
    10  	"github.com/hashicorp/consul/agent/structs"
    11  	"github.com/hashicorp/consul/testrpc"
    12  	"github.com/hashicorp/consul/testutil/retry"
    13  	"github.com/hashicorp/serf/coordinate"
    14  	"github.com/stretchr/testify/assert"
    15  	"github.com/stretchr/testify/require"
    16  )
    17  
    18  func TestCatalogRegister_Service_InvalidAddress(t *testing.T) {
    19  	t.Parallel()
    20  	a := NewTestAgent(t, t.Name(), "")
    21  	defer a.Shutdown()
    22  
    23  	for _, addr := range []string{"0.0.0.0", "::", "[::]"} {
    24  		t.Run("addr "+addr, func(t *testing.T) {
    25  			args := &structs.RegisterRequest{
    26  				Node:    "foo",
    27  				Address: "127.0.0.1",
    28  				Service: &structs.NodeService{
    29  					Service: "test",
    30  					Address: addr,
    31  					Port:    8080,
    32  				},
    33  			}
    34  			req, _ := http.NewRequest("PUT", "/v1/catalog/register", jsonReader(args))
    35  			_, err := a.srv.CatalogRegister(nil, req)
    36  			if err == nil || err.Error() != "Invalid service address" {
    37  				t.Fatalf("err: %v", err)
    38  			}
    39  		})
    40  	}
    41  }
    42  
    43  func TestCatalogDeregister(t *testing.T) {
    44  	t.Parallel()
    45  	a := NewTestAgent(t, t.Name(), "")
    46  	defer a.Shutdown()
    47  
    48  	// Register node
    49  	args := &structs.DeregisterRequest{Node: "foo"}
    50  	req, _ := http.NewRequest("PUT", "/v1/catalog/deregister", jsonReader(args))
    51  	obj, err := a.srv.CatalogDeregister(nil, req)
    52  	if err != nil {
    53  		t.Fatalf("err: %v", err)
    54  	}
    55  
    56  	res := obj.(bool)
    57  	if res != true {
    58  		t.Fatalf("bad: %v", res)
    59  	}
    60  }
    61  
    62  func TestCatalogDatacenters(t *testing.T) {
    63  	t.Parallel()
    64  	a := NewTestAgent(t, t.Name(), "")
    65  	defer a.Shutdown()
    66  
    67  	retry.Run(t, func(r *retry.R) {
    68  		req, _ := http.NewRequest("GET", "/v1/catalog/datacenters", nil)
    69  		obj, err := a.srv.CatalogDatacenters(nil, req)
    70  		if err != nil {
    71  			r.Fatal(err)
    72  		}
    73  
    74  		dcs := obj.([]string)
    75  		if got, want := len(dcs), 1; got != want {
    76  			r.Fatalf("got %d data centers want %d", got, want)
    77  		}
    78  	})
    79  }
    80  
    81  func TestCatalogNodes(t *testing.T) {
    82  	t.Parallel()
    83  	a := NewTestAgent(t, t.Name(), "")
    84  	defer a.Shutdown()
    85  	testrpc.WaitForTestAgent(t, a.RPC, "dc1")
    86  
    87  	// Register node
    88  	args := &structs.RegisterRequest{
    89  		Datacenter: "dc1",
    90  		Node:       "foo",
    91  		Address:    "127.0.0.1",
    92  	}
    93  
    94  	var out struct{}
    95  	if err := a.RPC("Catalog.Register", args, &out); err != nil {
    96  		t.Fatalf("err: %v", err)
    97  	}
    98  
    99  	req, _ := http.NewRequest("GET", "/v1/catalog/nodes?dc=dc1", nil)
   100  	resp := httptest.NewRecorder()
   101  	obj, err := a.srv.CatalogNodes(resp, req)
   102  	if err != nil {
   103  		t.Fatalf("err: %v", err)
   104  	}
   105  
   106  	// Verify an index is set
   107  	assertIndex(t, resp)
   108  
   109  	nodes := obj.(structs.Nodes)
   110  	if len(nodes) != 2 {
   111  		t.Fatalf("bad: %v ; nodes:=%v", obj, nodes)
   112  	}
   113  }
   114  
   115  func TestCatalogNodes_MetaFilter(t *testing.T) {
   116  	t.Parallel()
   117  	a := NewTestAgent(t, t.Name(), "")
   118  	defer a.Shutdown()
   119  	testrpc.WaitForTestAgent(t, a.RPC, "dc1")
   120  
   121  	// Register a node with a meta field
   122  	args := &structs.RegisterRequest{
   123  		Datacenter: "dc1",
   124  		Node:       "foo",
   125  		Address:    "127.0.0.1",
   126  		NodeMeta: map[string]string{
   127  			"somekey": "somevalue",
   128  		},
   129  	}
   130  
   131  	var out struct{}
   132  	if err := a.RPC("Catalog.Register", args, &out); err != nil {
   133  		t.Fatalf("err: %v", err)
   134  	}
   135  
   136  	req, _ := http.NewRequest("GET", "/v1/catalog/nodes?node-meta=somekey:somevalue", nil)
   137  	resp := httptest.NewRecorder()
   138  	obj, err := a.srv.CatalogNodes(resp, req)
   139  	if err != nil {
   140  		t.Fatalf("err: %v", err)
   141  	}
   142  
   143  	// Verify an index is set
   144  	assertIndex(t, resp)
   145  
   146  	// Verify we only get the node with the correct meta field back
   147  	nodes := obj.(structs.Nodes)
   148  	if len(nodes) != 1 {
   149  		t.Fatalf("bad: %v", obj)
   150  	}
   151  	if v, ok := nodes[0].Meta["somekey"]; !ok || v != "somevalue" {
   152  		t.Fatalf("bad: %v", nodes[0].Meta)
   153  	}
   154  }
   155  
   156  func TestCatalogNodes_WanTranslation(t *testing.T) {
   157  	t.Parallel()
   158  	a1 := NewTestAgent(t, t.Name(), `
   159  		datacenter = "dc1"
   160  		translate_wan_addrs = true
   161  		acl_datacenter = ""
   162  	`)
   163  	defer a1.Shutdown()
   164  	testrpc.WaitForTestAgent(t, a1.RPC, "dc1")
   165  
   166  	a2 := NewTestAgent(t, t.Name(), `
   167  		datacenter = "dc2"
   168  		translate_wan_addrs = true
   169  		acl_datacenter = ""
   170  	`)
   171  	defer a2.Shutdown()
   172  	testrpc.WaitForTestAgent(t, a2.RPC, "dc2")
   173  
   174  	// Wait for the WAN join.
   175  	addr := fmt.Sprintf("127.0.0.1:%d", a1.Config.SerfPortWAN)
   176  	if _, err := a2.JoinWAN([]string{addr}); err != nil {
   177  		t.Fatalf("err: %v", err)
   178  	}
   179  	testrpc.WaitForLeader(t, a1.RPC, "dc1")
   180  	testrpc.WaitForLeader(t, a2.RPC, "dc2")
   181  	retry.Run(t, func(r *retry.R) {
   182  		if got, want := len(a1.WANMembers()), 2; got < want {
   183  			r.Fatalf("got %d WAN members want at least %d", got, want)
   184  		}
   185  	})
   186  
   187  	// Register a node with DC2.
   188  	{
   189  		args := &structs.RegisterRequest{
   190  			Datacenter: "dc2",
   191  			Node:       "wan_translation_test",
   192  			Address:    "127.0.0.1",
   193  			TaggedAddresses: map[string]string{
   194  				"wan": "127.0.0.2",
   195  			},
   196  			Service: &structs.NodeService{
   197  				Service: "http_wan_translation_test",
   198  			},
   199  		}
   200  
   201  		var out struct{}
   202  		if err := a2.RPC("Catalog.Register", args, &out); err != nil {
   203  			t.Fatalf("err: %v", err)
   204  		}
   205  	}
   206  
   207  	// Query nodes in DC2 from DC1.
   208  	req, _ := http.NewRequest("GET", "/v1/catalog/nodes?dc=dc2", nil)
   209  	resp1 := httptest.NewRecorder()
   210  	obj1, err1 := a1.srv.CatalogNodes(resp1, req)
   211  	if err1 != nil {
   212  		t.Fatalf("err: %v", err1)
   213  	}
   214  	assertIndex(t, resp1)
   215  
   216  	// Expect that DC1 gives us a WAN address (since the node is in DC2).
   217  	nodes1 := obj1.(structs.Nodes)
   218  	if len(nodes1) != 2 {
   219  		t.Fatalf("bad: %v, nodes:=%v", obj1, nodes1)
   220  	}
   221  	var address string
   222  	for _, node := range nodes1 {
   223  		if node.Node == "wan_translation_test" {
   224  			address = node.Address
   225  		}
   226  	}
   227  	if address != "127.0.0.2" {
   228  		t.Fatalf("bad: %s", address)
   229  	}
   230  
   231  	// Query DC2 from DC2.
   232  	resp2 := httptest.NewRecorder()
   233  	obj2, err2 := a2.srv.CatalogNodes(resp2, req)
   234  	if err2 != nil {
   235  		t.Fatalf("err: %v", err2)
   236  	}
   237  	assertIndex(t, resp2)
   238  
   239  	// Expect that DC2 gives us a private address (since the node is in DC2).
   240  	nodes2 := obj2.(structs.Nodes)
   241  	if len(nodes2) != 2 {
   242  		t.Fatalf("bad: %v", obj2)
   243  	}
   244  	for _, node := range nodes2 {
   245  		if node.Node == "wan_translation_test" {
   246  			address = node.Address
   247  		}
   248  	}
   249  	if address != "127.0.0.1" {
   250  		t.Fatalf("bad: %s", address)
   251  	}
   252  }
   253  
   254  func TestCatalogNodes_Blocking(t *testing.T) {
   255  	t.Parallel()
   256  	a := NewTestAgent(t, t.Name(), "")
   257  	defer a.Shutdown()
   258  	testrpc.WaitForTestAgent(t, a.RPC, "dc1")
   259  
   260  	// Register node
   261  	args := &structs.DCSpecificRequest{
   262  		Datacenter: "dc1",
   263  	}
   264  
   265  	var out structs.IndexedNodes
   266  	if err := a.RPC("Catalog.ListNodes", *args, &out); err != nil {
   267  		t.Fatalf("err: %v", err)
   268  	}
   269  
   270  	// t.Fatal must be called from the main go routine
   271  	// of the test. Because of this we cannot call
   272  	// t.Fatal from within the go routines and use
   273  	// an error channel instead.
   274  	errch := make(chan error, 2)
   275  	go func() {
   276  		testrpc.WaitForTestAgent(t, a.RPC, "dc1")
   277  		start := time.Now()
   278  
   279  		// register a service after the blocking call
   280  		// in order to unblock it.
   281  		time.AfterFunc(100*time.Millisecond, func() {
   282  			args := &structs.RegisterRequest{
   283  				Datacenter: "dc1",
   284  				Node:       "foo",
   285  				Address:    "127.0.0.1",
   286  			}
   287  			var out struct{}
   288  			errch <- a.RPC("Catalog.Register", args, &out)
   289  		})
   290  
   291  		// now block
   292  		req, _ := http.NewRequest("GET", fmt.Sprintf("/v1/catalog/nodes?wait=3s&index=%d", out.Index+1), nil)
   293  		resp := httptest.NewRecorder()
   294  		obj, err := a.srv.CatalogNodes(resp, req)
   295  		if err != nil {
   296  			errch <- err
   297  		}
   298  
   299  		// Should block for a while
   300  		if d := time.Since(start); d < 50*time.Millisecond {
   301  			errch <- fmt.Errorf("too fast: %v", d)
   302  		}
   303  
   304  		if idx := getIndex(t, resp); idx <= out.Index {
   305  			errch <- fmt.Errorf("bad: %v", idx)
   306  		}
   307  
   308  		nodes := obj.(structs.Nodes)
   309  		if len(nodes) != 2 {
   310  			errch <- fmt.Errorf("bad: %v", obj)
   311  		}
   312  		errch <- nil
   313  	}()
   314  
   315  	// wait for both go routines to return
   316  	if err := <-errch; err != nil {
   317  		t.Fatal(err)
   318  	}
   319  	if err := <-errch; err != nil {
   320  		t.Fatal(err)
   321  	}
   322  }
   323  
   324  func TestCatalogNodes_DistanceSort(t *testing.T) {
   325  	t.Parallel()
   326  	a := NewTestAgent(t, t.Name(), "")
   327  	defer a.Shutdown()
   328  	testrpc.WaitForTestAgent(t, a.RPC, "dc1")
   329  
   330  	// Register nodes.
   331  	args := &structs.RegisterRequest{
   332  		Datacenter: "dc1",
   333  		Node:       "foo",
   334  		Address:    "127.0.0.1",
   335  	}
   336  	var out struct{}
   337  	if err := a.RPC("Catalog.Register", args, &out); err != nil {
   338  		t.Fatalf("err: %v", err)
   339  	}
   340  
   341  	args = &structs.RegisterRequest{
   342  		Datacenter: "dc1",
   343  		Node:       "bar",
   344  		Address:    "127.0.0.2",
   345  	}
   346  	if err := a.RPC("Catalog.Register", args, &out); err != nil {
   347  		t.Fatalf("err: %v", err)
   348  	}
   349  
   350  	// Nobody has coordinates set so this will still return them in the
   351  	// order they are indexed.
   352  	req, _ := http.NewRequest("GET", "/v1/catalog/nodes?dc=dc1&near=foo", nil)
   353  	resp := httptest.NewRecorder()
   354  	obj, err := a.srv.CatalogNodes(resp, req)
   355  	if err != nil {
   356  		t.Fatalf("err: %v", err)
   357  	}
   358  
   359  	assertIndex(t, resp)
   360  	nodes := obj.(structs.Nodes)
   361  	if len(nodes) != 3 {
   362  		t.Fatalf("bad: %v", obj)
   363  	}
   364  	if nodes[0].Node != "bar" {
   365  		t.Fatalf("bad: %v", nodes)
   366  	}
   367  	if nodes[1].Node != "foo" {
   368  		t.Fatalf("bad: %v", nodes)
   369  	}
   370  	if nodes[2].Node != a.Config.NodeName {
   371  		t.Fatalf("bad: %v", nodes)
   372  	}
   373  
   374  	// Send an update for the node and wait for it to get applied.
   375  	arg := structs.CoordinateUpdateRequest{
   376  		Datacenter: "dc1",
   377  		Node:       "foo",
   378  		Coord:      coordinate.NewCoordinate(coordinate.DefaultConfig()),
   379  	}
   380  	if err := a.RPC("Coordinate.Update", &arg, &out); err != nil {
   381  		t.Fatalf("err: %v", err)
   382  	}
   383  	time.Sleep(300 * time.Millisecond)
   384  
   385  	// Query again and now foo should have moved to the front of the line.
   386  	req, _ = http.NewRequest("GET", "/v1/catalog/nodes?dc=dc1&near=foo", nil)
   387  	resp = httptest.NewRecorder()
   388  	obj, err = a.srv.CatalogNodes(resp, req)
   389  	if err != nil {
   390  		t.Fatalf("err: %v", err)
   391  	}
   392  
   393  	assertIndex(t, resp)
   394  	nodes = obj.(structs.Nodes)
   395  	if len(nodes) != 3 {
   396  		t.Fatalf("bad: %v", obj)
   397  	}
   398  	if nodes[0].Node != "foo" {
   399  		t.Fatalf("bad: %v", nodes)
   400  	}
   401  	if nodes[1].Node != "bar" {
   402  		t.Fatalf("bad: %v", nodes)
   403  	}
   404  	if nodes[2].Node != a.Config.NodeName {
   405  		t.Fatalf("bad: %v", nodes)
   406  	}
   407  }
   408  
   409  func TestCatalogServices(t *testing.T) {
   410  	t.Parallel()
   411  	a := NewTestAgent(t, t.Name(), "")
   412  	defer a.Shutdown()
   413  	testrpc.WaitForTestAgent(t, a.RPC, "dc1")
   414  
   415  	// Register node
   416  	args := &structs.RegisterRequest{
   417  		Datacenter: "dc1",
   418  		Node:       "foo",
   419  		Address:    "127.0.0.1",
   420  		Service: &structs.NodeService{
   421  			Service: "api",
   422  		},
   423  	}
   424  
   425  	var out struct{}
   426  	if err := a.RPC("Catalog.Register", args, &out); err != nil {
   427  		t.Fatalf("err: %v", err)
   428  	}
   429  
   430  	req, _ := http.NewRequest("GET", "/v1/catalog/services?dc=dc1", nil)
   431  	resp := httptest.NewRecorder()
   432  	obj, err := a.srv.CatalogServices(resp, req)
   433  	if err != nil {
   434  		t.Fatalf("err: %v", err)
   435  	}
   436  
   437  	assertIndex(t, resp)
   438  
   439  	services := obj.(structs.Services)
   440  	if len(services) != 2 {
   441  		t.Fatalf("bad: %v", obj)
   442  	}
   443  }
   444  
   445  func TestCatalogServices_NodeMetaFilter(t *testing.T) {
   446  	t.Parallel()
   447  	a := NewTestAgent(t, t.Name(), "")
   448  	defer a.Shutdown()
   449  
   450  	// Register node
   451  	args := &structs.RegisterRequest{
   452  		Datacenter: "dc1",
   453  		Node:       "foo",
   454  		Address:    "127.0.0.1",
   455  		NodeMeta: map[string]string{
   456  			"somekey": "somevalue",
   457  		},
   458  		Service: &structs.NodeService{
   459  			Service: "api",
   460  		},
   461  	}
   462  
   463  	var out struct{}
   464  	if err := a.RPC("Catalog.Register", args, &out); err != nil {
   465  		t.Fatalf("err: %v", err)
   466  	}
   467  
   468  	req, _ := http.NewRequest("GET", "/v1/catalog/services?node-meta=somekey:somevalue", nil)
   469  	resp := httptest.NewRecorder()
   470  	obj, err := a.srv.CatalogServices(resp, req)
   471  	if err != nil {
   472  		t.Fatalf("err: %v", err)
   473  	}
   474  
   475  	assertIndex(t, resp)
   476  
   477  	services := obj.(structs.Services)
   478  	if len(services) != 1 {
   479  		t.Fatalf("bad: %v", obj)
   480  	}
   481  	if _, ok := services[args.Service.Service]; !ok {
   482  		t.Fatalf("bad: %v", services)
   483  	}
   484  }
   485  
   486  func TestCatalogServiceNodes(t *testing.T) {
   487  	t.Parallel()
   488  	a := NewTestAgent(t, t.Name(), "")
   489  	defer a.Shutdown()
   490  
   491  	assert := assert.New(t)
   492  	require := require.New(t)
   493  
   494  	// Make sure an empty list is returned, not a nil
   495  	{
   496  		req, _ := http.NewRequest("GET", "/v1/catalog/service/api?tag=a", nil)
   497  		resp := httptest.NewRecorder()
   498  		obj, err := a.srv.CatalogServiceNodes(resp, req)
   499  		if err != nil {
   500  			t.Fatalf("err: %v", err)
   501  		}
   502  
   503  		assertIndex(t, resp)
   504  
   505  		nodes := obj.(structs.ServiceNodes)
   506  		if nodes == nil || len(nodes) != 0 {
   507  			t.Fatalf("bad: %v", obj)
   508  		}
   509  	}
   510  
   511  	// Register node
   512  	args := &structs.RegisterRequest{
   513  		Datacenter: "dc1",
   514  		Node:       "foo",
   515  		Address:    "127.0.0.1",
   516  		Service: &structs.NodeService{
   517  			Service: "api",
   518  			Tags:    []string{"a"},
   519  		},
   520  	}
   521  
   522  	var out struct{}
   523  	if err := a.RPC("Catalog.Register", args, &out); err != nil {
   524  		t.Fatalf("err: %v", err)
   525  	}
   526  
   527  	req, _ := http.NewRequest("GET", "/v1/catalog/service/api?tag=a", nil)
   528  	resp := httptest.NewRecorder()
   529  	obj, err := a.srv.CatalogServiceNodes(resp, req)
   530  	if err != nil {
   531  		t.Fatalf("err: %v", err)
   532  	}
   533  
   534  	assertIndex(t, resp)
   535  
   536  	nodes := obj.(structs.ServiceNodes)
   537  	if len(nodes) != 1 {
   538  		t.Fatalf("bad: %v", obj)
   539  	}
   540  
   541  	// Test caching
   542  	{
   543  		// List instances with cache enabled
   544  		req, _ := http.NewRequest("GET", "/v1/catalog/service/api?cached", nil)
   545  		resp := httptest.NewRecorder()
   546  		obj, err := a.srv.CatalogServiceNodes(resp, req)
   547  		require.NoError(err)
   548  		nodes := obj.(structs.ServiceNodes)
   549  		assert.Len(nodes, 1)
   550  
   551  		// Should be a cache miss
   552  		assert.Equal("MISS", resp.Header().Get("X-Cache"))
   553  	}
   554  
   555  	{
   556  		// List instances with cache enabled
   557  		req, _ := http.NewRequest("GET", "/v1/catalog/service/api?cached", nil)
   558  		resp := httptest.NewRecorder()
   559  		obj, err := a.srv.CatalogServiceNodes(resp, req)
   560  		require.NoError(err)
   561  		nodes := obj.(structs.ServiceNodes)
   562  		assert.Len(nodes, 1)
   563  
   564  		// Should be a cache HIT now!
   565  		assert.Equal("HIT", resp.Header().Get("X-Cache"))
   566  		assert.Equal("0", resp.Header().Get("Age"))
   567  	}
   568  
   569  	// Ensure background refresh works
   570  	{
   571  		// Register a new instance of the service
   572  		args2 := args
   573  		args2.Node = "bar"
   574  		args2.Address = "127.0.0.2"
   575  		require.NoError(a.RPC("Catalog.Register", args, &out))
   576  
   577  		retry.Run(t, func(r *retry.R) {
   578  			// List it again
   579  			req, _ := http.NewRequest("GET", "/v1/catalog/service/api?cached", nil)
   580  			resp := httptest.NewRecorder()
   581  			obj, err := a.srv.CatalogServiceNodes(resp, req)
   582  			r.Check(err)
   583  
   584  			nodes := obj.(structs.ServiceNodes)
   585  			if len(nodes) != 2 {
   586  				r.Fatalf("Want 2 nodes")
   587  			}
   588  
   589  			// Should be a cache hit! The data should've updated in the cache
   590  			// in the background so this should've been fetched directly from
   591  			// the cache.
   592  			if resp.Header().Get("X-Cache") != "HIT" {
   593  				r.Fatalf("should be a cache hit")
   594  			}
   595  		})
   596  	}
   597  }
   598  
   599  func TestCatalogServiceNodes_NodeMetaFilter(t *testing.T) {
   600  	t.Parallel()
   601  	a := NewTestAgent(t, t.Name(), "")
   602  	defer a.Shutdown()
   603  
   604  	// Make sure an empty list is returned, not a nil
   605  	{
   606  		req, _ := http.NewRequest("GET", "/v1/catalog/service/api?node-meta=somekey:somevalue", nil)
   607  		resp := httptest.NewRecorder()
   608  		obj, err := a.srv.CatalogServiceNodes(resp, req)
   609  		if err != nil {
   610  			t.Fatalf("err: %v", err)
   611  		}
   612  
   613  		assertIndex(t, resp)
   614  
   615  		nodes := obj.(structs.ServiceNodes)
   616  		if nodes == nil || len(nodes) != 0 {
   617  			t.Fatalf("bad: %v", obj)
   618  		}
   619  	}
   620  
   621  	// Register node
   622  	args := &structs.RegisterRequest{
   623  		Datacenter: "dc1",
   624  		Node:       "foo",
   625  		Address:    "127.0.0.1",
   626  		NodeMeta: map[string]string{
   627  			"somekey": "somevalue",
   628  		},
   629  		Service: &structs.NodeService{
   630  			Service: "api",
   631  		},
   632  	}
   633  
   634  	var out struct{}
   635  	if err := a.RPC("Catalog.Register", args, &out); err != nil {
   636  		t.Fatalf("err: %v", err)
   637  	}
   638  
   639  	req, _ := http.NewRequest("GET", "/v1/catalog/service/api?node-meta=somekey:somevalue", nil)
   640  	resp := httptest.NewRecorder()
   641  	obj, err := a.srv.CatalogServiceNodes(resp, req)
   642  	if err != nil {
   643  		t.Fatalf("err: %v", err)
   644  	}
   645  
   646  	assertIndex(t, resp)
   647  
   648  	nodes := obj.(structs.ServiceNodes)
   649  	if len(nodes) != 1 {
   650  		t.Fatalf("bad: %v", obj)
   651  	}
   652  }
   653  
   654  func TestCatalogServiceNodes_WanTranslation(t *testing.T) {
   655  	t.Parallel()
   656  	a1 := NewTestAgent(t, t.Name(), `
   657  		datacenter = "dc1"
   658  		translate_wan_addrs = true
   659  		acl_datacenter = ""
   660  	`)
   661  	defer a1.Shutdown()
   662  
   663  	a2 := NewTestAgent(t, t.Name(), `
   664  		datacenter = "dc2"
   665  		translate_wan_addrs = true
   666  		acl_datacenter = ""
   667  	`)
   668  	defer a2.Shutdown()
   669  
   670  	// Wait for the WAN join.
   671  	addr := fmt.Sprintf("127.0.0.1:%d", a1.Config.SerfPortWAN)
   672  	if _, err := a2.srv.agent.JoinWAN([]string{addr}); err != nil {
   673  		t.Fatalf("err: %v", err)
   674  	}
   675  	retry.Run(t, func(r *retry.R) {
   676  		if got, want := len(a1.WANMembers()), 2; got < want {
   677  			r.Fatalf("got %d WAN members want at least %d", got, want)
   678  		}
   679  	})
   680  
   681  	// Register a node with DC2.
   682  	{
   683  		args := &structs.RegisterRequest{
   684  			Datacenter: "dc2",
   685  			Node:       "foo",
   686  			Address:    "127.0.0.1",
   687  			TaggedAddresses: map[string]string{
   688  				"wan": "127.0.0.2",
   689  			},
   690  			Service: &structs.NodeService{
   691  				Service: "http_wan_translation_test",
   692  			},
   693  		}
   694  
   695  		var out struct{}
   696  		if err := a2.RPC("Catalog.Register", args, &out); err != nil {
   697  			t.Fatalf("err: %v", err)
   698  		}
   699  	}
   700  
   701  	// Query for the node in DC2 from DC1.
   702  	req, _ := http.NewRequest("GET", "/v1/catalog/service/http_wan_translation_test?dc=dc2", nil)
   703  	resp1 := httptest.NewRecorder()
   704  	obj1, err1 := a1.srv.CatalogServiceNodes(resp1, req)
   705  	if err1 != nil {
   706  		t.Fatalf("err: %v", err1)
   707  	}
   708  	assertIndex(t, resp1)
   709  
   710  	// Expect that DC1 gives us a WAN address (since the node is in DC2).
   711  	nodes1 := obj1.(structs.ServiceNodes)
   712  	if len(nodes1) != 1 {
   713  		t.Fatalf("bad: %v", obj1)
   714  	}
   715  	node1 := nodes1[0]
   716  	if node1.Address != "127.0.0.2" {
   717  		t.Fatalf("bad: %v", node1)
   718  	}
   719  
   720  	// Query DC2 from DC2.
   721  	resp2 := httptest.NewRecorder()
   722  	obj2, err2 := a2.srv.CatalogServiceNodes(resp2, req)
   723  	if err2 != nil {
   724  		t.Fatalf("err: %v", err2)
   725  	}
   726  	assertIndex(t, resp2)
   727  
   728  	// Expect that DC2 gives us a local address (since the node is in DC2).
   729  	nodes2 := obj2.(structs.ServiceNodes)
   730  	if len(nodes2) != 1 {
   731  		t.Fatalf("bad: %v", obj2)
   732  	}
   733  	node2 := nodes2[0]
   734  	if node2.Address != "127.0.0.1" {
   735  		t.Fatalf("bad: %v", node2)
   736  	}
   737  }
   738  
   739  func TestCatalogServiceNodes_DistanceSort(t *testing.T) {
   740  	t.Parallel()
   741  	a := NewTestAgent(t, t.Name(), "")
   742  	defer a.Shutdown()
   743  	testrpc.WaitForLeader(t, a.RPC, "dc1")
   744  
   745  	// Register nodes.
   746  	args := &structs.RegisterRequest{
   747  		Datacenter: "dc1",
   748  		Node:       "bar",
   749  		Address:    "127.0.0.1",
   750  		Service: &structs.NodeService{
   751  			Service: "api",
   752  			Tags:    []string{"a"},
   753  		},
   754  	}
   755  	var out struct{}
   756  	if err := a.RPC("Catalog.Register", args, &out); err != nil {
   757  		t.Fatalf("err: %v", err)
   758  	}
   759  
   760  	req, _ := http.NewRequest("GET", "/v1/catalog/service/api?tag=a", nil)
   761  	args = &structs.RegisterRequest{
   762  		Datacenter: "dc1",
   763  		Node:       "foo",
   764  		Address:    "127.0.0.2",
   765  		Service: &structs.NodeService{
   766  			Service: "api",
   767  			Tags:    []string{"a"},
   768  		},
   769  	}
   770  	if err := a.RPC("Catalog.Register", args, &out); err != nil {
   771  		t.Fatalf("err: %v", err)
   772  	}
   773  
   774  	// Nobody has coordinates set so this will still return them in the
   775  	// order they are indexed.
   776  	req, _ = http.NewRequest("GET", "/v1/catalog/service/api?tag=a&near=foo", nil)
   777  	resp := httptest.NewRecorder()
   778  	obj, err := a.srv.CatalogServiceNodes(resp, req)
   779  	if err != nil {
   780  		t.Fatalf("err: %v", err)
   781  	}
   782  
   783  	assertIndex(t, resp)
   784  	nodes := obj.(structs.ServiceNodes)
   785  	if len(nodes) != 2 {
   786  		t.Fatalf("bad: %v", obj)
   787  	}
   788  	if nodes[0].Node != "bar" {
   789  		t.Fatalf("bad: %v", nodes)
   790  	}
   791  	if nodes[1].Node != "foo" {
   792  		t.Fatalf("bad: %v", nodes)
   793  	}
   794  
   795  	// Send an update for the node and wait for it to get applied.
   796  	arg := structs.CoordinateUpdateRequest{
   797  		Datacenter: "dc1",
   798  		Node:       "foo",
   799  		Coord:      coordinate.NewCoordinate(coordinate.DefaultConfig()),
   800  	}
   801  	if err := a.RPC("Coordinate.Update", &arg, &out); err != nil {
   802  		t.Fatalf("err: %v", err)
   803  	}
   804  	time.Sleep(300 * time.Millisecond)
   805  
   806  	// Query again and now foo should have moved to the front of the line.
   807  	req, _ = http.NewRequest("GET", "/v1/catalog/service/api?tag=a&near=foo", nil)
   808  	resp = httptest.NewRecorder()
   809  	obj, err = a.srv.CatalogServiceNodes(resp, req)
   810  	if err != nil {
   811  		t.Fatalf("err: %v", err)
   812  	}
   813  
   814  	assertIndex(t, resp)
   815  	nodes = obj.(structs.ServiceNodes)
   816  	if len(nodes) != 2 {
   817  		t.Fatalf("bad: %v", obj)
   818  	}
   819  	if nodes[0].Node != "foo" {
   820  		t.Fatalf("bad: %v", nodes)
   821  	}
   822  	if nodes[1].Node != "bar" {
   823  		t.Fatalf("bad: %v", nodes)
   824  	}
   825  }
   826  
   827  // Test that connect proxies can be queried via /v1/catalog/service/:service
   828  // directly and that their results contain the proxy fields.
   829  func TestCatalogServiceNodes_ConnectProxy(t *testing.T) {
   830  	t.Parallel()
   831  
   832  	assert := assert.New(t)
   833  	a := NewTestAgent(t, t.Name(), "")
   834  	defer a.Shutdown()
   835  	testrpc.WaitForLeader(t, a.RPC, "dc1")
   836  
   837  	// Register
   838  	args := structs.TestRegisterRequestProxy(t)
   839  	var out struct{}
   840  	assert.Nil(a.RPC("Catalog.Register", args, &out))
   841  
   842  	req, _ := http.NewRequest("GET", fmt.Sprintf(
   843  		"/v1/catalog/service/%s", args.Service.Service), nil)
   844  	resp := httptest.NewRecorder()
   845  	obj, err := a.srv.CatalogServiceNodes(resp, req)
   846  	assert.Nil(err)
   847  	assertIndex(t, resp)
   848  
   849  	nodes := obj.(structs.ServiceNodes)
   850  	assert.Len(nodes, 1)
   851  	assert.Equal(structs.ServiceKindConnectProxy, nodes[0].ServiceKind)
   852  	assert.Equal(args.Service.Proxy, nodes[0].ServiceProxy)
   853  	// DEPRECATED (ProxyDestination) - remove this when removing ProxyDestination
   854  	assert.Equal(args.Service.Proxy.DestinationServiceName, nodes[0].ServiceProxyDestination)
   855  }
   856  
   857  // Test that the Connect-compatible endpoints can be queried for a
   858  // service via /v1/catalog/connect/:service.
   859  func TestCatalogConnectServiceNodes_good(t *testing.T) {
   860  	t.Parallel()
   861  
   862  	assert := assert.New(t)
   863  	a := NewTestAgent(t, t.Name(), "")
   864  	defer a.Shutdown()
   865  	testrpc.WaitForLeader(t, a.RPC, "dc1")
   866  
   867  	// Register
   868  	args := structs.TestRegisterRequestProxy(t)
   869  	args.Service.Address = "127.0.0.55"
   870  	var out struct{}
   871  	assert.Nil(a.RPC("Catalog.Register", args, &out))
   872  
   873  	req, _ := http.NewRequest("GET", fmt.Sprintf(
   874  		"/v1/catalog/connect/%s", args.Service.Proxy.DestinationServiceName), nil)
   875  	resp := httptest.NewRecorder()
   876  	obj, err := a.srv.CatalogConnectServiceNodes(resp, req)
   877  	assert.Nil(err)
   878  	assertIndex(t, resp)
   879  
   880  	nodes := obj.(structs.ServiceNodes)
   881  	assert.Len(nodes, 1)
   882  	assert.Equal(structs.ServiceKindConnectProxy, nodes[0].ServiceKind)
   883  	assert.Equal(args.Service.Address, nodes[0].ServiceAddress)
   884  	assert.Equal(args.Service.Proxy, nodes[0].ServiceProxy)
   885  }
   886  
   887  func TestCatalogNodeServices(t *testing.T) {
   888  	t.Parallel()
   889  	a := NewTestAgent(t, t.Name(), "")
   890  	defer a.Shutdown()
   891  	testrpc.WaitForTestAgent(t, a.RPC, "dc1")
   892  
   893  	// Register node with a regular service and connect proxy
   894  	args := &structs.RegisterRequest{
   895  		Datacenter: "dc1",
   896  		Node:       "foo",
   897  		Address:    "127.0.0.1",
   898  		Service: &structs.NodeService{
   899  			Service: "api",
   900  			Tags:    []string{"a"},
   901  		},
   902  	}
   903  
   904  	var out struct{}
   905  	if err := a.RPC("Catalog.Register", args, &out); err != nil {
   906  		t.Fatalf("err: %v", err)
   907  	}
   908  
   909  	// Register a connect proxy
   910  	args.Service = structs.TestNodeServiceProxy(t)
   911  	require.NoError(t, a.RPC("Catalog.Register", args, &out))
   912  
   913  	req, _ := http.NewRequest("GET", "/v1/catalog/node/foo?dc=dc1", nil)
   914  	resp := httptest.NewRecorder()
   915  	obj, err := a.srv.CatalogNodeServices(resp, req)
   916  	if err != nil {
   917  		t.Fatalf("err: %v", err)
   918  	}
   919  	assertIndex(t, resp)
   920  
   921  	services := obj.(*structs.NodeServices)
   922  	if len(services.Services) != 2 {
   923  		t.Fatalf("bad: %v", obj)
   924  	}
   925  
   926  	// Proxy service should have it's config intact
   927  	require.Equal(t, args.Service.Proxy, services.Services["web-proxy"].Proxy)
   928  }
   929  
   930  // Test that the services on a node contain all the Connect proxies on
   931  // the node as well with their fields properly populated.
   932  func TestCatalogNodeServices_ConnectProxy(t *testing.T) {
   933  	t.Parallel()
   934  
   935  	assert := assert.New(t)
   936  	a := NewTestAgent(t, t.Name(), "")
   937  	defer a.Shutdown()
   938  	testrpc.WaitForTestAgent(t, a.RPC, "dc1")
   939  
   940  	// Register
   941  	args := structs.TestRegisterRequestProxy(t)
   942  	var out struct{}
   943  	assert.Nil(a.RPC("Catalog.Register", args, &out))
   944  
   945  	req, _ := http.NewRequest("GET", fmt.Sprintf(
   946  		"/v1/catalog/node/%s", args.Node), nil)
   947  	resp := httptest.NewRecorder()
   948  	obj, err := a.srv.CatalogNodeServices(resp, req)
   949  	assert.Nil(err)
   950  	assertIndex(t, resp)
   951  
   952  	ns := obj.(*structs.NodeServices)
   953  	assert.Len(ns.Services, 1)
   954  	v := ns.Services[args.Service.Service]
   955  	assert.Equal(structs.ServiceKindConnectProxy, v.Kind)
   956  }
   957  
   958  func TestCatalogNodeServices_WanTranslation(t *testing.T) {
   959  	t.Parallel()
   960  	a1 := NewTestAgent(t, t.Name(), `
   961  		datacenter = "dc1"
   962  		translate_wan_addrs = true
   963  		acl_datacenter = ""
   964  	`)
   965  	defer a1.Shutdown()
   966  	testrpc.WaitForTestAgent(t, a1.RPC, "dc1")
   967  
   968  	a2 := NewTestAgent(t, t.Name(), `
   969  		datacenter = "dc2"
   970  		translate_wan_addrs = true
   971  		acl_datacenter = ""
   972  	`)
   973  	defer a2.Shutdown()
   974  	testrpc.WaitForTestAgent(t, a2.RPC, "dc2")
   975  
   976  	// Wait for the WAN join.
   977  	addr := fmt.Sprintf("127.0.0.1:%d", a1.Config.SerfPortWAN)
   978  	if _, err := a2.srv.agent.JoinWAN([]string{addr}); err != nil {
   979  		t.Fatalf("err: %v", err)
   980  	}
   981  	retry.Run(t, func(r *retry.R) {
   982  		if got, want := len(a1.WANMembers()), 2; got < want {
   983  			r.Fatalf("got %d WAN members want at least %d", got, want)
   984  		}
   985  	})
   986  
   987  	// Register a node with DC2.
   988  	{
   989  		args := &structs.RegisterRequest{
   990  			Datacenter: "dc2",
   991  			Node:       "foo",
   992  			Address:    "127.0.0.1",
   993  			TaggedAddresses: map[string]string{
   994  				"wan": "127.0.0.2",
   995  			},
   996  			Service: &structs.NodeService{
   997  				Service: "http_wan_translation_test",
   998  			},
   999  		}
  1000  
  1001  		var out struct{}
  1002  		if err := a2.RPC("Catalog.Register", args, &out); err != nil {
  1003  			t.Fatalf("err: %v", err)
  1004  		}
  1005  	}
  1006  
  1007  	// Query for the node in DC2 from DC1.
  1008  	req, _ := http.NewRequest("GET", "/v1/catalog/node/foo?dc=dc2", nil)
  1009  	resp1 := httptest.NewRecorder()
  1010  	obj1, err1 := a1.srv.CatalogNodeServices(resp1, req)
  1011  	if err1 != nil {
  1012  		t.Fatalf("err: %v", err1)
  1013  	}
  1014  	assertIndex(t, resp1)
  1015  
  1016  	// Expect that DC1 gives us a WAN address (since the node is in DC2).
  1017  	services1 := obj1.(*structs.NodeServices)
  1018  	if len(services1.Services) != 1 {
  1019  		t.Fatalf("bad: %v", obj1)
  1020  	}
  1021  	service1 := services1.Node
  1022  	if service1.Address != "127.0.0.2" {
  1023  		t.Fatalf("bad: %v", service1)
  1024  	}
  1025  
  1026  	// Query DC2 from DC2.
  1027  	resp2 := httptest.NewRecorder()
  1028  	obj2, err2 := a2.srv.CatalogNodeServices(resp2, req)
  1029  	if err2 != nil {
  1030  		t.Fatalf("err: %v", err2)
  1031  	}
  1032  	assertIndex(t, resp2)
  1033  
  1034  	// Expect that DC2 gives us a private address (since the node is in DC2).
  1035  	services2 := obj2.(*structs.NodeServices)
  1036  	if len(services2.Services) != 1 {
  1037  		t.Fatalf("bad: %v", obj2)
  1038  	}
  1039  	service2 := services2.Node
  1040  	if service2.Address != "127.0.0.1" {
  1041  		t.Fatalf("bad: %v", service2)
  1042  	}
  1043  }