diff --git a/config/interpolate_funcs.go b/config/interpolate_funcs.go index a91fb3fd7..c48152648 100644 --- a/config/interpolate_funcs.go +++ b/config/interpolate_funcs.go @@ -240,12 +240,18 @@ func interpolationFuncConcat() ast.Function { // Otherwise variables if argument, ok := arg.([]ast.Variable); ok { for _, element := range argument { - finalListElements = append(finalListElements, element.Value.(string)) + t := element.Type + switch t { + case ast.TypeString: + finalListElements = append(finalListElements, element.Value.(string)) + default: + return nil, fmt.Errorf("concat() does not support lists of %s", t.Printable()) + } } continue } - return nil, fmt.Errorf("arguments to concat() must be a string or list") + return nil, fmt.Errorf("arguments to concat() must be a string or list of strings") } return stringSliceToVariableValue(finalListElements), nil diff --git a/config/interpolate_funcs_test.go b/config/interpolate_funcs_test.go index 3b2ea17cf..f4c527ebf 100644 --- a/config/interpolate_funcs_test.go +++ b/config/interpolate_funcs_test.go @@ -5,6 +5,7 @@ import ( "io/ioutil" "os" "reflect" + "strings" "testing" "github.com/hashicorp/hil" @@ -226,6 +227,40 @@ func TestInterpolateFuncConcat(t *testing.T) { }) } +// TODO: This test is split out and calls a private function +// because there's no good way to get a list of maps into the unit +// tests due to GH-7142 - once lists of maps can be expressed properly as +// literals this unit test can be wrapped back into the suite above. +// +// Reproduces crash reported in GH-7030. +func TestInterpolationFuncConcatListOfMaps(t *testing.T) { + listOfMapsOne := ast.Variable{ + Type: ast.TypeList, + Value: []ast.Variable{ + { + Type: ast.TypeMap, + Value: map[string]interface{}{"one": "foo"}, + }, + }, + } + listOfMapsTwo := ast.Variable{ + Type: ast.TypeList, + Value: []ast.Variable{ + { + Type: ast.TypeMap, + Value: map[string]interface{}{"two": "bar"}, + }, + }, + } + args := []interface{}{listOfMapsOne.Value, listOfMapsTwo.Value} + + _, err := interpolationFuncConcat().Callback(args) + + if err == nil || !strings.Contains(err.Error(), "concat() does not support lists of type map") { + t.Fatalf("Expected err, got: %v", err) + } +} + func TestInterpolateFuncFile(t *testing.T) { tf, err := ioutil.TempFile("", "tf") if err != nil {