core: Fix detection of empty list/map defaults

This commit changes config parsing from weak decoding lists and maps
into []string and map[string]string respectively to decode into
[]interface{} and map[string]interface{} respectively. This is in order
to take advantage of the work integrated in #7082 to defeat the backward
compatibility features of the mapstructure library.

Test coverage of loading empty variables and validating their default
types against expectation.
This commit is contained in:
James Nugent 2016-06-12 11:19:03 +02:00
parent 3662bfa67a
commit 01cd596c60
3 changed files with 41 additions and 3 deletions

View File

@ -891,7 +891,8 @@ func (v *Variable) ValidateTypeAndDefault() error {
} }
if v.inferTypeFromDefault() != v.Type() { if v.inferTypeFromDefault() != v.Type() {
return fmt.Errorf("'%s' has a default value which is not of type '%s'", v.Name, v.DeclaredType) return fmt.Errorf("'%s' has a default value which is not of type '%s' (got '%s')",
v.Name, v.DeclaredType, v.inferTypeFromDefault().Printable())
} }
return nil return nil
@ -924,13 +925,13 @@ func (v *Variable) inferTypeFromDefault() VariableType {
return VariableTypeString return VariableTypeString
} }
var m map[string]string var m map[string]interface{}
if err := hilmapstructure.WeakDecode(v.Default, &m); err == nil { if err := hilmapstructure.WeakDecode(v.Default, &m); err == nil {
v.Default = m v.Default = m
return VariableTypeMap return VariableTypeMap
} }
var l []string var l []interface{}
if err := hilmapstructure.WeakDecode(v.Default, &l); err == nil { if err := hilmapstructure.WeakDecode(v.Default, &l); err == nil {
v.Default = l v.Default = l
return VariableTypeList return VariableTypeList

View File

@ -2,6 +2,7 @@ package config
import ( import (
"path/filepath" "path/filepath"
"reflect"
"strings" "strings"
"testing" "testing"
) )
@ -85,6 +86,31 @@ func TestConfigCount_var(t *testing.T) {
} }
} }
func TestConfig_emptyCollections(t *testing.T) {
c := testConfig(t, "empty-collections")
if len(c.Variables) != 3 {
t.Fatalf("bad: expected 3 variables, got %d", len(c.Variables))
}
for _, variable := range c.Variables {
switch variable.Name {
case "empty_string":
if variable.Default != "" {
t.Fatalf("bad: wrong default %q for variable empty_string", variable.Default)
}
case "empty_map":
if !reflect.DeepEqual(variable.Default, map[string]interface{}{}) {
t.Fatalf("bad: wrong default %#v for variable empty_map", variable.Default)
}
case "empty_list":
if !reflect.DeepEqual(variable.Default, []interface{}{}) {
t.Fatalf("bad: wrong default %#v for variable empty_list", variable.Default)
}
default:
t.Fatalf("Unexpected variable: %s", variable.Name)
}
}
}
func TestConfigValidate(t *testing.T) { func TestConfigValidate(t *testing.T) {
c := testConfig(t, "validate-good") c := testConfig(t, "validate-good")
if err := c.Validate(); err != nil { if err := c.Validate(); err != nil {

View File

@ -0,0 +1,11 @@
variable "empty_string" {
default = ""
}
variable "empty_list" {
default = []
}
variable "empty_map" {
default = {}
}