Merge pull request #18795 from hashicorp/paddy_diff_nested_checkKey

Allow for nested fields with checkKey on ResourceDiffs.
This commit is contained in:
Paddy 2018-09-26 14:21:28 -07:00 committed by GitHub
commit 35d82b0555
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 124 additions and 7 deletions

View File

@ -231,7 +231,7 @@ func (d *ResourceDiff) UpdatedKeys() []string {
// Note that this does not wipe an override. This function is only allowed on // Note that this does not wipe an override. This function is only allowed on
// computed keys. // computed keys.
func (d *ResourceDiff) Clear(key string) error { func (d *ResourceDiff) Clear(key string) error {
if err := d.checkKey(key, "Clear"); err != nil { if err := d.checkKey(key, "Clear", true); err != nil {
return err return err
} }
@ -287,7 +287,7 @@ func (d *ResourceDiff) diffChange(key string) (interface{}, interface{}, bool, b
// //
// This function is only allowed on computed attributes. // This function is only allowed on computed attributes.
func (d *ResourceDiff) SetNew(key string, value interface{}) error { func (d *ResourceDiff) SetNew(key string, value interface{}) error {
if err := d.checkKey(key, "SetNew"); err != nil { if err := d.checkKey(key, "SetNew", false); err != nil {
return err return err
} }
@ -299,7 +299,7 @@ func (d *ResourceDiff) SetNew(key string, value interface{}) error {
// //
// This function is only allowed on computed attributes. // This function is only allowed on computed attributes.
func (d *ResourceDiff) SetNewComputed(key string) error { func (d *ResourceDiff) SetNewComputed(key string) error {
if err := d.checkKey(key, "SetNewComputed"); err != nil { if err := d.checkKey(key, "SetNewComputed", false); err != nil {
return err return err
} }
@ -535,12 +535,24 @@ func childAddrOf(child, parent string) bool {
} }
// checkKey checks the key to make sure it exists and is computed. // checkKey checks the key to make sure it exists and is computed.
func (d *ResourceDiff) checkKey(key, caller string) error { func (d *ResourceDiff) checkKey(key, caller string, nested bool) error {
s, ok := d.schema[key] var schema *Schema
if !ok { if nested {
keyParts := strings.Split(key, ".")
schemaL := addrToSchema(keyParts, d.schema)
if len(schemaL) > 0 {
schema = schemaL[len(schemaL)-1]
}
} else {
s, ok := d.schema[key]
if ok {
schema = s
}
}
if schema == nil {
return fmt.Errorf("%s: invalid key: %s", caller, key) return fmt.Errorf("%s: invalid key: %s", caller, key)
} }
if !s.Computed { if !schema.Computed {
return fmt.Errorf("%s only operates on computed keys - %s is not one", caller, key) return fmt.Errorf("%s only operates on computed keys - %s is not one", caller, key)
} }
return nil return nil

View File

@ -1028,6 +1028,111 @@ func TestClear(t *testing.T) {
}, },
}, },
}, },
resourceDiffTestCase{
Name: "basic sub-block diff",
Schema: map[string]*Schema{
"foo": &Schema{
Type: TypeList,
Optional: true,
Computed: true,
Elem: &Resource{
Schema: map[string]*Schema{
"bar": &Schema{
Type: TypeString,
Optional: true,
Computed: true,
},
"baz": &Schema{
Type: TypeString,
Optional: true,
Computed: true,
},
},
},
},
},
State: &terraform.InstanceState{
Attributes: map[string]string{
"foo.0.bar": "bar1",
"foo.0.baz": "baz1",
},
},
Config: testConfig(t, map[string]interface{}{
"foo": []map[string]interface{}{
map[string]interface{}{
"bar": "bar2",
"baz": "baz1",
},
},
}),
Diff: &terraform.InstanceDiff{
Attributes: map[string]*terraform.ResourceAttrDiff{
"foo.0.bar": &terraform.ResourceAttrDiff{
Old: "bar1",
New: "bar2",
},
},
},
Key: "foo.0.bar",
Expected: &terraform.InstanceDiff{Attributes: map[string]*terraform.ResourceAttrDiff{}},
},
resourceDiffTestCase{
Name: "sub-block diff only partial clear",
Schema: map[string]*Schema{
"foo": &Schema{
Type: TypeList,
Optional: true,
Computed: true,
Elem: &Resource{
Schema: map[string]*Schema{
"bar": &Schema{
Type: TypeString,
Optional: true,
Computed: true,
},
"baz": &Schema{
Type: TypeString,
Optional: true,
Computed: true,
},
},
},
},
},
State: &terraform.InstanceState{
Attributes: map[string]string{
"foo.0.bar": "bar1",
"foo.0.baz": "baz1",
},
},
Config: testConfig(t, map[string]interface{}{
"foo": []map[string]interface{}{
map[string]interface{}{
"bar": "bar2",
"baz": "baz2",
},
},
}),
Diff: &terraform.InstanceDiff{
Attributes: map[string]*terraform.ResourceAttrDiff{
"foo.0.bar": &terraform.ResourceAttrDiff{
Old: "bar1",
New: "bar2",
},
"foo.0.baz": &terraform.ResourceAttrDiff{
Old: "baz1",
New: "baz2",
},
},
},
Key: "foo.0.bar",
Expected: &terraform.InstanceDiff{Attributes: map[string]*terraform.ResourceAttrDiff{
"foo.0.baz": &terraform.ResourceAttrDiff{
Old: "baz1",
New: "baz2",
},
}},
},
} }
for _, tc := range cases { for _, tc := range cases {
t.Run(tc.Name, func(t *testing.T) { t.Run(tc.Name, func(t *testing.T) {