helper/schema: FieldReaderConfig detects computed maps
This commit is contained in:
parent
45f73e640f
commit
fa934d96d0
|
@ -105,34 +105,67 @@ func (r *ConfigFieldReader) readField(
|
|||
}
|
||||
|
||||
func (r *ConfigFieldReader) readMap(k string) (FieldReadResult, error) {
|
||||
mraw, ok := r.Config.Get(k)
|
||||
// We want both the raw value and the interpolated. We use the interpolated
|
||||
// to store actual values and we use the raw one to check for
|
||||
// computed keys.
|
||||
mraw, ok := r.Config.GetRaw(k)
|
||||
if !ok {
|
||||
return FieldReadResult{}, nil
|
||||
}
|
||||
|
||||
result := make(map[string]interface{})
|
||||
computed := false
|
||||
switch m := mraw.(type) {
|
||||
case []interface{}:
|
||||
for _, innerRaw := range m {
|
||||
for k, v := range innerRaw.(map[string]interface{}) {
|
||||
result[k] = v
|
||||
for i, innerRaw := range m {
|
||||
for ik, _ := range innerRaw.(map[string]interface{}) {
|
||||
key := fmt.Sprintf("%s.%d.%s", k, i, ik)
|
||||
if r.Config.IsComputed(key) {
|
||||
computed = true
|
||||
break
|
||||
}
|
||||
|
||||
v, _ := r.Config.Get(key)
|
||||
result[ik] = v
|
||||
}
|
||||
}
|
||||
case []map[string]interface{}:
|
||||
for _, innerRaw := range m {
|
||||
for k, v := range innerRaw {
|
||||
result[k] = v
|
||||
for i, innerRaw := range m {
|
||||
for ik, _ := range innerRaw {
|
||||
key := fmt.Sprintf("%s.%d.%s", k, i, ik)
|
||||
if r.Config.IsComputed(key) {
|
||||
computed = true
|
||||
break
|
||||
}
|
||||
|
||||
v, _ := r.Config.Get(key)
|
||||
result[ik] = v
|
||||
}
|
||||
}
|
||||
case map[string]interface{}:
|
||||
result = m
|
||||
for ik, _ := range m {
|
||||
key := fmt.Sprintf("%s.%s", k, ik)
|
||||
if r.Config.IsComputed(key) {
|
||||
computed = true
|
||||
break
|
||||
}
|
||||
|
||||
v, _ := r.Config.Get(key)
|
||||
result[ik] = v
|
||||
}
|
||||
default:
|
||||
panic(fmt.Sprintf("unknown type: %#v", mraw))
|
||||
}
|
||||
|
||||
var value interface{}
|
||||
if !computed {
|
||||
value = result
|
||||
}
|
||||
|
||||
return FieldReadResult{
|
||||
Value: result,
|
||||
Value: value,
|
||||
Exists: true,
|
||||
Computed: computed,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -135,6 +135,79 @@ func TestConfigFieldReader_DefaultHandling(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestConfigFieldReader_ComputedMap(t *testing.T) {
|
||||
schema := map[string]*Schema{
|
||||
"map": &Schema{
|
||||
Type: TypeMap,
|
||||
Computed: true,
|
||||
},
|
||||
}
|
||||
|
||||
cases := map[string]struct {
|
||||
Addr []string
|
||||
Result FieldReadResult
|
||||
Config *terraform.ResourceConfig
|
||||
Err bool
|
||||
}{
|
||||
"set, normal": {
|
||||
[]string{"map"},
|
||||
FieldReadResult{
|
||||
Value: map[string]interface{}{
|
||||
"foo": "bar",
|
||||
},
|
||||
Exists: true,
|
||||
Computed: false,
|
||||
},
|
||||
testConfig(t, map[string]interface{}{
|
||||
"map": map[string]interface{}{
|
||||
"foo": "bar",
|
||||
},
|
||||
}),
|
||||
false,
|
||||
},
|
||||
|
||||
"computed element": {
|
||||
[]string{"map"},
|
||||
FieldReadResult{
|
||||
Exists: true,
|
||||
Computed: true,
|
||||
},
|
||||
testConfigInterpolate(t, map[string]interface{}{
|
||||
"map": map[string]interface{}{
|
||||
"foo": "${var.foo}",
|
||||
},
|
||||
}, map[string]ast.Variable{
|
||||
"var.foo": ast.Variable{
|
||||
Value: config.UnknownVariableValue,
|
||||
Type: ast.TypeString,
|
||||
},
|
||||
}),
|
||||
false,
|
||||
},
|
||||
}
|
||||
|
||||
for name, tc := range cases {
|
||||
r := &ConfigFieldReader{
|
||||
Schema: schema,
|
||||
Config: tc.Config,
|
||||
}
|
||||
out, err := r.ReadField(tc.Addr)
|
||||
if (err != nil) != tc.Err {
|
||||
t.Fatalf("%s: err: %s", name, err)
|
||||
}
|
||||
if s, ok := out.Value.(*Set); ok {
|
||||
// If it is a set, convert to the raw map
|
||||
out.Value = s.m
|
||||
if len(s.m) == 0 {
|
||||
out.Value = nil
|
||||
}
|
||||
}
|
||||
if !reflect.DeepEqual(tc.Result, out) {
|
||||
t.Fatalf("%s: bad: %#v", name, out)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfigFieldReader_ComputedSet(t *testing.T) {
|
||||
schema := map[string]*Schema{
|
||||
"strSet": &Schema{
|
||||
|
|
|
@ -134,6 +134,15 @@ func (c *ResourceConfig) Get(k string) (interface{}, bool) {
|
|||
return c.get(k, c.Raw)
|
||||
}
|
||||
|
||||
// GetRaw looks up a configuration value by key and returns the value,
|
||||
// from the raw, uninterpolated config.
|
||||
//
|
||||
// The second return value is true if the get was successful. Get will
|
||||
// not succeed if the value is being computed.
|
||||
func (c *ResourceConfig) GetRaw(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)
|
||||
|
|
Loading…
Reference in New Issue