From fab39ed336d0c7675f9124f4c821d1dab2f85f96 Mon Sep 17 00:00:00 2001 From: Derek Menteer Date: Fri, 16 Sep 2022 08:54:04 -0500 Subject: [PATCH] Various fixes and unit tests. --- agent/configentry/resolve.go | 42 +++--- agent/configentry/resolve_test.go | 20 +++ agent/xds/config_test.go | 2 +- agent/xds/listeners_test.go | 16 +++ ...-balance-inbound-connections.latest.golden | 122 ++++++++++++++++++ ...tbound-connections-bind-port.latest.golden | 122 ++++++++++++++++++ api/config_entry_test.go | 14 +- 7 files changed, 310 insertions(+), 28 deletions(-) create mode 100644 agent/xds/testdata/listeners/listener-balance-inbound-connections.latest.golden create mode 100644 agent/xds/testdata/listeners/listener-balance-outbound-connections-bind-port.latest.golden diff --git a/agent/configentry/resolve.go b/agent/configentry/resolve.go index ee9f4da56e0e..e3f7e54fbec9 100644 --- a/agent/configentry/resolve.go +++ b/agent/configentry/resolve.go @@ -53,15 +53,7 @@ func ComputeResolvedServiceConfig( structs.NewServiceID(args.Name, &args.EnterpriseMeta), ) if serviceConf != nil { - if thisReply.ProxyConfig == nil { - thisReply.ProxyConfig = make(map[string]interface{}) - } - if serviceConf.Protocol != "" { - thisReply.ProxyConfig["protocol"] = serviceConf.Protocol - } - if serviceConf.BalanceInboundConnections != "" { - thisReply.ProxyConfig["balance_inbound_connections"] = serviceConf.BalanceInboundConnections - } + if serviceConf.Expose.Checks { thisReply.Expose.Checks = true } @@ -84,25 +76,29 @@ func ComputeResolvedServiceConfig( thisReply.Destination = *serviceConf.Destination } + // Populate values for the proxy config map + proxyConf := thisReply.ProxyConfig + if proxyConf == nil { + proxyConf = make(map[string]interface{}) + } + if serviceConf.Protocol != "" { + proxyConf["protocol"] = serviceConf.Protocol + } + if serviceConf.BalanceInboundConnections != "" { + proxyConf["balance_inbound_connections"] = serviceConf.BalanceInboundConnections + } if serviceConf.MaxInboundConnections > 0 { - if thisReply.ProxyConfig == nil { - thisReply.ProxyConfig = map[string]interface{}{} - } - thisReply.ProxyConfig["max_inbound_connections"] = serviceConf.MaxInboundConnections + proxyConf["max_inbound_connections"] = serviceConf.MaxInboundConnections } - if serviceConf.LocalConnectTimeoutMs > 0 { - if thisReply.ProxyConfig == nil { - thisReply.ProxyConfig = map[string]interface{}{} - } - thisReply.ProxyConfig["local_connect_timeout_ms"] = serviceConf.LocalConnectTimeoutMs + proxyConf["local_connect_timeout_ms"] = serviceConf.LocalConnectTimeoutMs } - if serviceConf.LocalRequestTimeoutMs > 0 { - if thisReply.ProxyConfig == nil { - thisReply.ProxyConfig = map[string]interface{}{} - } - thisReply.ProxyConfig["local_request_timeout_ms"] = serviceConf.LocalRequestTimeoutMs + proxyConf["local_request_timeout_ms"] = serviceConf.LocalRequestTimeoutMs + } + // Add the proxy conf to the response if any fields were populated + if len(proxyConf) > 0 { + thisReply.ProxyConfig = proxyConf } thisReply.Meta = serviceConf.Meta diff --git a/agent/configentry/resolve_test.go b/agent/configentry/resolve_test.go index 301472c1c519..a023dca40007 100644 --- a/agent/configentry/resolve_test.go +++ b/agent/configentry/resolve_test.go @@ -24,6 +24,26 @@ func Test_ComputeResolvedServiceConfig(t *testing.T) { args args want *structs.ServiceConfigResponse }{ + { + name: "proxy with balanceinboundconnections", + args: args{ + scReq: &structs.ServiceConfigRequest{ + Name: "sid", + }, + entries: &ResolvedServiceConfigSet{ + ServiceDefaults: map[structs.ServiceID]*structs.ServiceConfigEntry{ + sid: { + BalanceInboundConnections: "exact_balance", + }, + }, + }, + }, + want: &structs.ServiceConfigResponse{ + ProxyConfig: map[string]interface{}{ + "balance_inbound_connections": "exact_balance", + }, + }, + }, { name: "proxy with maxinboundsconnections", args: args{ diff --git a/agent/xds/config_test.go b/agent/xds/config_test.go index 780c96c65820..574449f1eeb8 100644 --- a/agent/xds/config_test.go +++ b/agent/xds/config_test.go @@ -158,7 +158,7 @@ func TestParseProxyConfig(t *testing.T) { }, }, { - name: "balance inbound connections override, bool", + name: "balance inbound connections override, string", input: map[string]interface{}{ "balance_inbound_connections": "exact_balance", }, diff --git a/agent/xds/listeners_test.go b/agent/xds/listeners_test.go index 1112222f3fc2..39ac2eac08fe 100644 --- a/agent/xds/listeners_test.go +++ b/agent/xds/listeners_test.go @@ -160,6 +160,22 @@ func TestListenersFromSnapshot(t *testing.T) { }, nil) }, }, + { + name: "listener-balance-inbound-connections", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { + ns.Proxy.Config["balance_inbound_connections"] = "exact_balance" + }, nil) + }, + }, + { + name: "listener-balance-outbound-connections-bind-port", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { + ns.Proxy.Upstreams[0].Config["balance_outbound_connections"] = "exact_balance" + }, nil) + }, + }, { name: "http-public-listener", create: func(t testinf.T) *proxycfg.ConfigSnapshot { diff --git a/agent/xds/testdata/listeners/listener-balance-inbound-connections.latest.golden b/agent/xds/testdata/listeners/listener-balance-inbound-connections.latest.golden new file mode 100644 index 000000000000..9c8b0a581714 --- /dev/null +++ b/agent/xds/testdata/listeners/listener-balance-inbound-connections.latest.golden @@ -0,0 +1,122 @@ +{ + "versionInfo": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "name": "db:127.0.0.1:9191", + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 9191 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "statPrefix": "upstream.db.default.default.dc1", + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ], + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "name": "prepared_query:geo-cache:127.10.10.10:8181", + "address": { + "socketAddress": { + "address": "127.10.10.10", + "portValue": 8181 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "statPrefix": "upstream.prepared_query_geo-cache", + "cluster": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ], + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "name": "public_listener:0.0.0.0:9999", + "address": { + "socketAddress": { + "address": "0.0.0.0", + "portValue": 9999 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": { + + }, + "statPrefix": "connect_authz" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "statPrefix": "public_listener", + "cluster": "local_app" + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsParams": { + + }, + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + } + ], + "trafficDirection": "INBOUND", + "connectionBalanceConfig": { + "exactBalance": {} + } + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "nonce": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/listeners/listener-balance-outbound-connections-bind-port.latest.golden b/agent/xds/testdata/listeners/listener-balance-outbound-connections-bind-port.latest.golden new file mode 100644 index 000000000000..1181ff019d8a --- /dev/null +++ b/agent/xds/testdata/listeners/listener-balance-outbound-connections-bind-port.latest.golden @@ -0,0 +1,122 @@ +{ + "versionInfo": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "name": "db:127.0.0.1:9191", + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 9191 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "statPrefix": "upstream.db.default.default.dc1", + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ], + "trafficDirection": "OUTBOUND", + "connectionBalanceConfig": { + "exactBalance": {} + } + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "name": "prepared_query:geo-cache:127.10.10.10:8181", + "address": { + "socketAddress": { + "address": "127.10.10.10", + "portValue": 8181 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "statPrefix": "upstream.prepared_query_geo-cache", + "cluster": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ], + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "name": "public_listener:0.0.0.0:9999", + "address": { + "socketAddress": { + "address": "0.0.0.0", + "portValue": 9999 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": { + + }, + "statPrefix": "connect_authz" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "statPrefix": "public_listener", + "cluster": "local_app" + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsParams": { + + }, + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + } + ], + "trafficDirection": "INBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "nonce": "00000001" +} \ No newline at end of file diff --git a/api/config_entry_test.go b/api/config_entry_test.go index 1502111d8308..376ad6182aed 100644 --- a/api/config_entry_test.go +++ b/api/config_entry_test.go @@ -104,9 +104,10 @@ func TestAPI_ConfigEntries(t *testing.T) { "foo": "bar", "gir": "zim", }, - MaxInboundConnections: 5, - LocalConnectTimeoutMs: 5000, - LocalRequestTimeoutMs: 7000, + MaxInboundConnections: 5, + BalanceInboundConnections: "exact_balance", + LocalConnectTimeoutMs: 5000, + LocalRequestTimeoutMs: 7000, } dest := &DestinationConfig{ @@ -148,6 +149,7 @@ func TestAPI_ConfigEntries(t *testing.T) { require.Equal(t, service.Meta, readService.Meta) require.Equal(t, service.Meta, readService.GetMeta()) require.Equal(t, service.MaxInboundConnections, readService.MaxInboundConnections) + require.Equal(t, service.BalanceInboundConnections, readService.BalanceInboundConnections) require.Equal(t, service.LocalConnectTimeoutMs, readService.LocalConnectTimeoutMs) require.Equal(t, service.LocalRequestTimeoutMs, readService.LocalRequestTimeoutMs) @@ -446,6 +448,7 @@ func TestDecodeConfigEntry(t *testing.T) { "OutboundListenerPort": 808, "DialedDirectly": true }, + "BalanceInboundConnections": "exact_balance", "UpstreamConfig": { "Overrides": [ { @@ -454,7 +457,8 @@ func TestDecodeConfigEntry(t *testing.T) { "MaxFailures": 3, "Interval": "2s", "EnforcingConsecutive5xx": 60 - } + }, + "BalanceOutboundConnections": "exact_balance" }, { "Name": "finance--billing", @@ -498,6 +502,7 @@ func TestDecodeConfigEntry(t *testing.T) { OutboundListenerPort: 808, DialedDirectly: true, }, + BalanceInboundConnections: "exact_balance", UpstreamConfig: &UpstreamConfiguration{ Overrides: []*UpstreamConfig{ { @@ -507,6 +512,7 @@ func TestDecodeConfigEntry(t *testing.T) { Interval: 2 * time.Second, EnforcingConsecutive5xx: uint32Pointer(60), }, + BalanceOutboundConnections: "exact_balance", }, { Name: "finance--billing",