diff --git a/config/config.go b/config/config.go index be4bf00f52..adacf5ec91 100644 --- a/config/config.go +++ b/config/config.go @@ -6,7 +6,9 @@ import ( "fmt" "strings" + "github.com/hashicorp/terraform/flatmap" "github.com/hashicorp/terraform/helper/multierror" + "github.com/mitchellh/mapstructure" ) // Config is the configuration that comes from loading a collection @@ -63,6 +65,14 @@ type Output struct { RawConfig *RawConfig } +type VariableType byte + +const ( + VariableTypeUnknown VariableType = iota + VariableTypeString + VariableTypeMap +) + // ProviderConfigName returns the name of the provider configuration in // the given mapping that maps to the proper provider configuration // for this resource. @@ -271,6 +281,20 @@ func (r *Resource) mergerMerge(m merger) merger { return &result } +// DefaultsMap returns a map of default values for this variable. +func (v *Variable) DefaultsMap() map[string]string { + switch v.Type() { + case VariableTypeString: + return map[string]string{v.Name: v.Default.(string)} + case VariableTypeMap: + return flatmap.Flatten(map[string]interface{}{ + v.Name: v.Default.(map[string]string), + }) + default: + return nil + } +} + // Merge merges two variables to create a new third variable. func (v *Variable) Merge(v2 *Variable) *Variable { // Shallow copy the variable @@ -289,6 +313,27 @@ func (v *Variable) Merge(v2 *Variable) *Variable { return &result } +// Type returns the type of varialbe this is. +func (v *Variable) Type() VariableType { + if v.Default == nil { + return VariableTypeString + } + + var strVal string + if err := mapstructure.WeakDecode(v.Default, &strVal); err == nil { + v.Default = strVal + return VariableTypeString + } + + var m map[string]string + if err := mapstructure.WeakDecode(v.Default, &m); err == nil { + v.Default = m + return VariableTypeMap + } + + return VariableTypeUnknown +} + func (v *Variable) mergerName() string { return v.Name } diff --git a/config/config_test.go b/config/config_test.go index 000719ee5a..40f54b5c79 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -2,6 +2,7 @@ package config import ( "path/filepath" + "reflect" "testing" ) @@ -96,6 +97,37 @@ func TestProviderConfigName(t *testing.T) { } } +func TestVariableDefaultsMap(t *testing.T) { + cases := []struct { + Default interface{} + Output map[string]string + }{ + { + "foo", + map[string]string{"foo": "foo"}, + }, + + { + map[interface{}]interface{}{ + "foo": "bar", + "bar": "baz", + }, + map[string]string{ + "foo.foo": "bar", + "foo.bar": "baz", + }, + }, + } + + for i, tc := range cases { + v := &Variable{Name: "foo", Default: tc.Default} + actual := v.DefaultsMap() + if !reflect.DeepEqual(actual, tc.Output) { + t.Fatalf("%d: bad: %#v", i, actual) + } + } +} + func testConfig(t *testing.T, name string) *Config { c, err := Load(filepath.Join(fixtureDir, name, "main.tf")) if err != nil {