Fix proxy-defaults incorrectly merging config on upstreams. (#16021)
This commit is contained in:
parent
feacfb2886
commit
bb6951f99d
|
@ -33,7 +33,6 @@ func ComputeResolvedServiceConfig(
|
||||||
// blocking query, this function will be rerun and these state store lookups will both be current.
|
// blocking query, this function will be rerun and these state store lookups will both be current.
|
||||||
// We use the default enterprise meta to look up the global proxy defaults because they are not namespaced.
|
// We use the default enterprise meta to look up the global proxy defaults because they are not namespaced.
|
||||||
|
|
||||||
var proxyConfGlobalProtocol string
|
|
||||||
proxyConf := entries.GetProxyDefaults(args.PartitionOrDefault())
|
proxyConf := entries.GetProxyDefaults(args.PartitionOrDefault())
|
||||||
if proxyConf != nil {
|
if proxyConf != nil {
|
||||||
// Apply the proxy defaults to the sidecar's proxy config
|
// Apply the proxy defaults to the sidecar's proxy config
|
||||||
|
@ -50,21 +49,19 @@ func ComputeResolvedServiceConfig(
|
||||||
thisReply.EnvoyExtensions = proxyConf.EnvoyExtensions
|
thisReply.EnvoyExtensions = proxyConf.EnvoyExtensions
|
||||||
thisReply.AccessLogs = proxyConf.AccessLogs
|
thisReply.AccessLogs = proxyConf.AccessLogs
|
||||||
|
|
||||||
parsed, err := structs.ParseUpstreamConfigNoDefaults(mapCopy.(map[string]interface{}))
|
// Only MeshGateway and Protocol should affect upstreams.
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to parse upstream config map for proxy-defaults: %v", err)
|
|
||||||
}
|
|
||||||
proxyConfGlobalProtocol = parsed.Protocol
|
|
||||||
|
|
||||||
// MeshGateway is strange. It's marshaled into UpstreamConfigs via the arbitrary map, but it
|
// MeshGateway is strange. It's marshaled into UpstreamConfigs via the arbitrary map, but it
|
||||||
// uses concrete fields everywhere else. We always take the explicit definition here for
|
// uses concrete fields everywhere else. We always take the explicit definition here for
|
||||||
// wildcard upstreams and discard the user setting it via arbitrary map in proxy-defaults.
|
// wildcard upstreams and discard the user setting it via arbitrary map in proxy-defaults.
|
||||||
if err := mergo.MergeWithOverwrite(&wildcardUpstreamDefaults, mapCopy); err != nil {
|
if mgw, ok := thisReply.ProxyConfig["mesh_gateway"]; ok {
|
||||||
return nil, fmt.Errorf("failed to merge upstream config map for proxy-defaults: %v", err)
|
wildcardUpstreamDefaults["mesh_gateway"] = mgw
|
||||||
}
|
}
|
||||||
if !proxyConf.MeshGateway.IsZero() {
|
if !proxyConf.MeshGateway.IsZero() {
|
||||||
wildcardUpstreamDefaults["mesh_gateway"] = proxyConf.MeshGateway
|
wildcardUpstreamDefaults["mesh_gateway"] = proxyConf.MeshGateway
|
||||||
}
|
}
|
||||||
|
if protocol, ok := thisReply.ProxyConfig["protocol"]; ok {
|
||||||
|
wildcardUpstreamDefaults["protocol"] = protocol
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
serviceConf := entries.GetServiceDefaults(
|
serviceConf := entries.GetServiceDefaults(
|
||||||
|
@ -149,9 +146,7 @@ func ComputeResolvedServiceConfig(
|
||||||
|
|
||||||
// First store all upstreams that were provided in the request
|
// First store all upstreams that were provided in the request
|
||||||
for _, sid := range upstreamIDs {
|
for _, sid := range upstreamIDs {
|
||||||
if _, ok := seenUpstreams[sid]; !ok {
|
seenUpstreams[sid] = struct{}{}
|
||||||
seenUpstreams[sid] = struct{}{}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Then store upstreams inferred from service-defaults and mapify the overrides.
|
// Then store upstreams inferred from service-defaults and mapify the overrides.
|
||||||
|
@ -204,21 +199,19 @@ func ComputeResolvedServiceConfig(
|
||||||
// 2. Protocol for upstream service defined in its service-defaults (how the upstream wants to be addressed)
|
// 2. Protocol for upstream service defined in its service-defaults (how the upstream wants to be addressed)
|
||||||
// 3. Protocol defined for the upstream in the service-defaults.(upstream_config.defaults|upstream_config.overrides) of the downstream
|
// 3. Protocol defined for the upstream in the service-defaults.(upstream_config.defaults|upstream_config.overrides) of the downstream
|
||||||
// (how the downstream wants to address it)
|
// (how the downstream wants to address it)
|
||||||
protocol := proxyConfGlobalProtocol
|
if err := mergo.MergeWithOverwrite(&resolvedCfg, wildcardUpstreamDefaults); err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to merge wildcard defaults into upstream: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
upstreamSvcDefaults := entries.GetServiceDefaults(
|
upstreamSvcDefaults := entries.GetServiceDefaults(
|
||||||
structs.NewServiceID(upstream.ID, &upstream.EnterpriseMeta),
|
structs.NewServiceID(upstream.ID, &upstream.EnterpriseMeta),
|
||||||
)
|
)
|
||||||
if upstreamSvcDefaults != nil {
|
if upstreamSvcDefaults != nil {
|
||||||
if upstreamSvcDefaults.Protocol != "" {
|
if upstreamSvcDefaults.Protocol != "" {
|
||||||
protocol = upstreamSvcDefaults.Protocol
|
resolvedCfg["protocol"] = upstreamSvcDefaults.Protocol
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if protocol != "" {
|
|
||||||
resolvedCfg["protocol"] = protocol
|
|
||||||
}
|
|
||||||
|
|
||||||
// When dialing an upstream, the goal is to flatten the mesh gateway mode in this order
|
// When dialing an upstream, the goal is to flatten the mesh gateway mode in this order
|
||||||
// (larger number wins):
|
// (larger number wins):
|
||||||
// 1. Value from the proxy-defaults
|
// 1. Value from the proxy-defaults
|
||||||
|
|
|
@ -141,8 +141,10 @@ func Test_ComputeResolvedServiceConfig(t *testing.T) {
|
||||||
name: "proxy inherits kitchen sink from proxy-defaults",
|
name: "proxy inherits kitchen sink from proxy-defaults",
|
||||||
args: args{
|
args: args{
|
||||||
scReq: &structs.ServiceConfigRequest{
|
scReq: &structs.ServiceConfigRequest{
|
||||||
Name: "sid",
|
Name: "sid",
|
||||||
|
UpstreamIDs: uids,
|
||||||
},
|
},
|
||||||
|
upstreamIDs: uids,
|
||||||
entries: &ResolvedServiceConfigSet{
|
entries: &ResolvedServiceConfigSet{
|
||||||
ProxyDefaults: map[string]*structs.ProxyConfigEntry{
|
ProxyDefaults: map[string]*structs.ProxyConfigEntry{
|
||||||
acl.DefaultEnterpriseMeta().PartitionOrDefault(): {
|
acl.DefaultEnterpriseMeta().PartitionOrDefault(): {
|
||||||
|
@ -195,7 +197,12 @@ func Test_ComputeResolvedServiceConfig(t *testing.T) {
|
||||||
{
|
{
|
||||||
Upstream: wildcard,
|
Upstream: wildcard,
|
||||||
Config: map[string]interface{}{
|
Config: map[string]interface{}{
|
||||||
"foo": "bar",
|
"mesh_gateway": remoteMeshGW,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Upstream: uid,
|
||||||
|
Config: map[string]interface{}{
|
||||||
"mesh_gateway": remoteMeshGW,
|
"mesh_gateway": remoteMeshGW,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -1025,8 +1025,9 @@ func TestConfigEntry_ResolveServiceConfig(t *testing.T) {
|
||||||
// Create a dummy proxy/service config in the state store to look up.
|
// Create a dummy proxy/service config in the state store to look up.
|
||||||
state := s1.fsm.State()
|
state := s1.fsm.State()
|
||||||
require.NoError(t, state.EnsureConfigEntry(1, &structs.ProxyConfigEntry{
|
require.NoError(t, state.EnsureConfigEntry(1, &structs.ProxyConfigEntry{
|
||||||
Kind: structs.ProxyDefaults,
|
Kind: structs.ProxyDefaults,
|
||||||
Name: structs.ProxyConfigGlobal,
|
Name: structs.ProxyConfigGlobal,
|
||||||
|
MeshGateway: structs.MeshGatewayConfig{Mode: structs.MeshGatewayModeLocal},
|
||||||
Config: map[string]interface{}{
|
Config: map[string]interface{}{
|
||||||
"foo": 1,
|
"foo": 1,
|
||||||
},
|
},
|
||||||
|
@ -1056,12 +1057,25 @@ func TestConfigEntry_ResolveServiceConfig(t *testing.T) {
|
||||||
"foo": int64(1),
|
"foo": int64(1),
|
||||||
"protocol": "http",
|
"protocol": "http",
|
||||||
},
|
},
|
||||||
|
MeshGateway: structs.MeshGatewayConfig{
|
||||||
|
Mode: structs.MeshGatewayModeLocal,
|
||||||
|
},
|
||||||
UpstreamConfigs: map[string]map[string]interface{}{
|
UpstreamConfigs: map[string]map[string]interface{}{
|
||||||
"*": {
|
"*": {
|
||||||
"foo": int64(1),
|
"mesh_gateway": map[string]interface{}{
|
||||||
|
"Mode": "local",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
"bar": {
|
"bar": {
|
||||||
"protocol": "grpc",
|
"protocol": "grpc",
|
||||||
|
"mesh_gateway": map[string]interface{}{
|
||||||
|
"Mode": "local",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"baz": {
|
||||||
|
"mesh_gateway": map[string]interface{}{
|
||||||
|
"Mode": "local",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Meta: map[string]string{"foo": "bar"},
|
Meta: map[string]string{"foo": "bar"},
|
||||||
|
|
|
@ -11,7 +11,6 @@ import (
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"github.com/hashicorp/consul/acl"
|
|
||||||
"github.com/hashicorp/consul/agent/structs"
|
"github.com/hashicorp/consul/agent/structs"
|
||||||
"github.com/hashicorp/consul/sdk/testutil/retry"
|
"github.com/hashicorp/consul/sdk/testutil/retry"
|
||||||
"github.com/hashicorp/consul/testrpc"
|
"github.com/hashicorp/consul/testrpc"
|
||||||
|
@ -421,12 +420,6 @@ func TestServiceManager_PersistService_API(t *testing.T) {
|
||||||
"protocol": "http",
|
"protocol": "http",
|
||||||
},
|
},
|
||||||
UpstreamIDConfigs: structs.OpaqueUpstreamConfigs{
|
UpstreamIDConfigs: structs.OpaqueUpstreamConfigs{
|
||||||
{
|
|
||||||
Upstream: structs.NewServiceID(structs.WildcardSpecifier, acl.DefaultEnterpriseMeta().WithWildcardNamespace()),
|
|
||||||
Config: map[string]interface{}{
|
|
||||||
"foo": int64(1),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
Upstream: structs.NewServiceID("redis", nil),
|
Upstream: structs.NewServiceID("redis", nil),
|
||||||
Config: map[string]interface{}{
|
Config: map[string]interface{}{
|
||||||
|
@ -475,12 +468,6 @@ func TestServiceManager_PersistService_API(t *testing.T) {
|
||||||
"protocol": "http",
|
"protocol": "http",
|
||||||
},
|
},
|
||||||
UpstreamIDConfigs: structs.OpaqueUpstreamConfigs{
|
UpstreamIDConfigs: structs.OpaqueUpstreamConfigs{
|
||||||
{
|
|
||||||
Upstream: structs.NewServiceID(structs.WildcardSpecifier, acl.DefaultEnterpriseMeta().WithWildcardNamespace()),
|
|
||||||
Config: map[string]interface{}{
|
|
||||||
"foo": int64(1),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
Upstream: structs.NewServiceID("redis", nil),
|
Upstream: structs.NewServiceID("redis", nil),
|
||||||
Config: map[string]interface{}{
|
Config: map[string]interface{}{
|
||||||
|
@ -660,12 +647,6 @@ func TestServiceManager_PersistService_ConfigFiles(t *testing.T) {
|
||||||
"protocol": "http",
|
"protocol": "http",
|
||||||
},
|
},
|
||||||
UpstreamIDConfigs: structs.OpaqueUpstreamConfigs{
|
UpstreamIDConfigs: structs.OpaqueUpstreamConfigs{
|
||||||
{
|
|
||||||
Upstream: structs.NewServiceID(structs.WildcardSpecifier, acl.DefaultEnterpriseMeta().WithWildcardNamespace()),
|
|
||||||
Config: map[string]interface{}{
|
|
||||||
"foo": int64(1),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
Upstream: structs.NewServiceID("redis", nil),
|
Upstream: structs.NewServiceID("redis", nil),
|
||||||
Config: map[string]interface{}{
|
Config: map[string]interface{}{
|
||||||
|
|
Loading…
Reference in New Issue