diff --git a/helper/schema/resource_data.go b/helper/schema/resource_data.go index 4f7a4b9931..26d607730e 100644 --- a/helper/schema/resource_data.go +++ b/helper/schema/resource_data.go @@ -52,6 +52,7 @@ const ( type getResult struct { Value interface{} ValueProcessed interface{} + Computed bool Exists bool Schema *Schema } @@ -221,7 +222,8 @@ func (d *ResourceData) init() { d.newState = ©State } -func (d *ResourceData) diffChange(k string) (interface{}, interface{}, bool) { +func (d *ResourceData) diffChange( + k string) (interface{}, interface{}, bool, bool) { // Get the change between the state and the config. o, n := d.getChange(k, getSourceState, getSourceConfig) if !o.Exists { @@ -232,7 +234,7 @@ func (d *ResourceData) diffChange(k string) (interface{}, interface{}, bool) { } // Return the old, new, and whether there is a change - return o.Value, n.Value, !reflect.DeepEqual(o.Value, n.Value) + return o.Value, n.Value, !reflect.DeepEqual(o.Value, n.Value), n.Computed } func (d *ResourceData) getChange( @@ -516,17 +518,21 @@ func (d *ResourceData) getList( } // Get the entire list. + var result []interface{} count := d.getList(k, []string{"#"}, schema, source) - result := make([]interface{}, count.Value.(int)) - for i, _ := range result { - is := strconv.FormatInt(int64(i), 10) - result[i] = d.getList(k, []string{is}, schema, source).Value + if !count.Computed { + result = make([]interface{}, count.Value.(int)) + for i, _ := range result { + is := strconv.FormatInt(int64(i), 10) + result[i] = d.getList(k, []string{is}, schema, source).Value + } } return getResult{ - Value: result, - Exists: count.Exists, - Schema: schema, + Value: result, + Computed: count.Computed, + Exists: count.Exists, + Schema: schema, } } @@ -537,7 +543,7 @@ func (d *ResourceData) getPrimitive( source getSource) getResult { var result string var resultProcessed interface{} - var resultSet bool + var resultComputed, resultSet bool if d.state != nil && source >= getSourceState { result, resultSet = d.state.Attributes[k] } @@ -555,6 +561,8 @@ func (d *ResourceData) getPrimitive( resultSet = false } + // If it is computed, set that. + resultComputed = d.config.IsComputed(k) } if d.diff != nil && source >= getSourceDiff { @@ -615,6 +623,10 @@ func (d *ResourceData) getPrimitive( break } + if resultComputed { + break + } + v, err := strconv.ParseInt(result, 0, 0) if err != nil { panic(err) @@ -628,6 +640,7 @@ func (d *ResourceData) getPrimitive( return getResult{ Value: resultValue, ValueProcessed: resultProcessed, + Computed: resultComputed, Exists: resultSet, Schema: schema, } diff --git a/helper/schema/schema.go b/helper/schema/schema.go index 7d373bd0dc..cb3e11617d 100644 --- a/helper/schema/schema.go +++ b/helper/schema/schema.go @@ -434,7 +434,7 @@ func (m schemaMap) diffList( schema *Schema, diff *terraform.InstanceDiff, d *ResourceData) error { - o, n, _ := d.diffChange(k) + o, n, _, computedList := d.diffChange(k) // If we have an old value, but no new value set but we're computed, // then nothing has changed. @@ -460,6 +460,16 @@ func (m schemaMap) diffList( // Get the counts oldLen := len(os) newLen := len(vs) + oldStr := strconv.FormatInt(int64(oldLen), 10) + + // If the whole list is computed, then say that the # is computed + if computedList { + diff.Attributes[k+".#"] = &terraform.ResourceAttrDiff{ + Old: oldStr, + NewComputed: true, + } + return nil + } // If the counts are not the same, then record that diff changed := oldLen != newLen @@ -471,11 +481,11 @@ func (m schemaMap) diffList( ForceNew: schema.ForceNew, } - oldStr := "" newStr := "" if !computed { - oldStr = strconv.FormatInt(int64(oldLen), 10) newStr = strconv.FormatInt(int64(newLen), 10) + } else { + oldStr = "" } diff.Attributes[k+".#"] = countSchema.finalizeDiff(&terraform.ResourceAttrDiff{ @@ -534,7 +544,7 @@ func (m schemaMap) diffMap( // First get all the values from the state var stateMap, configMap map[string]string - o, n, _ := d.diffChange(k) + o, n, _, _ := d.diffChange(k) if err := mapstructure.WeakDecode(o, &stateMap); err != nil { return fmt.Errorf("%s: %s", k, err) } @@ -581,7 +591,7 @@ func (m schemaMap) diffString( d *ResourceData) error { var originalN interface{} var os, ns string - o, n, _ := d.diffChange(k) + o, n, _, _ := d.diffChange(k) if n == nil { n = schema.Default if schema.DefaultFunc != nil { diff --git a/helper/schema/schema_test.go b/helper/schema/schema_test.go index d3305a6859..23c283b380 100644 --- a/helper/schema/schema_test.go +++ b/helper/schema/schema_test.go @@ -428,6 +428,39 @@ func TestSchemaMap_Diff(t *testing.T) { Err: false, }, + { + Schema: map[string]*Schema{ + "ports": &Schema{ + Type: TypeList, + Required: true, + Elem: &Schema{Type: TypeInt}, + }, + }, + + State: nil, + + Config: map[string]interface{}{ + "ports": []interface{}{1, "${var.foo}"}, + }, + + ConfigVariables: map[string]string{ + "var.foo": config.UnknownVariableValue + + config.InterpSplitDelim + "5", + }, + + Diff: &terraform.InstanceDiff{ + Attributes: map[string]*terraform.ResourceAttrDiff{ + "ports.#": &terraform.ResourceAttrDiff{ + Old: "0", + New: "", + NewComputed: true, + }, + }, + }, + + Err: false, + }, + { Schema: map[string]*Schema{ "ports": &Schema{ diff --git a/terraform/resource.go b/terraform/resource.go index b43d296acd..071c0592d4 100644 --- a/terraform/resource.go +++ b/terraform/resource.go @@ -128,6 +128,13 @@ func (c *ResourceConfig) Get(k string) (interface{}, bool) { return c.get(k, c.Raw) } +// IsComputed returns whether the given key is computed or not. +func (c *ResourceConfig) IsComputed(k string) bool { + _, ok := c.get(k, c.Config) + _, okRaw := c.get(k, c.Raw) + return !ok && okRaw +} + // IsSet checks if the key in the configuration is set. A key is set if // it has a value or the value is being computed (is unknown currently). //