config: use the new HookTranslateKeys instead of lib.TranslateKeys

With the exception of CA provider config, which will be migrated at some
later time.
This commit is contained in:
Daniel Nephin 2020-05-27 14:42:01 -04:00
parent 644eb3b33a
commit 8f939da431
6 changed files with 58 additions and 106 deletions

View File

@ -6,6 +6,7 @@ import (
"strings"
"github.com/hashicorp/consul/lib"
"github.com/hashicorp/consul/lib/decode"
"github.com/hashicorp/go-multierror"
"github.com/hashicorp/hcl"
"github.com/mitchellh/mapstructure"
@ -108,32 +109,11 @@ func Parse(data string, format string) (c Config, keys []string, err error) {
"config_entries.bootstrap", // completely ignore this tree (fixed elsewhere)
})
// There is a difference of representation of some fields depending on
// where they are used. The HTTP API uses CamelCase whereas the config
// files use snake_case and between the two there is no automatic mapping.
// While the JSON and HCL parsers match keys without case (both `id` and
// `ID` are mapped to an ID field) the same thing does not happen between
// CamelCase and snake_case. Since changing either format would break
// existing setups we have to support both and slowly transition to one of
// the formats. Also, there is at least one case where we use the "wrong"
// key and want to map that to the new key to support deprecation -
// see [GH-3179]. TranslateKeys maps potentially CamelCased values to the
// snake_case that is used in the config file parser. If both the CamelCase
// and snake_case values are set the snake_case value is used and the other
// value is discarded.
lib.TranslateKeys(m, map[string]string{
"deregistercriticalserviceafter": "deregister_critical_service_after",
"dockercontainerid": "docker_container_id",
"scriptargs": "args",
"serviceid": "service_id",
"tlsskipverify": "tls_skip_verify",
"config_entries.bootstrap": "",
})
var md mapstructure.Metadata
d, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
Metadata: &md,
Result: &c,
DecodeHook: decode.HookTranslateKeys,
Metadata: &md,
Result: &c,
})
if err != nil {
return Config{}, nil, err

View File

@ -9,6 +9,7 @@ import (
cachetype "github.com/hashicorp/consul/agent/cache-types"
"github.com/hashicorp/consul/agent/structs"
"github.com/hashicorp/consul/lib"
"github.com/hashicorp/consul/lib/decode"
"github.com/mitchellh/mapstructure"
)
@ -105,15 +106,12 @@ func decodeDiscoveryChainReadRequest(raw map[string]interface{}) (*discoveryChai
// to do this part first.
raw = lib.PatchSliceOfMaps(raw, nil, nil)
lib.TranslateKeys(raw, map[string]string{
"override_mesh_gateway": "overridemeshgateway",
"override_protocol": "overrideprotocol",
"override_connect_timeout": "overrideconnecttimeout",
})
var apiReq discoveryChainReadRequest
decodeConf := &mapstructure.DecoderConfig{
DecodeHook: mapstructure.StringToTimeDurationHookFunc(),
DecodeHook: mapstructure.ComposeDecodeHookFunc(
decode.HookTranslateKeys,
mapstructure.StringToTimeDurationHookFunc(),
),
Result: &apiReq,
WeaklyTypedInput: true,
}

View File

@ -8,6 +8,7 @@ import (
"github.com/hashicorp/consul/acl"
"github.com/hashicorp/consul/agent/cache"
"github.com/hashicorp/consul/lib"
"github.com/hashicorp/consul/lib/decode"
"github.com/hashicorp/go-msgpack/codec"
"github.com/hashicorp/go-multierror"
"github.com/mitchellh/hashstructure"
@ -283,7 +284,7 @@ func DecodeConfigEntry(raw map[string]interface{}) (ConfigEntry, error) {
return nil, fmt.Errorf("Kind value in payload is not a string")
}
skipWhenPatching, translateKeysDict, err := ConfigEntryDecodeRulesForKind(entry.GetKind())
skipWhenPatching, err := ConfigEntryDecodeRulesForKind(entry.GetKind())
if err != nil {
return nil, err
}
@ -292,11 +293,12 @@ func DecodeConfigEntry(raw map[string]interface{}) (ConfigEntry, error) {
// to do this part first.
raw = lib.PatchSliceOfMaps(raw, skipWhenPatching, nil)
lib.TranslateKeys(raw, translateKeysDict)
var md mapstructure.Metadata
decodeConf := &mapstructure.DecoderConfig{
DecodeHook: mapstructure.StringToTimeDurationHookFunc(),
DecodeHook: mapstructure.ComposeDecodeHookFunc(
decode.HookTranslateKeys,
mapstructure.StringToTimeDurationHookFunc(),
),
Metadata: &md,
Result: &entry,
WeaklyTypedInput: true,
@ -327,80 +329,48 @@ func DecodeConfigEntry(raw map[string]interface{}) (ConfigEntry, error) {
// ConfigEntryDecodeRulesForKind returns rules for 'fixing' config entry key
// formats by kind. This is shared between the 'structs' and 'api' variations
// of config entries.
func ConfigEntryDecodeRulesForKind(kind string) (skipWhenPatching []string, translateKeysDict map[string]string, err error) {
func ConfigEntryDecodeRulesForKind(kind string) (skipWhenPatching []string, err error) {
switch kind {
case ProxyDefaults:
return []string{
"expose.paths",
"Expose.Paths",
}, map[string]string{
"local_path_port": "localpathport",
"listener_port": "listenerport",
"mesh_gateway": "meshgateway",
"config": "",
}, nil
"expose.paths",
"Expose.Paths",
}, nil
case ServiceDefaults:
return []string{
"expose.paths",
"Expose.Paths",
}, map[string]string{
"local_path_port": "localpathport",
"listener_port": "listenerport",
"mesh_gateway": "meshgateway",
"external_sni": "externalsni",
}, nil
"expose.paths",
"Expose.Paths",
}, nil
case ServiceRouter:
return []string{
"routes",
"Routes",
"routes.match.http.header",
"Routes.Match.HTTP.Header",
"routes.match.http.query_param",
"Routes.Match.HTTP.QueryParam",
}, map[string]string{
"num_retries": "numretries",
"path_exact": "pathexact",
"path_prefix": "pathprefix",
"path_regex": "pathregex",
"prefix_rewrite": "prefixrewrite",
"query_param": "queryparam",
"request_timeout": "requesttimeout",
"retry_on_connect_failure": "retryonconnectfailure",
"retry_on_status_codes": "retryonstatuscodes",
"service_subset": "servicesubset",
}, nil
"routes",
"Routes",
"routes.match.http.header",
"Routes.Match.HTTP.Header",
"routes.match.http.query_param",
"Routes.Match.HTTP.QueryParam",
}, nil
case ServiceSplitter:
return []string{
"splits",
"Splits",
}, map[string]string{
"service_subset": "servicesubset",
}, nil
case ServiceResolver:
return nil, map[string]string{
"connect_timeout": "connecttimeout",
"default_subset": "defaultsubset",
"only_passing": "onlypassing",
"service_subset": "servicesubset",
"splits",
"Splits",
}, nil
case ServiceResolver:
return nil, nil
case IngressGateway:
return []string{
"listeners",
"Listeners",
"listeners.services",
"Listeners.Services",
}, nil, nil
}, nil
case TerminatingGateway:
return []string{
"services",
"Services",
}, map[string]string{
"ca_file": "cafile",
"cert_file": "certfile",
"key_file": "keyfile",
}, nil
"services",
"Services",
}, nil
default:
return nil, nil, fmt.Errorf("kind %q should be explicitly handled here", kind)
return nil, fmt.Errorf("kind %q should be explicitly handled here", kind)
}
}

View File

@ -7,7 +7,7 @@ import (
envoycluster "github.com/envoyproxy/go-control-plane/envoy/api/v2/cluster"
"github.com/gogo/protobuf/types"
"github.com/hashicorp/consul/agent/structs"
"github.com/hashicorp/consul/lib"
"github.com/hashicorp/consul/lib/decode"
"github.com/mitchellh/mapstructure"
)
@ -97,15 +97,18 @@ type GatewayConfig struct {
// error occurs during parsing, it is returned along with the default config. This
// allows the caller to choose whether and how to report the error
func ParseGatewayConfig(m map[string]interface{}) (GatewayConfig, error) {
// Fixup for deprecated mesh gateway names
lib.TranslateKeys(m, map[string]string{
"envoy_mesh_gateway_bind_tagged_addresses": "envoy_gateway_bind_tagged_addresses",
"envoy_mesh_gateway_bind_addresses": "envoy_gateway_bind_addresses",
"envoy_mesh_gateway_no_default_bind": "envoy_gateway_no_default_bind",
})
var cfg GatewayConfig
err := mapstructure.WeakDecode(m, &cfg)
d, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
DecodeHook: decode.HookTranslateKeys,
Result: &cfg,
WeaklyTypedInput: true,
})
if err != nil {
return cfg, err
}
if err := d.Decode(m); err != nil {
return cfg, err
}
if cfg.ConnectTimeoutMs < 1 {
cfg.ConnectTimeoutMs = 5000

View File

@ -10,6 +10,7 @@ import (
"github.com/hashicorp/consul/command/flags"
"github.com/hashicorp/consul/command/helpers"
"github.com/hashicorp/consul/lib"
"github.com/hashicorp/consul/lib/decode"
"github.com/hashicorp/go-multierror"
"github.com/mitchellh/cli"
"github.com/mitchellh/mapstructure"
@ -132,7 +133,7 @@ func newDecodeConfigEntry(raw map[string]interface{}) (api.ConfigEntry, error) {
return nil, fmt.Errorf("Kind value in payload is not a string")
}
skipWhenPatching, translateKeysDict, err := structs.ConfigEntryDecodeRulesForKind(entry.GetKind())
skipWhenPatching, err := structs.ConfigEntryDecodeRulesForKind(entry.GetKind())
if err != nil {
return nil, err
}
@ -141,14 +142,12 @@ func newDecodeConfigEntry(raw map[string]interface{}) (api.ConfigEntry, error) {
// to do this part first.
raw = lib.PatchSliceOfMaps(raw, skipWhenPatching, nil)
// CamelCase is the canonical form for these, since this translation
// happens in the `consul config write` command and the JSON form is sent
// off to the server.
lib.TranslateKeys(raw, translateKeysDict)
var md mapstructure.Metadata
decodeConf := &mapstructure.DecoderConfig{
DecodeHook: mapstructure.StringToTimeDurationHookFunc(),
DecodeHook: mapstructure.ComposeDecodeHookFunc(
decode.HookTranslateKeys,
mapstructure.StringToTimeDurationHookFunc(),
),
Metadata: &md,
Result: &entry,
WeaklyTypedInput: true,

View File

@ -34,6 +34,8 @@ import (
// // item's config field
// "widgets.config": "",
// })
//
// Deprecated: Use lib/decode.HookTranslateKeys instead.
func TranslateKeys(v map[string]interface{}, dict map[string]string) {
// Convert all dict keys for exclusions to lower. so we can match against them
// unambiguously with a single lookup.