From 5e88f02fd81eed61b295d1e4b53507b3da7fede3 Mon Sep 17 00:00:00 2001 From: Ben Whaley Date: Thu, 29 Oct 2020 21:43:25 -0700 Subject: [PATCH] Swap for Convert func --- config/config.go | 5 +-- variables/variables.go | 4 +-- variables/yaml_helpers.go | 29 +++++++++++++--- variables/yaml_mapstr.go | 71 --------------------------------------- 4 files changed, 29 insertions(+), 80 deletions(-) delete mode 100644 variables/yaml_mapstr.go diff --git a/config/config.go b/config/config.go index 20d729d3..eefffda2 100644 --- a/config/config.go +++ b/config/config.go @@ -5,12 +5,11 @@ import ( "io/ioutil" "path" - "gopkg.in/yaml.v2" - "github.com/gruntwork-io/boilerplate/errors" "github.com/gruntwork-io/boilerplate/options" "github.com/gruntwork-io/boilerplate/util" "github.com/gruntwork-io/boilerplate/variables" + "gopkg.in/yaml.v2" ) const BOILERPLATE_CONFIG_FILE = "boilerplate.yml" @@ -92,6 +91,8 @@ func ParseBoilerplateConfig(configContents []byte) (*BoilerplateConfig, error) { return nil, errors.WithStackTrace(err) } + boilerplateConfig = variables.Convert(boilerplateConfig).(*BoilerplateConfig) + return boilerplateConfig, nil } diff --git a/variables/variables.go b/variables/variables.go index 00003f68..4d0935c0 100644 --- a/variables/variables.go +++ b/variables/variables.go @@ -26,7 +26,7 @@ type Variable interface { // The type of the variable Type() BoilerplateType - // The default value for teh variable, if any + // The default value for the variable, if any Default() interface{} // The name of another variable from which this variable should take its value @@ -234,7 +234,7 @@ func ConvertType(value interface{}, variable Variable) (interface{}, error) { } case Map: if reflect.TypeOf(value).Kind() == reflect.Map { - return value, nil + return Convert(value), nil } if isString { return parseStringAsMap(asString) diff --git a/variables/yaml_helpers.go b/variables/yaml_helpers.go index 8155fa95..a5036407 100644 --- a/variables/yaml_helpers.go +++ b/variables/yaml_helpers.go @@ -6,10 +6,9 @@ import ( "reflect" "strings" - "gopkg.in/yaml.v2" - "github.com/gruntwork-io/boilerplate/errors" "github.com/gruntwork-io/boilerplate/util" + "gopkg.in/yaml.v2" ) // Given a map of key:value pairs read from a Boilerplate YAML config file of the format: @@ -283,6 +282,8 @@ func ParseYamlString(str string) (interface{}, error) { return nil, errors.WithStackTrace(err) } + parsedValue = Convert(parsedValue) + return parsedValue, nil } @@ -317,12 +318,11 @@ func ParseVariablesFromVarFile(varFilePath string) (map[string]interface{}, erro func parseVariablesFromVarFileContents(varFileContents []byte) (map[string]interface{}, error) { vars := make(map[string]interface{}) - // Use a custom unmarshaller to work around the issue described in https://github.com/go-yaml/yaml/issues/139 - if err := UnmarshalYaml(varFileContents, &vars); err != nil { + if err := yaml.Unmarshal(varFileContents, &vars); err != nil { return vars, err } - return vars, nil + return Convert(vars).(map[string]interface{}), nil } // Parse variables passed in via command line options, either as a list of NAME=VALUE variable pairs in varsList, or a @@ -344,6 +344,25 @@ func ParseVars(varsList []string, varFileList []string) (map[string]interface{}, return util.MergeMaps(varsFromVarsList, varsFromVarFiles), nil } +// Convert converts i of type map[interface{}]interface{} to a map[string]interface{} so that it may be properly +// marshalled in to JSON. +// See: https://github.com/go-yaml/yaml/issues/139 +func Convert(i interface{}) interface{} { + switch x := i.(type) { + case map[interface{}]interface{}: + m2 := map[string]interface{}{} + for k, v := range x { + m2[k.(string)] = Convert(v) + } + return m2 + case []interface{}: + for i, v := range x { + x[i] = Convert(v) + } + } + return i +} + // Custom error types type OptionsMissing string diff --git a/variables/yaml_mapstr.go b/variables/yaml_mapstr.go deleted file mode 100644 index 27559f92..00000000 --- a/variables/yaml_mapstr.go +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright (c) 2015-2016 Michael Persson -// Copyright (c) 2012–2015 Elasticsearch -// -// Originally distributed as part of "beats" repository (https://github.com/elastic/beats). -// -// Modified for use with Gruntwork Boilerplate -// -// Distributed underneath "Apache License, Version 2.0" which is compatible with the LICENSE for this package. -// -// This is included as a workaround for the following issue in the go-yaml package: -// https://github.com/go-yaml/yaml/issues/139 -// Based off the code here: -// https://github.com/go-yaml/yaml/issues/139#issuecomment-220072190 - -package variables - -import ( - // Base packages. - "fmt" - - // Third party packages. - "gopkg.in/yaml.v2" -) - -// Unmarshal YAML to map[string]interface{} instead of map[interface{}]interface{}. -func UnmarshalYaml(in []byte, out interface{}) error { - res := make(map[string]interface{}) - - if err := yaml.Unmarshal(in, &res); err != nil { - return err - } - - for k, v := range res { - res[k] = cleanupMapValue(v) - } - *out.(*map[string]interface{}) = res - - return nil -} - -// Marshal YAML wrapper function. -func Marshal(in interface{}) ([]byte, error) { - return yaml.Marshal(in) -} - -func cleanupInterfaceArray(in []interface{}) []interface{} { - res := make([]interface{}, len(in)) - for i, v := range in { - res[i] = cleanupMapValue(v) - } - return res -} - -func cleanupInterfaceMap(in map[interface{}]interface{}) map[string]interface{} { - res := make(map[string]interface{}) - for k, v := range in { - res[fmt.Sprintf("%v", k)] = cleanupMapValue(v) - } - return res -} - -func cleanupMapValue(v interface{}) interface{} { - switch v := v.(type) { - case []interface{}: - return cleanupInterfaceArray(v) - case map[interface{}]interface{}: - return cleanupInterfaceMap(v) - default: - return v - } -}