command: more resilient HCL check for inputs
This commit is contained in:
parent
30ea22c252
commit
0a2b5de67f
|
@ -129,6 +129,14 @@ func (v *FlagStringSlice) Set(raw string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
// This regular expression is how we check if a value for a variable
|
||||||
|
// matches what we'd expect a rich HCL value to be. For example: {
|
||||||
|
// definitely signals a map. If a value DOESN'T match this, we return
|
||||||
|
// it as a raw string.
|
||||||
|
varFlagHCLRe = regexp.MustCompile(`^["\[\{]`)
|
||||||
|
)
|
||||||
|
|
||||||
// parseVarFlagAsHCL parses the value of a single variable as would have been specified
|
// parseVarFlagAsHCL parses the value of a single variable as would have been specified
|
||||||
// on the command line via -var or in an environment variable named TF_VAR_x, where x is
|
// on the command line via -var or in an environment variable named TF_VAR_x, where x is
|
||||||
// the name of the variable. In order to get around the restriction of HCL requiring a
|
// the name of the variable. In order to get around the restriction of HCL requiring a
|
||||||
|
@ -143,13 +151,23 @@ func parseVarFlagAsHCL(input string) (string, interface{}, error) {
|
||||||
|
|
||||||
parsed, err := hcl.Parse(input)
|
parsed, err := hcl.Parse(input)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
value := input[idx+1:]
|
||||||
|
|
||||||
|
// If it didn't parse as HCL, we check if it doesn't match our
|
||||||
|
// whitelist of TF-accepted HCL types for inputs. If not, then
|
||||||
|
// we let it through as a raw string.
|
||||||
|
trimmed := strings.TrimSpace(value)
|
||||||
|
if !varFlagHCLRe.MatchString(trimmed) {
|
||||||
|
return probablyName, value, nil
|
||||||
|
}
|
||||||
|
|
||||||
// This covers flags of the form `foo=bar` which is not valid HCL
|
// This covers flags of the form `foo=bar` which is not valid HCL
|
||||||
// At this point, probablyName is actually the name, and the remainder
|
// At this point, probablyName is actually the name, and the remainder
|
||||||
// of the expression after the equals sign is the value.
|
// of the expression after the equals sign is the value.
|
||||||
if regexp.MustCompile(`Unknown token: \d+:\d+ IDENT`).Match([]byte(err.Error())) {
|
if regexp.MustCompile(`Unknown token: \d+:\d+ IDENT`).Match([]byte(err.Error())) {
|
||||||
value := input[idx+1:]
|
|
||||||
return probablyName, value, nil
|
return probablyName, value, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return "", nil, fmt.Errorf("Cannot parse value for variable %s (%q) as valid HCL: %s", probablyName, input, err)
|
return "", nil, fmt.Errorf("Cannot parse value for variable %s (%q) as valid HCL: %s", probablyName, input, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,6 +47,12 @@ func TestFlagStringKV(t *testing.T) {
|
||||||
nil,
|
nil,
|
||||||
true,
|
true,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"key=/path",
|
||||||
|
map[string]string{"key": "/path"},
|
||||||
|
false,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range cases {
|
for _, tc := range cases {
|
||||||
|
@ -127,6 +133,21 @@ func TestFlagTypedKV(t *testing.T) {
|
||||||
nil,
|
nil,
|
||||||
true,
|
true,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
TODO: wait for HCL merge
|
||||||
|
{
|
||||||
|
"key=/path",
|
||||||
|
map[string]interface{}{"key": "/path"},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
*/
|
||||||
|
|
||||||
|
{
|
||||||
|
"key=1234.dkr.ecr.us-east-1.amazonaws.com/proj:abcdef",
|
||||||
|
map[string]interface{}{"key": "1234.dkr.ecr.us-east-1.amazonaws.com/proj:abcdef"},
|
||||||
|
false,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range cases {
|
for _, tc := range cases {
|
||||||
|
|
Loading…
Reference in New Issue