From 7df846aa24c1be2758fde0fb3074ebc597759601 Mon Sep 17 00:00:00 2001 From: freddygv Date: Mon, 15 Mar 2021 14:32:13 -0600 Subject: [PATCH] Pass MeshGateway config in service config request ResolveServiceConfig is called by service manager before the proxy registration is in the catalog. Therefore we should pass proxy registration flags in the request rather than trying to fetch them from the state store (where they may not exist yet). --- agent/consul/config_endpoint.go | 36 +++++---------- agent/consul/config_endpoint_test.go | 65 ++++++++-------------------- agent/structs/config_entry.go | 5 ++- 3 files changed, 32 insertions(+), 74 deletions(-) diff --git a/agent/consul/config_endpoint.go b/agent/consul/config_endpoint.go index 8d49c111f3..9033b9f9f8 100644 --- a/agent/consul/config_endpoint.go +++ b/agent/consul/config_endpoint.go @@ -445,27 +445,6 @@ func (c *ConfigEntry) ResolveServiceConfig(args *structs.ServiceConfigRequest, r } } - // The goal is to flatten the mesh gateway mode in this order: - // 0. Value from centralized upstream_defaults - // 1. Value from local proxy registration - // 2. Value from centralized upstream_configs - // 3. Value from local upstream definition. This last step is done in the client's service manager. - var registrationMGConfig structs.MeshGatewayConfig - - if args.ID != "" && args.NodeName != "" { - index, registration, err := state.NodeServiceWatch(ws, args.NodeName, args.ID, &args.EnterpriseMeta) - if err != nil { - return fmt.Errorf("failed to query service registration") - } - if index > reply.Index { - reply.Index = index - } - - if registration != nil && !registration.Proxy.MeshGateway.IsZero() { - registrationMGConfig = registration.Proxy.MeshGateway - } - } - // usConfigs stores the opaque config map for each upstream and is keyed on the upstream's ID. usConfigs := make(map[structs.ServiceID]map[string]interface{}) @@ -500,10 +479,17 @@ func (c *ConfigEntry) ResolveServiceConfig(args *structs.ServiceConfigRequest, r if upstreamDefaults != nil { upstreamDefaults.MergeInto(resolvedCfg) } - // The value from the proxy registration overrides the one from upstream_defaults because - // it is specific to the proxy instance - if !registrationMGConfig.IsZero() { - resolvedCfg["mesh_gateway"] = registrationMGConfig + + // The MeshGateway value from the proxy registration overrides the one from upstream_defaults + // because it is specific to the proxy instance. + // + // The goal is to flatten the mesh gateway mode in this order: + // 0. Value from centralized upstream_defaults + // 1. Value from local proxy registration + // 2. Value from centralized upstream_configs + // 3. Value from local upstream definition. This last step is done in the client's service manager. + if !args.MeshGateway.IsZero() { + resolvedCfg["mesh_gateway"] = args.MeshGateway } if upstreamConfigs[upstream.String()] != nil { diff --git a/agent/consul/config_endpoint_test.go b/agent/consul/config_endpoint_test.go index 8f2bcf6aa7..04d7f7824f 100644 --- a/agent/consul/config_endpoint_test.go +++ b/agent/consul/config_endpoint_test.go @@ -930,8 +930,6 @@ func TestConfigEntry_ResolveServiceConfig_Upstreams(t *testing.T) { }, request: structs.ServiceConfigRequest{ Name: "foo", - ID: "foo-proxy-1", - NodeName: "foo-node", Datacenter: "dc1", Upstreams: []string{"zap"}, }, @@ -973,8 +971,6 @@ func TestConfigEntry_ResolveServiceConfig_Upstreams(t *testing.T) { }, request: structs.ServiceConfigRequest{ Name: "foo", - ID: "foo-proxy-1", - NodeName: "foo-node", Datacenter: "dc1", UpstreamIDs: []structs.ServiceID{{ID: "zap"}}, }, @@ -1019,17 +1015,13 @@ func TestConfigEntry_ResolveServiceConfig_Upstreams(t *testing.T) { }, request: structs.ServiceConfigRequest{ Name: "foo", - ID: "foo-proxy-1", - NodeName: "foo-node", Datacenter: "dc1", - UpstreamIDs: []structs.ServiceID{ - {ID: "zap"}, - }, - }, - proxyCfg: structs.ConnectProxyConfig{ MeshGateway: structs.MeshGatewayConfig{ Mode: structs.MeshGatewayModeNone, }, + UpstreamIDs: []structs.ServiceID{ + {ID: "zap"}, + }, }, expect: structs.ServiceConfigResponse{ UpstreamIDConfigs: structs.OpaqueUpstreamConfigs{ @@ -1085,17 +1077,13 @@ func TestConfigEntry_ResolveServiceConfig_Upstreams(t *testing.T) { }, request: structs.ServiceConfigRequest{ Name: "foo", - ID: "foo-proxy-1", - NodeName: "foo-node", Datacenter: "dc1", - UpstreamIDs: []structs.ServiceID{ - {ID: "zap"}, - }, - }, - proxyCfg: structs.ConnectProxyConfig{ MeshGateway: structs.MeshGatewayConfig{ Mode: structs.MeshGatewayModeNone, }, + UpstreamIDs: []structs.ServiceID{ + {ID: "zap"}, + }, }, expect: structs.ServiceConfigResponse{ ProxyConfig: map[string]interface{}{ @@ -1141,19 +1129,6 @@ func TestConfigEntry_ResolveServiceConfig_Upstreams(t *testing.T) { idx++ } - // The config endpoints pulls the proxy registration if a proxy ID is provided. - if tc.request.ID != "" { - require.NoError(t, state.EnsureNode(4, &structs.Node{ - ID: "9c6e733c-c39d-4555-8d41-0f174a31c489", - Node: tc.request.NodeName, - })) - require.NoError(t, state.EnsureService(5, tc.request.NodeName, &structs.NodeService{ - ID: tc.request.ID, - Service: tc.request.ID, - Proxy: tc.proxyCfg, - })) - } - var out structs.ServiceConfigResponse require.NoError(t, msgpackrpc.CallWithCodec(codec, "ConfigEntry.ResolveServiceConfig", &tc.request, &out)) @@ -1213,8 +1188,6 @@ func TestConfigEntry_ResolveServiceConfig_Upstreams_RegistrationBlocking(t *test args := structs.ServiceConfigRequest{ Name: "foo", - ID: "foo-proxy", - NodeName: nodeName, Datacenter: s1.config.Datacenter, Upstreams: []string{"bar", "baz"}, } @@ -1263,8 +1236,6 @@ func TestConfigEntry_ResolveServiceConfig_Upstreams_RegistrationBlocking(t *test require.NoError(t, msgpackrpc.CallWithCodec(codec, "ConfigEntry.ResolveServiceConfig", &structs.ServiceConfigRequest{ Name: "foo", - ID: "foo-proxy", - NodeName: nodeName, Datacenter: "dc1", Upstreams: []string{"bar", "baz"}, QueryOptions: structs.QueryOptions{ @@ -1343,7 +1314,8 @@ func TestConfigEntry_ResolveServiceConfig_Upstreams_DegistrationBlocking(t *test ID: "9c6e733c-c39d-4555-8d41-0f174a31c489", Node: nodeName, })) - require.NoError(t, state.EnsureService(5, nodeName, &structs.NodeService{ + + registration := structs.NodeService{ ID: "foo-proxy", Service: "foo-proxy", Proxy: structs.ConnectProxyConfig{ @@ -1351,14 +1323,14 @@ func TestConfigEntry_ResolveServiceConfig_Upstreams_DegistrationBlocking(t *test Mode: structs.MeshGatewayModeLocal, }, }, - })) + } + require.NoError(t, state.EnsureService(5, nodeName, ®istration)) args := structs.ServiceConfigRequest{ - Name: "foo", - ID: "foo-proxy", - NodeName: nodeName, - Datacenter: s1.config.Datacenter, - Upstreams: []string{"bar", "baz"}, + Name: "foo", + Datacenter: s1.config.Datacenter, + MeshGateway: registration.Proxy.MeshGateway, + Upstreams: []string{"bar", "baz"}, } var out structs.ServiceConfigResponse require.NoError(t, msgpackrpc.CallWithCodec(codec, "ConfigEntry.ResolveServiceConfig", &args, &out)) @@ -1400,11 +1372,10 @@ func TestConfigEntry_ResolveServiceConfig_Upstreams_DegistrationBlocking(t *test var out structs.ServiceConfigResponse require.NoError(t, msgpackrpc.CallWithCodec(codec, "ConfigEntry.ResolveServiceConfig", &structs.ServiceConfigRequest{ - Name: "foo", - ID: "foo-proxy", - NodeName: nodeName, - Datacenter: "dc1", - Upstreams: []string{"bar", "baz"}, + Name: "foo", + Datacenter: "dc1", + MeshGateway: registration.Proxy.MeshGateway, + Upstreams: []string{"bar", "baz"}, QueryOptions: structs.QueryOptions{ MinQueryIndex: index, MaxQueryTime: time.Second, diff --git a/agent/structs/config_entry.go b/agent/structs/config_entry.go index 79329aed82..44c924180b 100644 --- a/agent/structs/config_entry.go +++ b/agent/structs/config_entry.go @@ -578,10 +578,11 @@ func (r *ConfigEntryListAllRequest) RequestDatacenter() string { // for a service. type ServiceConfigRequest struct { Name string - ID string - NodeName string Datacenter string + // MeshGateway contains the mesh gateway configuration from the requesting proxy's registration + MeshGateway MeshGatewayConfig + UpstreamIDs []ServiceID // DEPRECATED