Skip to content

Commit bec83af

Browse files
prashantvaschepis
authored andcommitted
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 89ec6a1 commit bec83af

File tree

3 files changed

+79
-5
lines changed

3 files changed

+79
-5
lines changed

helper/schema/schema.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -947,10 +947,10 @@ func (m schemaMap) diff(
947947
continue
948948
}
949949

950-
attrV = &terraform.ResourceAttrDiff{
951-
Old: attrV.Old,
952-
New: attrV.Old,
953-
}
950+
// If the diff is suppressed, we want Old = New, but retain the other properties.
951+
updatedAttr := *attrV
952+
updatedAttr.New = attrV.Old
953+
attrV = &updatedAttr
954954
}
955955
}
956956
diff.Attributes[attrK] = attrV

helper/schema/schema_test.go

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

1225+
{
1226+
Name: "Set with DiffSuppressFunc",
1227+
Schema: map[string]*Schema{
1228+
"rule": {
1229+
Type: TypeSet,
1230+
Required: true,
1231+
Elem: &Resource{
1232+
Schema: map[string]*Schema{
1233+
"port": {
1234+
Type: TypeInt,
1235+
Required: true,
1236+
},
1237+
"duration": {
1238+
Type: TypeString,
1239+
Optional: true,
1240+
DiffSuppressFunc: func(k, oldValue, newValue string, d *ResourceData) bool {
1241+
// Adding a DiffSuppressFunc to an element in a set changes behaviour.
1242+
// The actual suppress func doesn't matter.
1243+
return oldValue == newValue
1244+
},
1245+
},
1246+
},
1247+
},
1248+
Set: func(v interface{}) int {
1249+
m := v.(map[string]interface{})
1250+
port := m["port"].(int)
1251+
return port
1252+
},
1253+
},
1254+
},
1255+
1256+
State: &terraform.InstanceState{
1257+
Attributes: map[string]string{
1258+
"rule.#": "1",
1259+
"rule.80.port": "80",
1260+
"rule.80.duration": "",
1261+
},
1262+
},
1263+
1264+
Config: map[string]interface{}{
1265+
"rule": []interface{}{
1266+
map[string]interface{}{
1267+
"port": 90,
1268+
"duration": "30s",
1269+
},
1270+
},
1271+
},
1272+
1273+
Diff: &terraform.InstanceDiff{
1274+
Attributes: map[string]*terraform.ResourceAttrDiff{
1275+
"rule.80.port": {
1276+
Old: "80",
1277+
New: "0",
1278+
NewRemoved: true,
1279+
},
1280+
"rule.80.duration": {
1281+
Old: "",
1282+
New: "",
1283+
NewRemoved: true,
1284+
},
1285+
"rule.90.port": {
1286+
Old: "",
1287+
New: "90",
1288+
},
1289+
"rule.90.duration": {
1290+
Old: "",
1291+
New: "30s",
1292+
},
1293+
},
1294+
},
1295+
1296+
Err: false,
1297+
},
1298+
12251299
{
12261300
Name: "List of structure decode",
12271301
Schema: map[string]*Schema{

helper/schema/serialize_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ func TestSerializeForHash(t *testing.T) {
158158
"duration": {
159159
Type: TypeString,
160160
Required: true,
161-
StateFunc: func(v any) string {
161+
StateFunc: func(v interface{}) string {
162162
d, err := time.ParseDuration(v.(string))
163163
if err != nil {
164164
panic(err)

0 commit comments

Comments
 (0)