terraform: ResourceConfig.IsComputed cases

This commit is contained in:
Mitchell Hashimoto 2016-11-08 22:49:56 -08:00
parent 0c271b2b2d
commit 29485f6167
No known key found for this signature in database
GPG Key ID: 744E147AA52F5B0A
3 changed files with 51 additions and 6 deletions

View File

@ -344,7 +344,7 @@ func TestConfigFieldReader_ComputedSet(t *testing.T) {
}, map[string]ast.Variable{ }, map[string]ast.Variable{
"var.foo": ast.Variable{ "var.foo": ast.Variable{
Value: config.UnknownVariableValue, Value: config.UnknownVariableValue,
Type: ast.TypeString, Type: ast.TypeUnknown,
}, },
}), }),
false, false,
@ -362,7 +362,7 @@ func TestConfigFieldReader_ComputedSet(t *testing.T) {
}, map[string]ast.Variable{ }, map[string]ast.Variable{
"var.foo": ast.Variable{ "var.foo": ast.Variable{
Value: config.UnknownVariableValue, Value: config.UnknownVariableValue,
Type: ast.TypeString, Type: ast.TypeUnknown,
}, },
}), }),
false, false,

View File

@ -209,6 +209,15 @@ func (c *ResourceConfig) GetRaw(k string) (interface{}, bool) {
// IsComputed returns whether the given key is computed or not. // IsComputed returns whether the given key is computed or not.
func (c *ResourceConfig) IsComputed(k string) bool { func (c *ResourceConfig) IsComputed(k string) bool {
// First, check for pure computed key equality since that is fast
for _, ck := range c.ComputedKeys {
if ck == k {
return true
}
}
// The next thing we do is check the config if we get a computed
// value out of it.
v, ok := c.get(k, c.Config) v, ok := c.get(k, c.Config)
_, okRaw := c.get(k, c.Raw) _, okRaw := c.get(k, c.Raw)
@ -252,6 +261,7 @@ func (c *ResourceConfig) get(
var current interface{} = raw var current interface{} = raw
var previous interface{} = nil var previous interface{} = nil
for i, part := range parts { for i, part := range parts {
println(fmt.Sprintf("%#v: %#v %T", part, current, current))
if current == nil { if current == nil {
return nil, false return nil, false
} }
@ -268,6 +278,7 @@ func (c *ResourceConfig) get(
if !v.IsValid() { if !v.IsValid() {
return nil, false return nil, false
} }
return v.Interface(), true return v.Interface(), true
} }
@ -299,22 +310,39 @@ func (c *ResourceConfig) get(
current = cv.Index(int(i)).Interface() current = cv.Index(int(i)).Interface()
} }
case reflect.String: case reflect.String:
// If we get the unknown value, return that
if current == unknownValue() {
return current, false
}
// This happens when map keys contain "." and have a common // This happens when map keys contain "." and have a common
// prefix so were split as path components above. // prefix so were split as path components above.
actualKey := strings.Join(parts[i-1:], ".") actualKey := strings.Join(parts[i-1:], ".")
if prevMap, ok := previous.(map[string]interface{}); ok { if prevMap, ok := previous.(map[string]interface{}); ok {
return prevMap[actualKey], true return prevMap[actualKey], true
} }
return nil, false return nil, false
default: default:
panic(fmt.Sprintf("Unknown kind: %s", cv.Kind())) panic(fmt.Sprintf("Unknown kind: %s", cv.Kind()))
} }
} }
// If the value is just the unknown value, then we don't switch cv := reflect.ValueOf(current); cv.Kind() {
// know anything beyond here. case reflect.Slice:
if current == unknownValue() { // If any value in a list is computed, this whole thing
return current, false // is computed and we can't read any part of it.
for i := 0; i < cv.Len(); i++ {
if v := cv.Index(i).Interface(); v == unknownValue() {
return v, false
}
}
default:
// If the value is just the unknown value, then we don't
// know anything beyond here.
if current == unknownValue() {
return current, false
}
} }
return current, true return current, true

View File

@ -326,6 +326,23 @@ func TestResourceConfigIsComputed(t *testing.T) {
Key: "foo.#", Key: "foo.#",
Result: true, Result: true,
}, },
{
Name: "nested set with computed elements",
Config: map[string]interface{}{
"route": []map[string]interface{}{
map[string]interface{}{
"index": "1",
"gateway": []interface{}{"${var.foo}"},
},
},
},
Vars: map[string]interface{}{
"foo": unknownValue(),
},
Key: "route.0.gateway",
Result: true,
},
} }
for i, tc := range cases { for i, tc := range cases {