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).
This commit is contained in:
freddygv 2021-03-15 14:32:13 -06:00
parent d90240d367
commit 04fbc104cd
3 changed files with 32 additions and 74 deletions

View File

@ -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 stores the opaque config map for each upstream and is keyed on the upstream's ID.
usConfigs := make(map[structs.ServiceID]map[string]interface{}) usConfigs := make(map[structs.ServiceID]map[string]interface{})
@ -500,10 +479,17 @@ func (c *ConfigEntry) ResolveServiceConfig(args *structs.ServiceConfigRequest, r
if upstreamDefaults != nil { if upstreamDefaults != nil {
upstreamDefaults.MergeInto(resolvedCfg) upstreamDefaults.MergeInto(resolvedCfg)
} }
// The value from the proxy registration overrides the one from upstream_defaults because
// it is specific to the proxy instance // The MeshGateway value from the proxy registration overrides the one from upstream_defaults
if !registrationMGConfig.IsZero() { // because it is specific to the proxy instance.
resolvedCfg["mesh_gateway"] = registrationMGConfig //
// 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 { if upstreamConfigs[upstream.String()] != nil {

View File

@ -930,8 +930,6 @@ func TestConfigEntry_ResolveServiceConfig_Upstreams(t *testing.T) {
}, },
request: structs.ServiceConfigRequest{ request: structs.ServiceConfigRequest{
Name: "foo", Name: "foo",
ID: "foo-proxy-1",
NodeName: "foo-node",
Datacenter: "dc1", Datacenter: "dc1",
Upstreams: []string{"zap"}, Upstreams: []string{"zap"},
}, },
@ -973,8 +971,6 @@ func TestConfigEntry_ResolveServiceConfig_Upstreams(t *testing.T) {
}, },
request: structs.ServiceConfigRequest{ request: structs.ServiceConfigRequest{
Name: "foo", Name: "foo",
ID: "foo-proxy-1",
NodeName: "foo-node",
Datacenter: "dc1", Datacenter: "dc1",
UpstreamIDs: []structs.ServiceID{{ID: "zap"}}, UpstreamIDs: []structs.ServiceID{{ID: "zap"}},
}, },
@ -1019,17 +1015,13 @@ func TestConfigEntry_ResolveServiceConfig_Upstreams(t *testing.T) {
}, },
request: structs.ServiceConfigRequest{ request: structs.ServiceConfigRequest{
Name: "foo", Name: "foo",
ID: "foo-proxy-1",
NodeName: "foo-node",
Datacenter: "dc1", Datacenter: "dc1",
UpstreamIDs: []structs.ServiceID{
{ID: "zap"},
},
},
proxyCfg: structs.ConnectProxyConfig{
MeshGateway: structs.MeshGatewayConfig{ MeshGateway: structs.MeshGatewayConfig{
Mode: structs.MeshGatewayModeNone, Mode: structs.MeshGatewayModeNone,
}, },
UpstreamIDs: []structs.ServiceID{
{ID: "zap"},
},
}, },
expect: structs.ServiceConfigResponse{ expect: structs.ServiceConfigResponse{
UpstreamIDConfigs: structs.OpaqueUpstreamConfigs{ UpstreamIDConfigs: structs.OpaqueUpstreamConfigs{
@ -1085,17 +1077,13 @@ func TestConfigEntry_ResolveServiceConfig_Upstreams(t *testing.T) {
}, },
request: structs.ServiceConfigRequest{ request: structs.ServiceConfigRequest{
Name: "foo", Name: "foo",
ID: "foo-proxy-1",
NodeName: "foo-node",
Datacenter: "dc1", Datacenter: "dc1",
UpstreamIDs: []structs.ServiceID{
{ID: "zap"},
},
},
proxyCfg: structs.ConnectProxyConfig{
MeshGateway: structs.MeshGatewayConfig{ MeshGateway: structs.MeshGatewayConfig{
Mode: structs.MeshGatewayModeNone, Mode: structs.MeshGatewayModeNone,
}, },
UpstreamIDs: []structs.ServiceID{
{ID: "zap"},
},
}, },
expect: structs.ServiceConfigResponse{ expect: structs.ServiceConfigResponse{
ProxyConfig: map[string]interface{}{ ProxyConfig: map[string]interface{}{
@ -1141,19 +1129,6 @@ func TestConfigEntry_ResolveServiceConfig_Upstreams(t *testing.T) {
idx++ 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 var out structs.ServiceConfigResponse
require.NoError(t, msgpackrpc.CallWithCodec(codec, "ConfigEntry.ResolveServiceConfig", &tc.request, &out)) 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{ args := structs.ServiceConfigRequest{
Name: "foo", Name: "foo",
ID: "foo-proxy",
NodeName: nodeName,
Datacenter: s1.config.Datacenter, Datacenter: s1.config.Datacenter,
Upstreams: []string{"bar", "baz"}, Upstreams: []string{"bar", "baz"},
} }
@ -1263,8 +1236,6 @@ func TestConfigEntry_ResolveServiceConfig_Upstreams_RegistrationBlocking(t *test
require.NoError(t, msgpackrpc.CallWithCodec(codec, "ConfigEntry.ResolveServiceConfig", require.NoError(t, msgpackrpc.CallWithCodec(codec, "ConfigEntry.ResolveServiceConfig",
&structs.ServiceConfigRequest{ &structs.ServiceConfigRequest{
Name: "foo", Name: "foo",
ID: "foo-proxy",
NodeName: nodeName,
Datacenter: "dc1", Datacenter: "dc1",
Upstreams: []string{"bar", "baz"}, Upstreams: []string{"bar", "baz"},
QueryOptions: structs.QueryOptions{ QueryOptions: structs.QueryOptions{
@ -1343,7 +1314,8 @@ func TestConfigEntry_ResolveServiceConfig_Upstreams_DegistrationBlocking(t *test
ID: "9c6e733c-c39d-4555-8d41-0f174a31c489", ID: "9c6e733c-c39d-4555-8d41-0f174a31c489",
Node: nodeName, Node: nodeName,
})) }))
require.NoError(t, state.EnsureService(5, nodeName, &structs.NodeService{
registration := structs.NodeService{
ID: "foo-proxy", ID: "foo-proxy",
Service: "foo-proxy", Service: "foo-proxy",
Proxy: structs.ConnectProxyConfig{ Proxy: structs.ConnectProxyConfig{
@ -1351,14 +1323,14 @@ func TestConfigEntry_ResolveServiceConfig_Upstreams_DegistrationBlocking(t *test
Mode: structs.MeshGatewayModeLocal, Mode: structs.MeshGatewayModeLocal,
}, },
}, },
})) }
require.NoError(t, state.EnsureService(5, nodeName, &registration))
args := structs.ServiceConfigRequest{ args := structs.ServiceConfigRequest{
Name: "foo", Name: "foo",
ID: "foo-proxy", Datacenter: s1.config.Datacenter,
NodeName: nodeName, MeshGateway: registration.Proxy.MeshGateway,
Datacenter: s1.config.Datacenter, Upstreams: []string{"bar", "baz"},
Upstreams: []string{"bar", "baz"},
} }
var out structs.ServiceConfigResponse var out structs.ServiceConfigResponse
require.NoError(t, msgpackrpc.CallWithCodec(codec, "ConfigEntry.ResolveServiceConfig", &args, &out)) 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 var out structs.ServiceConfigResponse
require.NoError(t, msgpackrpc.CallWithCodec(codec, "ConfigEntry.ResolveServiceConfig", require.NoError(t, msgpackrpc.CallWithCodec(codec, "ConfigEntry.ResolveServiceConfig",
&structs.ServiceConfigRequest{ &structs.ServiceConfigRequest{
Name: "foo", Name: "foo",
ID: "foo-proxy", Datacenter: "dc1",
NodeName: nodeName, MeshGateway: registration.Proxy.MeshGateway,
Datacenter: "dc1", Upstreams: []string{"bar", "baz"},
Upstreams: []string{"bar", "baz"},
QueryOptions: structs.QueryOptions{ QueryOptions: structs.QueryOptions{
MinQueryIndex: index, MinQueryIndex: index,
MaxQueryTime: time.Second, MaxQueryTime: time.Second,

View File

@ -578,10 +578,11 @@ func (r *ConfigEntryListAllRequest) RequestDatacenter() string {
// for a service. // for a service.
type ServiceConfigRequest struct { type ServiceConfigRequest struct {
Name string Name string
ID string
NodeName string
Datacenter string Datacenter string
// MeshGateway contains the mesh gateway configuration from the requesting proxy's registration
MeshGateway MeshGatewayConfig
UpstreamIDs []ServiceID UpstreamIDs []ServiceID
// DEPRECATED // DEPRECATED