helper/schema: properly detect that a list is computed

pull/385/head
Mitchell Hashimoto 12 years ago
parent a931707a6a
commit dcaf653d6f

@ -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 = &copyState
}
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,
}

@ -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 {

@ -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{

@ -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).
//

Loading…
Cancel
Save