diff --git a/internal/manager/config/map.go b/internal/manager/config/map.go index b13cf73ac81..289e6e5dfbf 100644 --- a/internal/manager/config/map.go +++ b/internal/manager/config/map.go @@ -10,7 +10,7 @@ import ( // HACK: viper changes map keys to case insensitive values, so the workaround is to // convert the map to use snake-case keys -// toSnakeCase converts a string to snake_case +// toSnakeCase converts a string from camelCase to snake_case // NOTE: a double capital will be converted in a way that will yield a different result // when converted back to camel case. // For example: someIDs => some_ids => someIds @@ -30,6 +30,7 @@ func toSnakeCase(v string) string { return buf.String() } +// fromSnakeCase converts a string from snake_case to camelCase func fromSnakeCase(v string) string { var buf bytes.Buffer leadingUnderscore := true @@ -51,48 +52,31 @@ func fromSnakeCase(v string) string { return buf.String() } -// copyAndInsensitiviseMap behaves like insensitiviseMap, but creates a copy of -// any map it makes case insensitive. -func toSnakeCaseMap(m map[string]interface{}) map[string]interface{} { - nm := make(map[string]interface{}) - - for key, val := range m { - adjKey := toSnakeCase(key) - - switch v := val.(type) { - case map[string]interface{}: - nm[adjKey] = toSnakeCaseMap(v) - default: - nm[adjKey] = val - } - } - - return nm +// fromSnakeCaseMap recursively converts a map using snake_case keys to camelCase keys +func fromSnakeCaseMap(m map[string]interface{}) map[string]interface{} { + return fromSnakeCaseValue(m).(map[string]interface{}) } -// convertMapValue converts values into something that can be marshalled in JSON -// This means converting map[interface{}]interface{} to map[string]interface{} where ever -// encountered. -func convertMapValue(val interface{}) interface{} { +func fromSnakeCaseValue(val interface{}) interface{} { switch v := val.(type) { case map[interface{}]interface{}: ret := cast.ToStringMap(v) for k, vv := range ret { adjKey := fromSnakeCase(k) - ret[adjKey] = convertMapValue(vv) + ret[adjKey] = fromSnakeCaseValue(vv) } return ret case map[string]interface{}: ret := make(map[string]interface{}) for k, vv := range v { adjKey := fromSnakeCase(k) - ret[adjKey] = convertMapValue(vv) + ret[adjKey] = fromSnakeCaseValue(vv) } return ret case []interface{}: ret := make([]interface{}, len(v)) for i, vv := range v { - ret[i] = convertMapValue(vv) + ret[i] = fromSnakeCaseValue(vv) } return ret default: @@ -100,13 +84,34 @@ func convertMapValue(val interface{}) interface{} { } } -func fromSnakeCaseMap(m map[string]interface{}) map[string]interface{} { - nm := make(map[string]interface{}) +// toSnakeCaseMap recursively converts a map using camelCase keys to snake_case keys +func toSnakeCaseMap(m map[string]interface{}) map[string]interface{} { + return toSnakeCaseValue(m).(map[string]interface{}) +} - for key, val := range m { - adjKey := fromSnakeCase(key) - nm[adjKey] = convertMapValue(val) +func toSnakeCaseValue(val interface{}) interface{} { + switch v := val.(type) { + case map[interface{}]interface{}: + ret := cast.ToStringMap(v) + for k, vv := range ret { + adjKey := toSnakeCase(k) + ret[adjKey] = toSnakeCaseValue(vv) + } + return ret + case map[string]interface{}: + ret := make(map[string]interface{}) + for k, vv := range v { + adjKey := toSnakeCase(k) + ret[adjKey] = toSnakeCaseValue(vv) + } + return ret + case []interface{}: + ret := make([]interface{}, len(v)) + for i, vv := range v { + ret[i] = toSnakeCaseValue(vv) + } + return ret + default: + return v } - - return nm }