Skip to content

Commit c747872

Browse files
authored
Fix for TypeSet applying with unexpected empty element (#2)
hashicorp/terraform-plugin-sdk#895 When calculating a diff, sets are added as delete of all old attributes and a create of all new attributes. When DiffSuppressFunc is used, the delete attribute drops the `NewRemoved` field, which results in sending a diff that ends up creating a new empty set element. Without the fix, the test fails: ``` === RUN TestSchemaMap_Diff/30-Set_with_DiffSuppressFunc schema_test.go:3188: expected: *terraform.InstanceDiff{ [...]"rule.80.duration":*terraform.ResourceAttrDiff{Old:"", New:"", NewComputed:false, NewRemoved:true, [...] got: *terraform.InstanceDiff{ [...]"rule.80.duration":*terraform.ResourceAttrDiff{Old:"", New:"", NewComputed:false, [...] NewRemoved:false, [...] ``` Previously, `NewRemoved` was set to false for the sustain field even though it belonged to an element being removed.
1 parent e14d3b6 commit c747872

File tree

2 files changed

+78
-4
lines changed

2 files changed

+78
-4
lines changed

helper/schema/schema.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1149,10 +1149,10 @@ func (m schemaMap) diff(
11491149
}
11501150

11511151
logging.HelperSchemaDebug(ctx, "Ignoring change due to DiffSuppressFunc", map[string]interface{}{logging.KeyAttributePath: attrK})
1152-
attrV = &terraform.ResourceAttrDiff{
1153-
Old: attrV.Old,
1154-
New: attrV.Old,
1155-
}
1152+
// If the diff is suppressed, we want Old = New, but retain the other properties.
1153+
updatedAttr := *attrV
1154+
updatedAttr.New = attrV.Old
1155+
attrV = &updatedAttr
11561156
}
11571157
}
11581158
diff.Attributes[attrK] = attrV

helper/schema/schema_test.go

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1155,6 +1155,80 @@ func TestSchemaMap_Diff(t *testing.T) {
11551155
Err: false,
11561156
},
11571157

1158+
{
1159+
Name: "Set with DiffSuppressFunc",
1160+
Schema: map[string]*Schema{
1161+
"rule": {
1162+
Type: TypeSet,
1163+
Required: true,
1164+
Elem: &Resource{
1165+
Schema: map[string]*Schema{
1166+
"port": {
1167+
Type: TypeInt,
1168+
Required: true,
1169+
},
1170+
"duration": {
1171+
Type: TypeString,
1172+
Optional: true,
1173+
DiffSuppressFunc: func(k, oldValue, newValue string, d *ResourceData) bool {
1174+
// Adding a DiffSuppressFunc to an element in a set changes behaviour.
1175+
// The actual suppress func doesn't matter.
1176+
return oldValue == newValue
1177+
},
1178+
},
1179+
},
1180+
},
1181+
Set: func(v interface{}) int {
1182+
m := v.(map[string]interface{})
1183+
port := m["port"].(int)
1184+
return port
1185+
},
1186+
},
1187+
},
1188+
1189+
State: &terraform.InstanceState{
1190+
Attributes: map[string]string{
1191+
"rule.#": "1",
1192+
"rule.80.port": "80",
1193+
"rule.80.duration": "",
1194+
},
1195+
},
1196+
1197+
Config: map[string]interface{}{
1198+
"rule": []interface{}{
1199+
map[string]interface{}{
1200+
"port": 90,
1201+
"duration": "30s",
1202+
},
1203+
},
1204+
},
1205+
1206+
Diff: &terraform.InstanceDiff{
1207+
Attributes: map[string]*terraform.ResourceAttrDiff{
1208+
"rule.80.port": {
1209+
Old: "80",
1210+
New: "0",
1211+
NewRemoved: true,
1212+
},
1213+
"rule.80.duration": {
1214+
Old: "",
1215+
New: "",
1216+
NewRemoved: true,
1217+
},
1218+
"rule.90.port": {
1219+
Old: "",
1220+
New: "90",
1221+
},
1222+
"rule.90.duration": {
1223+
Old: "",
1224+
New: "30s",
1225+
},
1226+
},
1227+
},
1228+
1229+
Err: false,
1230+
},
1231+
11581232
{
11591233
Name: "List of structure decode",
11601234
Schema: map[string]*Schema{

0 commit comments

Comments
 (0)