github.com/kjdelisle/consul@v1.4.5/connect/proxy/config_test.go (about)

     1  package proxy
     2  
     3  import (
     4  	"log"
     5  	"os"
     6  	"testing"
     7  	"time"
     8  
     9  	"github.com/stretchr/testify/assert"
    10  
    11  	"github.com/hashicorp/consul/agent"
    12  	"github.com/hashicorp/consul/api"
    13  	"github.com/hashicorp/consul/connect"
    14  	"github.com/stretchr/testify/require"
    15  )
    16  
    17  func TestUpstreamResolverFuncFromClient(t *testing.T) {
    18  	t.Parallel()
    19  
    20  	tests := []struct {
    21  		name string
    22  		cfg  UpstreamConfig
    23  		want *connect.ConsulResolver
    24  	}{
    25  		{
    26  			name: "service",
    27  			cfg: UpstreamConfig{
    28  				DestinationNamespace: "foo",
    29  				DestinationName:      "web",
    30  				Datacenter:           "ny1",
    31  				DestinationType:      "service",
    32  			},
    33  			want: &connect.ConsulResolver{
    34  				Namespace:  "foo",
    35  				Name:       "web",
    36  				Datacenter: "ny1",
    37  				Type:       connect.ConsulResolverTypeService,
    38  			},
    39  		},
    40  		{
    41  			name: "prepared_query",
    42  			cfg: UpstreamConfig{
    43  				DestinationNamespace: "foo",
    44  				DestinationName:      "web",
    45  				Datacenter:           "ny1",
    46  				DestinationType:      "prepared_query",
    47  			},
    48  			want: &connect.ConsulResolver{
    49  				Namespace:  "foo",
    50  				Name:       "web",
    51  				Datacenter: "ny1",
    52  				Type:       connect.ConsulResolverTypePreparedQuery,
    53  			},
    54  		},
    55  		{
    56  			name: "unknown behaves like service",
    57  			cfg: UpstreamConfig{
    58  				DestinationNamespace: "foo",
    59  				DestinationName:      "web",
    60  				Datacenter:           "ny1",
    61  				DestinationType:      "junk",
    62  			},
    63  			want: &connect.ConsulResolver{
    64  				Namespace:  "foo",
    65  				Name:       "web",
    66  				Datacenter: "ny1",
    67  				Type:       connect.ConsulResolverTypeService,
    68  			},
    69  		},
    70  	}
    71  	for _, tt := range tests {
    72  		t.Run(tt.name, func(t *testing.T) {
    73  			// Client doesn't really matter as long as it's passed through.
    74  			gotFn := UpstreamResolverFuncFromClient(nil)
    75  			got, err := gotFn(tt.cfg)
    76  			require.NoError(t, err)
    77  			require.Equal(t, tt.want, got)
    78  		})
    79  	}
    80  }
    81  
    82  func TestAgentConfigWatcherManagedProxy(t *testing.T) {
    83  	t.Parallel()
    84  
    85  	a := agent.NewTestAgent(t, "agent_smith", `
    86  	connect {
    87  		enabled = true
    88  		proxy {
    89  			allow_managed_api_registration = true
    90  		}
    91  	}
    92  	`)
    93  	defer a.Shutdown()
    94  
    95  	client := a.Client()
    96  	agent := client.Agent()
    97  
    98  	// Register a local agent service with a managed proxy
    99  	reg := &api.AgentServiceRegistration{
   100  		Name: "web",
   101  		Port: 8080,
   102  		Connect: &api.AgentServiceConnect{
   103  			Proxy: &api.AgentServiceConnectProxy{
   104  				Config: map[string]interface{}{
   105  					"bind_address":          "10.10.10.10",
   106  					"bind_port":             1010,
   107  					"local_service_address": "127.0.0.1:5000",
   108  					"handshake_timeout_ms":  999,
   109  				},
   110  				Upstreams: []api.Upstream{
   111  					{
   112  						DestinationName: "db",
   113  						LocalBindPort:   9191,
   114  					},
   115  				},
   116  			},
   117  		},
   118  	}
   119  	err := agent.ServiceRegister(reg)
   120  	require.NoError(t, err)
   121  
   122  	w, err := NewAgentConfigWatcher(client, "web-proxy",
   123  		log.New(os.Stderr, "", log.LstdFlags))
   124  	require.NoError(t, err)
   125  
   126  	cfg := testGetConfigValTimeout(t, w, 500*time.Millisecond)
   127  
   128  	expectCfg := &Config{
   129  		ProxiedServiceName:      "web",
   130  		ProxiedServiceNamespace: "default",
   131  		PublicListener: PublicListenerConfig{
   132  			BindAddress:           "10.10.10.10",
   133  			BindPort:              1010,
   134  			LocalServiceAddress:   "127.0.0.1:5000",
   135  			HandshakeTimeoutMs:    999,
   136  			LocalConnectTimeoutMs: 1000, // from applyDefaults
   137  		},
   138  		Upstreams: []UpstreamConfig{
   139  			{
   140  				DestinationName:      "db",
   141  				DestinationNamespace: "default",
   142  				DestinationType:      "service",
   143  				LocalBindPort:        9191,
   144  				LocalBindAddress:     "127.0.0.1",
   145  			},
   146  		},
   147  	}
   148  
   149  	assert.Equal(t, expectCfg, cfg)
   150  
   151  	// Now keep watching and update the config.
   152  	go func() {
   153  		// Wait for watcher to be watching
   154  		time.Sleep(20 * time.Millisecond)
   155  		reg.Connect.Proxy.Upstreams = append(reg.Connect.Proxy.Upstreams,
   156  			api.Upstream{
   157  				DestinationName:  "cache",
   158  				LocalBindPort:    9292,
   159  				LocalBindAddress: "127.10.10.10",
   160  			})
   161  		reg.Connect.Proxy.Config["local_connect_timeout_ms"] = 444
   162  		err := agent.ServiceRegister(reg)
   163  		require.NoError(t, err)
   164  	}()
   165  
   166  	cfg = testGetConfigValTimeout(t, w, 2*time.Second)
   167  
   168  	expectCfg.Upstreams = append(expectCfg.Upstreams, UpstreamConfig{
   169  		DestinationName:      "cache",
   170  		DestinationNamespace: "default",
   171  		DestinationType:      "service",
   172  		LocalBindPort:        9292,
   173  		LocalBindAddress:     "127.10.10.10",
   174  	})
   175  	expectCfg.PublicListener.LocalConnectTimeoutMs = 444
   176  
   177  	assert.Equal(t, expectCfg, cfg)
   178  }
   179  
   180  func TestAgentConfigWatcherSidecarProxy(t *testing.T) {
   181  	t.Parallel()
   182  
   183  	a := agent.NewTestAgent(t, "agent_smith", ``)
   184  	defer a.Shutdown()
   185  
   186  	client := a.Client()
   187  	agent := client.Agent()
   188  
   189  	// Register a local agent service with a managed proxy
   190  	reg := &api.AgentServiceRegistration{
   191  		Name: "web",
   192  		Port: 8080,
   193  		Connect: &api.AgentServiceConnect{
   194  			SidecarService: &api.AgentServiceRegistration{
   195  				Proxy: &api.AgentServiceConnectProxyConfig{
   196  					Config: map[string]interface{}{
   197  						"handshake_timeout_ms": 999,
   198  					},
   199  					Upstreams: []api.Upstream{
   200  						{
   201  							DestinationName: "db",
   202  							LocalBindPort:   9191,
   203  						},
   204  					},
   205  				},
   206  			},
   207  		},
   208  	}
   209  	err := agent.ServiceRegister(reg)
   210  	require.NoError(t, err)
   211  
   212  	w, err := NewAgentConfigWatcher(client, "web-sidecar-proxy",
   213  		log.New(os.Stderr, "", log.LstdFlags))
   214  	require.NoError(t, err)
   215  
   216  	cfg := testGetConfigValTimeout(t, w, 500*time.Millisecond)
   217  
   218  	expectCfg := &Config{
   219  		ProxiedServiceName:      "web",
   220  		ProxiedServiceNamespace: "default",
   221  		PublicListener: PublicListenerConfig{
   222  			BindAddress:           "0.0.0.0",
   223  			BindPort:              21000,
   224  			LocalServiceAddress:   "127.0.0.1:8080",
   225  			HandshakeTimeoutMs:    999,
   226  			LocalConnectTimeoutMs: 1000, // from applyDefaults
   227  		},
   228  		Upstreams: []UpstreamConfig{
   229  			{
   230  				DestinationName:      "db",
   231  				DestinationNamespace: "default",
   232  				DestinationType:      "service",
   233  				LocalBindPort:        9191,
   234  				LocalBindAddress:     "127.0.0.1",
   235  			},
   236  		},
   237  	}
   238  
   239  	require.Equal(t, expectCfg, cfg)
   240  
   241  	// Now keep watching and update the config.
   242  	go func() {
   243  		// Wait for watcher to be watching
   244  		time.Sleep(20 * time.Millisecond)
   245  		reg.Connect.SidecarService.Proxy.Upstreams = append(reg.Connect.SidecarService.Proxy.Upstreams,
   246  			api.Upstream{
   247  				DestinationName:  "cache",
   248  				LocalBindPort:    9292,
   249  				LocalBindAddress: "127.10.10.10",
   250  			})
   251  		reg.Connect.SidecarService.Proxy.Config["local_connect_timeout_ms"] = 444
   252  		err := agent.ServiceRegister(reg)
   253  		require.NoError(t, err)
   254  	}()
   255  
   256  	cfg = testGetConfigValTimeout(t, w, 2*time.Second)
   257  
   258  	expectCfg.Upstreams = append(expectCfg.Upstreams, UpstreamConfig{
   259  		DestinationName:      "cache",
   260  		DestinationNamespace: "default",
   261  		DestinationType:      "service",
   262  		LocalBindPort:        9292,
   263  		LocalBindAddress:     "127.10.10.10",
   264  	})
   265  	expectCfg.PublicListener.LocalConnectTimeoutMs = 444
   266  
   267  	assert.Equal(t, expectCfg, cfg)
   268  }
   269  
   270  func testGetConfigValTimeout(t *testing.T, w ConfigWatcher,
   271  	timeout time.Duration) *Config {
   272  	t.Helper()
   273  	select {
   274  	case cfg := <-w.Watch():
   275  		return cfg
   276  	case <-time.After(timeout):
   277  		t.Fatalf("timeout after %s waiting for config update", timeout)
   278  		return nil
   279  	}
   280  }