fallback to proxy config global protocol when upstream services' protocol is unset (#6277)

fallback to proxy config global protocol when upstream services' protocol is unset

Fixes #5857
This commit is contained in:
Sarah Adams 2019-08-05 12:52:35 -07:00 committed by GitHub
parent f834854f8a
commit 9ed3e64510
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 86 additions and 2 deletions

View File

@ -274,6 +274,12 @@ func (c *ConfigEntry) ResolveServiceConfig(args *structs.ServiceConfigRequest, r
reply.ProxyConfig["protocol"] = serviceConf.Protocol reply.ProxyConfig["protocol"] = serviceConf.Protocol
} }
// Extract the global protocol from proxyConf for upstream configs.
var proxyConfGlobalProtocol interface{}
if proxyConf != nil && proxyConf.Config != nil {
proxyConfGlobalProtocol = proxyConf.Config["protocol"]
}
// Apply the upstream protocols to the upstream configs // Apply the upstream protocols to the upstream configs
for _, upstream := range args.Upstreams { for _, upstream := range args.Upstreams {
_, upstreamEntry, err := state.ConfigEntry(ws, structs.ServiceDefaults, upstream) _, upstreamEntry, err := state.ConfigEntry(ws, structs.ServiceDefaults, upstream)
@ -289,8 +295,19 @@ func (c *ConfigEntry) ResolveServiceConfig(args *structs.ServiceConfigRequest, r
} }
} }
// No upstream found; skip.
if upstreamConf == nil {
continue
}
// Fallback to proxyConf global protocol.
protocol := proxyConfGlobalProtocol
if upstreamConf.Protocol != "" {
protocol = upstreamConf.Protocol
}
// Nothing to configure if a protocol hasn't been set. // Nothing to configure if a protocol hasn't been set.
if upstreamConf == nil || upstreamConf.Protocol == "" { if protocol == nil {
continue continue
} }
@ -298,7 +315,7 @@ func (c *ConfigEntry) ResolveServiceConfig(args *structs.ServiceConfigRequest, r
reply.UpstreamConfigs = make(map[string]map[string]interface{}) reply.UpstreamConfigs = make(map[string]map[string]interface{})
} }
reply.UpstreamConfigs[upstream] = map[string]interface{}{ reply.UpstreamConfigs[upstream] = map[string]interface{}{
"protocol": upstreamConf.Protocol, "protocol": protocol,
} }
} }

View File

@ -704,6 +704,73 @@ func TestConfigEntry_ResolveServiceConfig(t *testing.T) {
require.Equal(map[string]interface{}{"foo": 1}, proxyConf.Config) require.Equal(map[string]interface{}{"foo": 1}, proxyConf.Config)
} }
func TestConfigEntry_ResolveServiceConfig_UpstreamProxyDefaultsProtocol(t *testing.T) {
t.Parallel()
require := require.New(t)
dir1, s1 := testServer(t)
defer os.RemoveAll(dir1)
defer s1.Shutdown()
codec := rpcClient(t, s1)
defer codec.Close()
// Create a dummy proxy/service config in the state store to look up.
state := s1.fsm.State()
require.NoError(state.EnsureConfigEntry(1, &structs.ProxyConfigEntry{
Kind: structs.ProxyDefaults,
Name: structs.ProxyConfigGlobal,
Config: map[string]interface{}{
"protocol": "http",
},
}))
require.NoError(state.EnsureConfigEntry(2, &structs.ServiceConfigEntry{
Kind: structs.ServiceDefaults,
Name: "foo",
}))
require.NoError(state.EnsureConfigEntry(2, &structs.ServiceConfigEntry{
Kind: structs.ServiceDefaults,
Name: "bar",
}))
require.NoError(state.EnsureConfigEntry(2, &structs.ServiceConfigEntry{
Kind: structs.ServiceDefaults,
Name: "other",
}))
require.NoError(state.EnsureConfigEntry(2, &structs.ServiceConfigEntry{
Kind: structs.ServiceDefaults,
Name: "alreadyprotocol",
Protocol: "grpc",
}))
args := structs.ServiceConfigRequest{
Name: "foo",
Datacenter: s1.config.Datacenter,
Upstreams: []string{"bar", "other", "alreadyprotocol", "dne"},
}
var out structs.ServiceConfigResponse
require.NoError(msgpackrpc.CallWithCodec(codec, "ConfigEntry.ResolveServiceConfig", &args, &out))
expected := structs.ServiceConfigResponse{
ProxyConfig: map[string]interface{}{
"protocol": "http",
},
UpstreamConfigs: map[string]map[string]interface{}{
"bar": map[string]interface{}{
"protocol": "http",
},
"other": map[string]interface{}{
"protocol": "http",
},
"alreadyprotocol": map[string]interface{}{
"protocol": "grpc",
},
},
// Don't know what this is deterministically
QueryMeta: out.QueryMeta,
}
require.Equal(expected, out)
}
func TestConfigEntry_ResolveServiceConfigNoConfig(t *testing.T) { func TestConfigEntry_ResolveServiceConfigNoConfig(t *testing.T) {
t.Parallel() t.Parallel()