github.com/adityamillind98/nomad@v0.11.8/command/agent/consul/connect_test.go (about)

     1  package consul
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/hashicorp/consul/api"
     7  	"github.com/hashicorp/nomad/nomad/structs"
     8  	"github.com/stretchr/testify/require"
     9  )
    10  
    11  var (
    12  	testConnectNetwork = structs.Networks{{
    13  		Mode:   "bridge",
    14  		Device: "eth0",
    15  		IP:     "192.168.30.1",
    16  		DynamicPorts: []structs.Port{
    17  			{Label: "healthPort", Value: 23100, To: 23100},
    18  			{Label: "metricsPort", Value: 23200, To: 23200},
    19  			{Label: "connect-proxy-redis", Value: 3000, To: 3000},
    20  		},
    21  	}}
    22  )
    23  
    24  func TestConnect_newConnect(t *testing.T) {
    25  	t.Parallel()
    26  
    27  	t.Run("nil", func(t *testing.T) {
    28  		asr, err := newConnect("", nil, nil)
    29  		require.NoError(t, err)
    30  		require.Nil(t, asr)
    31  	})
    32  
    33  	t.Run("native", func(t *testing.T) {
    34  		asr, err := newConnect("", &structs.ConsulConnect{
    35  			Native: true,
    36  		}, nil)
    37  		require.NoError(t, err)
    38  		require.True(t, asr.Native)
    39  		require.Nil(t, asr.SidecarService)
    40  	})
    41  
    42  	t.Run("with sidecar", func(t *testing.T) {
    43  		asr, err := newConnect("redis", &structs.ConsulConnect{
    44  			Native: false,
    45  			SidecarService: &structs.ConsulSidecarService{
    46  				Tags: []string{"foo", "bar"},
    47  				Port: "sidecarPort",
    48  			},
    49  		}, testConnectNetwork)
    50  		require.NoError(t, err)
    51  		require.Equal(t, &api.AgentServiceRegistration{
    52  			Tags:    []string{"foo", "bar"},
    53  			Port:    3000,
    54  			Address: "192.168.30.1",
    55  			Proxy: &api.AgentServiceConnectProxyConfig{
    56  				Config: map[string]interface{}{
    57  					"bind_address": "0.0.0.0",
    58  					"bind_port":    3000,
    59  				},
    60  			},
    61  		}, asr.SidecarService)
    62  	})
    63  }
    64  
    65  func TestConnect_connectSidecarRegistration(t *testing.T) {
    66  	t.Parallel()
    67  
    68  	t.Run("nil", func(t *testing.T) {
    69  		sidecarReg, err := connectSidecarRegistration("", nil, testConnectNetwork)
    70  		require.NoError(t, err)
    71  		require.Nil(t, sidecarReg)
    72  	})
    73  
    74  	t.Run("no service port", func(t *testing.T) {
    75  		_, err := connectSidecarRegistration("unknown", &structs.ConsulSidecarService{
    76  			// irrelevant
    77  		}, testConnectNetwork)
    78  		require.EqualError(t, err, `No Connect port defined for service "unknown"`)
    79  	})
    80  
    81  	t.Run("bad proxy", func(t *testing.T) {
    82  		_, err := connectSidecarRegistration("redis", &structs.ConsulSidecarService{
    83  			Proxy: &structs.ConsulProxy{
    84  				Expose: &structs.ConsulExposeConfig{
    85  					Paths: []structs.ConsulExposePath{{
    86  						ListenerPort: "badPort",
    87  					}},
    88  				},
    89  			},
    90  		}, testConnectNetwork)
    91  		require.EqualError(t, err, `No port of label "badPort" defined`)
    92  	})
    93  
    94  	t.Run("normal", func(t *testing.T) {
    95  		proxy, err := connectSidecarRegistration("redis", &structs.ConsulSidecarService{
    96  			Tags: []string{"foo", "bar"},
    97  			Port: "sidecarPort",
    98  		}, testConnectNetwork)
    99  		require.NoError(t, err)
   100  		require.Equal(t, &api.AgentServiceRegistration{
   101  			Tags:    []string{"foo", "bar"},
   102  			Port:    3000,
   103  			Address: "192.168.30.1",
   104  			Proxy: &api.AgentServiceConnectProxyConfig{
   105  				Config: map[string]interface{}{
   106  					"bind_address": "0.0.0.0",
   107  					"bind_port":    3000,
   108  				},
   109  			},
   110  		}, proxy)
   111  	})
   112  }
   113  
   114  func TestConnect_connectProxy(t *testing.T) {
   115  	t.Parallel()
   116  
   117  	// If the input proxy is nil, we expect the output to be a proxy with its
   118  	// config set to default values.
   119  	t.Run("nil proxy", func(t *testing.T) {
   120  		proxy, err := connectProxy(nil, 2000, testConnectNetwork)
   121  		require.NoError(t, err)
   122  		require.Equal(t, &api.AgentServiceConnectProxyConfig{
   123  			LocalServiceAddress: "",
   124  			LocalServicePort:    0,
   125  			Upstreams:           nil,
   126  			Expose:              api.ExposeConfig{},
   127  			Config: map[string]interface{}{
   128  				"bind_address": "0.0.0.0",
   129  				"bind_port":    2000,
   130  			},
   131  		}, proxy)
   132  	})
   133  
   134  	t.Run("bad proxy", func(t *testing.T) {
   135  		_, err := connectProxy(&structs.ConsulProxy{
   136  			LocalServiceAddress: "0.0.0.0",
   137  			LocalServicePort:    2000,
   138  			Upstreams:           nil,
   139  			Expose: &structs.ConsulExposeConfig{
   140  				Paths: []structs.ConsulExposePath{{
   141  					ListenerPort: "badPort",
   142  				}},
   143  			},
   144  			Config: nil,
   145  		}, 2000, testConnectNetwork)
   146  		require.EqualError(t, err, `No port of label "badPort" defined`)
   147  	})
   148  
   149  	t.Run("normal", func(t *testing.T) {
   150  		proxy, err := connectProxy(&structs.ConsulProxy{
   151  			LocalServiceAddress: "0.0.0.0",
   152  			LocalServicePort:    2000,
   153  			Upstreams:           nil,
   154  			Expose: &structs.ConsulExposeConfig{
   155  				Paths: []structs.ConsulExposePath{{
   156  					Path:          "/health",
   157  					Protocol:      "http",
   158  					LocalPathPort: 8000,
   159  					ListenerPort:  "healthPort",
   160  				}},
   161  			},
   162  			Config: nil,
   163  		}, 2000, testConnectNetwork)
   164  		require.NoError(t, err)
   165  		require.Equal(t, &api.AgentServiceConnectProxyConfig{
   166  			LocalServiceAddress: "0.0.0.0",
   167  			LocalServicePort:    2000,
   168  			Upstreams:           nil,
   169  			Expose: api.ExposeConfig{
   170  				Paths: []api.ExposePath{{
   171  					Path:          "/health",
   172  					Protocol:      "http",
   173  					LocalPathPort: 8000,
   174  					ListenerPort:  23100,
   175  				}},
   176  			},
   177  			Config: map[string]interface{}{
   178  				"bind_address": "0.0.0.0",
   179  				"bind_port":    2000,
   180  			},
   181  		}, proxy)
   182  	})
   183  }
   184  
   185  func TestConnect_connectProxyExpose(t *testing.T) {
   186  	t.Parallel()
   187  
   188  	t.Run("nil", func(t *testing.T) {
   189  		exposeConfig, err := connectProxyExpose(nil, nil)
   190  		require.NoError(t, err)
   191  		require.Equal(t, api.ExposeConfig{}, exposeConfig)
   192  	})
   193  
   194  	t.Run("bad port", func(t *testing.T) {
   195  		_, err := connectProxyExpose(&structs.ConsulExposeConfig{
   196  			Paths: []structs.ConsulExposePath{{
   197  				ListenerPort: "badPort",
   198  			}},
   199  		}, testConnectNetwork)
   200  		require.EqualError(t, err, `No port of label "badPort" defined`)
   201  	})
   202  
   203  	t.Run("normal", func(t *testing.T) {
   204  		expose, err := connectProxyExpose(&structs.ConsulExposeConfig{
   205  			Paths: []structs.ConsulExposePath{{
   206  				Path:          "/health",
   207  				Protocol:      "http",
   208  				LocalPathPort: 8000,
   209  				ListenerPort:  "healthPort",
   210  			}},
   211  		}, testConnectNetwork)
   212  		require.NoError(t, err)
   213  		require.Equal(t, api.ExposeConfig{
   214  			Checks: false,
   215  			Paths: []api.ExposePath{{
   216  				Path:            "/health",
   217  				ListenerPort:    23100,
   218  				LocalPathPort:   8000,
   219  				Protocol:        "http",
   220  				ParsedFromCheck: false,
   221  			}},
   222  		}, expose)
   223  	})
   224  }
   225  
   226  func TestConnect_connectProxyExposePaths(t *testing.T) {
   227  	t.Parallel()
   228  
   229  	t.Run("nil", func(t *testing.T) {
   230  		upstreams, err := connectProxyExposePaths(nil, nil)
   231  		require.NoError(t, err)
   232  		require.Empty(t, upstreams)
   233  	})
   234  
   235  	t.Run("no network", func(t *testing.T) {
   236  		original := []structs.ConsulExposePath{{Path: "/path"}}
   237  		_, err := connectProxyExposePaths(original, nil)
   238  		require.EqualError(t, err, `Connect only supported with exactly 1 network (found 0)`)
   239  	})
   240  
   241  	t.Run("normal", func(t *testing.T) {
   242  		original := []structs.ConsulExposePath{{
   243  			Path:          "/health",
   244  			Protocol:      "http",
   245  			LocalPathPort: 8000,
   246  			ListenerPort:  "healthPort",
   247  		}, {
   248  			Path:          "/metrics",
   249  			Protocol:      "grpc",
   250  			LocalPathPort: 9500,
   251  			ListenerPort:  "metricsPort",
   252  		}}
   253  		exposePaths, err := connectProxyExposePaths(original, testConnectNetwork)
   254  		require.NoError(t, err)
   255  		require.Equal(t, []api.ExposePath{
   256  			{
   257  				Path:            "/health",
   258  				Protocol:        "http",
   259  				LocalPathPort:   8000,
   260  				ListenerPort:    23100,
   261  				ParsedFromCheck: false,
   262  			},
   263  			{
   264  				Path:            "/metrics",
   265  				Protocol:        "grpc",
   266  				LocalPathPort:   9500,
   267  				ListenerPort:    23200,
   268  				ParsedFromCheck: false,
   269  			},
   270  		}, exposePaths)
   271  	})
   272  }
   273  
   274  func TestConnect_connectUpstreams(t *testing.T) {
   275  	t.Parallel()
   276  
   277  	t.Run("nil", func(t *testing.T) {
   278  		require.Nil(t, connectUpstreams(nil))
   279  	})
   280  
   281  	t.Run("not empty", func(t *testing.T) {
   282  		require.Equal(t,
   283  			[]api.Upstream{{
   284  				DestinationName: "foo",
   285  				LocalBindPort:   8000,
   286  			}, {
   287  				DestinationName: "bar",
   288  				LocalBindPort:   9000,
   289  			}},
   290  			connectUpstreams([]structs.ConsulUpstream{{
   291  				DestinationName: "foo",
   292  				LocalBindPort:   8000,
   293  			}, {
   294  				DestinationName: "bar",
   295  				LocalBindPort:   9000,
   296  			}}),
   297  		)
   298  	})
   299  }
   300  
   301  func TestConnect_connectProxyConfig(t *testing.T) {
   302  	t.Parallel()
   303  
   304  	t.Run("nil map", func(t *testing.T) {
   305  		require.Equal(t, map[string]interface{}{
   306  			"bind_address": "0.0.0.0",
   307  			"bind_port":    42,
   308  		}, connectProxyConfig(nil, 42))
   309  	})
   310  
   311  	t.Run("pre-existing map", func(t *testing.T) {
   312  		require.Equal(t, map[string]interface{}{
   313  			"bind_address": "0.0.0.0",
   314  			"bind_port":    42,
   315  			"foo":          "bar",
   316  		}, connectProxyConfig(map[string]interface{}{
   317  			"foo": "bar",
   318  		}, 42))
   319  	})
   320  }
   321  
   322  func TestConnect_getConnectPort(t *testing.T) {
   323  	t.Parallel()
   324  
   325  	networks := structs.Networks{{
   326  		IP: "192.168.30.1",
   327  		DynamicPorts: []structs.Port{{
   328  			Label: "connect-proxy-foo",
   329  			Value: 23456,
   330  			To:    23456,
   331  		}}}}
   332  
   333  	t.Run("normal", func(t *testing.T) {
   334  		nr, port, err := connectPort("foo", networks)
   335  		require.NoError(t, err)
   336  		require.Equal(t, structs.Port{
   337  			Label: "connect-proxy-foo",
   338  			Value: 23456,
   339  			To:    23456,
   340  		}, port)
   341  		require.Equal(t, "192.168.30.1", nr.IP)
   342  	})
   343  
   344  	t.Run("no such service", func(t *testing.T) {
   345  		_, _, err := connectPort("other", networks)
   346  		require.EqualError(t, err, `No Connect port defined for service "other"`)
   347  	})
   348  
   349  	t.Run("no network", func(t *testing.T) {
   350  		_, _, err := connectPort("foo", nil)
   351  		require.EqualError(t, err, "Connect only supported with exactly 1 network (found 0)")
   352  	})
   353  
   354  	t.Run("multi network", func(t *testing.T) {
   355  		_, _, err := connectPort("foo", append(networks, &structs.NetworkResource{
   356  			Device: "eth1",
   357  			IP:     "10.0.10.0",
   358  		}))
   359  		require.EqualError(t, err, "Connect only supported with exactly 1 network (found 2)")
   360  	})
   361  }
   362  
   363  func TestConnect_getExposePathPort(t *testing.T) {
   364  	t.Parallel()
   365  
   366  	networks := structs.Networks{{
   367  		Device: "eth0",
   368  		IP:     "192.168.30.1",
   369  		DynamicPorts: []structs.Port{{
   370  			Label: "myPort",
   371  			Value: 23456,
   372  			To:    23456,
   373  		}}}}
   374  
   375  	t.Run("normal", func(t *testing.T) {
   376  		ip, port, err := connectExposePathPort("myPort", networks)
   377  		require.NoError(t, err)
   378  		require.Equal(t, ip, "192.168.30.1")
   379  		require.Equal(t, 23456, port)
   380  	})
   381  
   382  	t.Run("no such port label", func(t *testing.T) {
   383  		_, _, err := connectExposePathPort("otherPort", networks)
   384  		require.EqualError(t, err, `No port of label "otherPort" defined`)
   385  	})
   386  
   387  	t.Run("no network", func(t *testing.T) {
   388  		_, _, err := connectExposePathPort("myPort", nil)
   389  		require.EqualError(t, err, "Connect only supported with exactly 1 network (found 0)")
   390  	})
   391  
   392  	t.Run("multi network", func(t *testing.T) {
   393  		_, _, err := connectExposePathPort("myPort", append(networks, &structs.NetworkResource{
   394  			Device: "eth1",
   395  			IP:     "10.0.10.0",
   396  		}))
   397  		require.EqualError(t, err, "Connect only supported with exactly 1 network (found 2)")
   398  	})
   399  }