diff --git a/helper/schema/provider.go b/helper/schema/provider.go index b1bb65ccb..ff9f991ca 100644 --- a/helper/schema/provider.go +++ b/helper/schema/provider.go @@ -87,6 +87,13 @@ func (p *Provider) SetMeta(v interface{}) { p.meta = v } +// Input implementation of terraform.ResourceProvider interface. +func (p *Provider) Input( + input terraform.UIInput, + c *terraform.ResourceConfig) (*terraform.ResourceConfig, error) { + return schemaMap(p.Schema).Input(input, c) +} + // Validate implementation of terraform.ResourceProvider interface. func (p *Provider) Validate(c *terraform.ResourceConfig) ([]string, []error) { return schemaMap(p.Schema).Validate(c) diff --git a/helper/schema/schema.go b/helper/schema/schema.go index 711262bf9..1f7b9c49d 100644 --- a/helper/schema/schema.go +++ b/helper/schema/schema.go @@ -270,6 +270,42 @@ func (m schemaMap) Diff( return result, nil } +// Input implements the terraform.ResourceProvider method by asking +// for input for required configuration keys that don't have a value. +func (m schemaMap) Input( + input terraform.UIInput, + c *terraform.ResourceConfig) (*terraform.ResourceConfig, error) { + for k, v := range m { + // Skip things that don't require config, if that is even valid + // for a provider schema. + if !v.Required && !v.Optional { + continue + } + + var value interface{} + var err error + switch v.Type { + case TypeBool: + fallthrough + case TypeInt: + fallthrough + case TypeString: + value, err = m.inputString(input, k, v) + default: + panic(fmt.Sprintf("Unknown type for input: %s", v.Type)) + } + + if err != nil { + return nil, fmt.Errorf( + "%s: %s", k, err) + } + + c.Raw[k] = value + } + + return c, nil +} + // Validate validates the configuration against this schema mapping. func (m schemaMap) Validate(c *terraform.ResourceConfig) ([]string, []error) { return m.validateObject("", m, c) @@ -569,6 +605,18 @@ func (m schemaMap) diffString( return nil } +func (m schemaMap) inputString( + input terraform.UIInput, + k string, + schema *Schema) (interface{}, error) { + result, err := input.Input(&terraform.InputOpts{ + Id: k, + Query: fmt.Sprintf("%s: ", k), + }) + + return result, err +} + func (m schemaMap) validate( k string, schema *Schema, diff --git a/helper/schema/schema_test.go b/helper/schema/schema_test.go index 91b958325..2f8abfac4 100644 --- a/helper/schema/schema_test.go +++ b/helper/schema/schema_test.go @@ -1035,6 +1035,63 @@ func TestSchemaMap_Diff(t *testing.T) { } } +func TestSchemaMap_Input(t *testing.T) { + cases := []struct { + Schema map[string]*Schema + Config map[string]interface{} + Input map[string]string + Result map[string]interface{} + Err bool + }{ + /* + * String decode + */ + + { + Schema: map[string]*Schema{ + "availability_zone": &Schema{ + Type: TypeString, + Optional: true, + }, + }, + + Config: map[string]interface{}{ + "availability_zone": "bar", + }, + + Input: map[string]string{ + "availability_zone": "foo", + }, + + Result: map[string]interface{}{ + "availability_zone": "foo", + }, + + Err: false, + }, + } + + for i, tc := range cases { + c, err := config.NewRawConfig(tc.Config) + if err != nil { + t.Fatalf("err: %s", err) + } + + input := new(terraform.MockUIInput) + input.InputReturnMap = tc.Input + + actual, err := schemaMap(tc.Schema).Input( + input, terraform.NewResourceConfig(c)) + if (err != nil) != tc.Err { + t.Fatalf("#%d err: %s", i, err) + } + + if !reflect.DeepEqual(tc.Result, actual.Raw) { + t.Fatalf("#%d: bad:\n\n%#v", i, actual.Raw) + } + } +} + func TestSchemaMap_InternalValidate(t *testing.T) { cases := []struct { In map[string]*Schema