Skip to content

Commit

Permalink
Detailed diff use minimal edit distance for list attribute diffs (#2863)
Browse files Browse the repository at this point in the history
This PR uses a minimal edit distance algorithm to compute a sensible
list attribute diff.

Uses https://github.com/t0yv0/godifft with a small modification.

Note that this is only done for list attributes as blocks might trigger
replaces from a nested property. This matches the terraform behaviour,
more details in
#2295 (comment)

Alternative to
#2862
fixes #2295
fixes #2239
  • Loading branch information
VenelinMartinov authored Jan 27, 2025
1 parent 5ede9f4 commit 93de27b
Show file tree
Hide file tree
Showing 22 changed files with 119 additions and 369 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,17 +35,11 @@ Plan: 0 to add, 1 to change, 0 to destroy.
[id=newid]
[urn=urn:pulumi:test::project::crossprovider:index/testRes:TestRes::example]
~ props: [
~ [0]: "val2" => "val1"
~ [1]: "val3" => "val2"
+ [2]: "val3"
+ [0]: "val1"
]
Resources:
~ 1 to update
1 unchanged
`,
detailedDiff: map[string]interface{}{
"props[0]": map[string]interface{}{"kind": "UPDATE"},
"props[1]": map[string]interface{}{"kind": "UPDATE"},
"props[2]": map[string]interface{}{},
},
detailedDiff: map[string]interface{}{"props[0]": map[string]interface{}{}},
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,11 @@ Plan: 0 to add, 1 to change, 0 to destroy.
[id=newid]
[urn=urn:pulumi:test::project::crossprovider:index/testRes:TestRes::example]
~ props: [
~ [1]: "val3" => "val2"
+ [2]: "val3"
+ [1]: "val2"
]
Resources:
~ 1 to update
1 unchanged
`,
detailedDiff: map[string]interface{}{
"props[1]": map[string]interface{}{"kind": "UPDATE"},
"props[2]": map[string]interface{}{},
},
detailedDiff: map[string]interface{}{"props[1]": map[string]interface{}{}},
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,17 +35,11 @@ Plan: 0 to add, 1 to change, 0 to destroy.
[id=newid]
[urn=urn:pulumi:test::project::crossprovider:index/testRes:TestRes::example]
~ props: [
~ [0]: "val1" => "val2"
~ [1]: "val2" => "val3"
- [2]: "val3"
- [0]: "val1"
]
Resources:
~ 1 to update
1 unchanged
`,
detailedDiff: map[string]interface{}{
"props[0]": map[string]interface{}{"kind": "UPDATE"},
"props[1]": map[string]interface{}{"kind": "UPDATE"},
"props[2]": map[string]interface{}{"kind": "DELETE"},
},
detailedDiff: map[string]interface{}{"props[0]": map[string]interface{}{"kind": "DELETE"}},
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,11 @@ Plan: 0 to add, 1 to change, 0 to destroy.
[id=newid]
[urn=urn:pulumi:test::project::crossprovider:index/testRes:TestRes::example]
~ props: [
~ [1]: "val2" => "val3"
- [2]: "val3"
- [1]: "val2"
]
Resources:
~ 1 to update
1 unchanged
`,
detailedDiff: map[string]interface{}{
"props[1]": map[string]interface{}{"kind": "UPDATE"},
"props[2]": map[string]interface{}{"kind": "DELETE"},
},
detailedDiff: map[string]interface{}{"props[1]": map[string]interface{}{"kind": "DELETE"}},
}
Original file line number Diff line number Diff line change
Expand Up @@ -71,53 +71,11 @@ Plan: 0 to add, 1 to change, 0 to destroy.
[id=newid]
[urn=urn:pulumi:test::project::crossprovider:index/testRes:TestRes::example]
~ props: [
~ [0]: "value0" => "value20"
~ [1]: "value1" => "value0"
~ [2]: "value2" => "value1"
~ [3]: "value3" => "value2"
~ [4]: "value4" => "value3"
~ [5]: "value5" => "value4"
~ [6]: "value6" => "value5"
~ [7]: "value7" => "value6"
~ [8]: "value8" => "value7"
~ [9]: "value9" => "value8"
~ [10]: "value10" => "value9"
~ [11]: "value11" => "value10"
~ [12]: "value12" => "value11"
~ [13]: "value13" => "value12"
~ [14]: "value14" => "value13"
~ [15]: "value15" => "value14"
~ [16]: "value16" => "value15"
~ [17]: "value17" => "value16"
~ [18]: "value18" => "value17"
~ [19]: "value19" => "value18"
+ [20]: "value19"
+ [0]: "value20"
]
Resources:
~ 1 to update
1 unchanged
`,
detailedDiff: map[string]interface{}{
"props[0]": map[string]interface{}{"kind": "UPDATE"},
"props[10]": map[string]interface{}{"kind": "UPDATE"},
"props[11]": map[string]interface{}{"kind": "UPDATE"},
"props[12]": map[string]interface{}{"kind": "UPDATE"},
"props[13]": map[string]interface{}{"kind": "UPDATE"},
"props[14]": map[string]interface{}{"kind": "UPDATE"},
"props[15]": map[string]interface{}{"kind": "UPDATE"},
"props[16]": map[string]interface{}{"kind": "UPDATE"},
"props[17]": map[string]interface{}{"kind": "UPDATE"},
"props[18]": map[string]interface{}{"kind": "UPDATE"},
"props[19]": map[string]interface{}{"kind": "UPDATE"},
"props[1]": map[string]interface{}{"kind": "UPDATE"},
"props[20]": map[string]interface{}{},
"props[2]": map[string]interface{}{"kind": "UPDATE"},
"props[3]": map[string]interface{}{"kind": "UPDATE"},
"props[4]": map[string]interface{}{"kind": "UPDATE"},
"props[5]": map[string]interface{}{"kind": "UPDATE"},
"props[6]": map[string]interface{}{"kind": "UPDATE"},
"props[7]": map[string]interface{}{"kind": "UPDATE"},
"props[8]": map[string]interface{}{"kind": "UPDATE"},
"props[9]": map[string]interface{}{"kind": "UPDATE"},
},
detailedDiff: map[string]interface{}{"props[0]": map[string]interface{}{}},
}
Original file line number Diff line number Diff line change
Expand Up @@ -71,53 +71,11 @@ Plan: 0 to add, 1 to change, 0 to destroy.
[id=newid]
[urn=urn:pulumi:test::project::crossprovider:index/testRes:TestRes::example]
~ props: [
~ [0]: "value20" => "value0"
~ [1]: "value0" => "value1"
~ [2]: "value1" => "value2"
~ [3]: "value2" => "value3"
~ [4]: "value3" => "value4"
~ [5]: "value4" => "value5"
~ [6]: "value5" => "value6"
~ [7]: "value6" => "value7"
~ [8]: "value7" => "value8"
~ [9]: "value8" => "value9"
~ [10]: "value9" => "value10"
~ [11]: "value10" => "value11"
~ [12]: "value11" => "value12"
~ [13]: "value12" => "value13"
~ [14]: "value13" => "value14"
~ [15]: "value14" => "value15"
~ [16]: "value15" => "value16"
~ [17]: "value16" => "value17"
~ [18]: "value17" => "value18"
~ [19]: "value18" => "value19"
- [20]: "value19"
- [0]: "value20"
]
Resources:
~ 1 to update
1 unchanged
`,
detailedDiff: map[string]interface{}{
"props[0]": map[string]interface{}{"kind": "UPDATE"},
"props[10]": map[string]interface{}{"kind": "UPDATE"},
"props[11]": map[string]interface{}{"kind": "UPDATE"},
"props[12]": map[string]interface{}{"kind": "UPDATE"},
"props[13]": map[string]interface{}{"kind": "UPDATE"},
"props[14]": map[string]interface{}{"kind": "UPDATE"},
"props[15]": map[string]interface{}{"kind": "UPDATE"},
"props[16]": map[string]interface{}{"kind": "UPDATE"},
"props[17]": map[string]interface{}{"kind": "UPDATE"},
"props[18]": map[string]interface{}{"kind": "UPDATE"},
"props[19]": map[string]interface{}{"kind": "UPDATE"},
"props[1]": map[string]interface{}{"kind": "UPDATE"},
"props[20]": map[string]interface{}{"kind": "DELETE"},
"props[2]": map[string]interface{}{"kind": "UPDATE"},
"props[3]": map[string]interface{}{"kind": "UPDATE"},
"props[4]": map[string]interface{}{"kind": "UPDATE"},
"props[5]": map[string]interface{}{"kind": "UPDATE"},
"props[6]": map[string]interface{}{"kind": "UPDATE"},
"props[7]": map[string]interface{}{"kind": "UPDATE"},
"props[8]": map[string]interface{}{"kind": "UPDATE"},
"props[9]": map[string]interface{}{"kind": "UPDATE"},
},
detailedDiff: map[string]interface{}{"props[0]": map[string]interface{}{"kind": "DELETE"}},
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,17 +36,15 @@ Plan: 0 to add, 1 to change, 0 to destroy.
[id=newid]
[urn=urn:pulumi:test::project::crossprovider:index/testRes:TestRes::example]
~ props: [
~ [0]: "val1" => "val2"
~ [1]: "val2" => "val3"
~ [2]: "val3" => "val4"
- [0]: "val1"
+ [2]: "val4"
]
Resources:
~ 1 to update
1 unchanged
`,
detailedDiff: map[string]interface{}{
"props[0]": map[string]interface{}{"kind": "UPDATE"},
"props[1]": map[string]interface{}{"kind": "UPDATE"},
"props[2]": map[string]interface{}{"kind": "UPDATE"},
"props[0]": map[string]interface{}{"kind": "DELETE"},
"props[2]": map[string]interface{}{},
},
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,17 +35,11 @@ Plan: 0 to add, 1 to change, 0 to destroy.
[id=id]
[urn=urn:pulumi:test::project::crossprovider:index/testRes:TestRes::example]
~ props: [
~ [0]: "val2" => "val1"
~ [1]: "val3" => "val2"
+ [2]: "val3"
+ [0]: "val1"
]
Resources:
~ 1 to update
1 unchanged
`,
detailedDiff: map[string]interface{}{
"props[0]": map[string]interface{}{"kind": "UPDATE"},
"props[1]": map[string]interface{}{"kind": "UPDATE"},
"props[2]": map[string]interface{}{},
},
detailedDiff: map[string]interface{}{"props[0]": map[string]interface{}{}},
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,11 @@ Plan: 0 to add, 1 to change, 0 to destroy.
[id=id]
[urn=urn:pulumi:test::project::crossprovider:index/testRes:TestRes::example]
~ props: [
~ [1]: "val3" => "val2"
+ [2]: "val3"
+ [1]: "val2"
]
Resources:
~ 1 to update
1 unchanged
`,
detailedDiff: map[string]interface{}{
"props[1]": map[string]interface{}{"kind": "UPDATE"},
"props[2]": map[string]interface{}{},
},
detailedDiff: map[string]interface{}{"props[1]": map[string]interface{}{}},
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,17 +35,11 @@ Plan: 0 to add, 1 to change, 0 to destroy.
[id=id]
[urn=urn:pulumi:test::project::crossprovider:index/testRes:TestRes::example]
~ props: [
~ [0]: "val1" => "val2"
~ [1]: "val2" => "val3"
- [2]: "val3"
- [0]: "val1"
]
Resources:
~ 1 to update
1 unchanged
`,
detailedDiff: map[string]interface{}{
"props[0]": map[string]interface{}{"kind": "UPDATE"},
"props[1]": map[string]interface{}{"kind": "UPDATE"},
"props[2]": map[string]interface{}{"kind": "DELETE"},
},
detailedDiff: map[string]interface{}{"props[0]": map[string]interface{}{"kind": "DELETE"}},
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,11 @@ Plan: 0 to add, 1 to change, 0 to destroy.
[id=id]
[urn=urn:pulumi:test::project::crossprovider:index/testRes:TestRes::example]
~ props: [
~ [1]: "val2" => "val3"
- [2]: "val3"
- [1]: "val2"
]
Resources:
~ 1 to update
1 unchanged
`,
detailedDiff: map[string]interface{}{
"props[1]": map[string]interface{}{"kind": "UPDATE"},
"props[2]": map[string]interface{}{"kind": "DELETE"},
},
detailedDiff: map[string]interface{}{"props[1]": map[string]interface{}{"kind": "DELETE"}},
}
Original file line number Diff line number Diff line change
Expand Up @@ -71,53 +71,11 @@ Plan: 0 to add, 1 to change, 0 to destroy.
[id=id]
[urn=urn:pulumi:test::project::crossprovider:index/testRes:TestRes::example]
~ props: [
~ [0]: "value0" => "value20"
~ [1]: "value1" => "value0"
~ [2]: "value2" => "value1"
~ [3]: "value3" => "value2"
~ [4]: "value4" => "value3"
~ [5]: "value5" => "value4"
~ [6]: "value6" => "value5"
~ [7]: "value7" => "value6"
~ [8]: "value8" => "value7"
~ [9]: "value9" => "value8"
~ [10]: "value10" => "value9"
~ [11]: "value11" => "value10"
~ [12]: "value12" => "value11"
~ [13]: "value13" => "value12"
~ [14]: "value14" => "value13"
~ [15]: "value15" => "value14"
~ [16]: "value16" => "value15"
~ [17]: "value17" => "value16"
~ [18]: "value18" => "value17"
~ [19]: "value19" => "value18"
+ [20]: "value19"
+ [0]: "value20"
]
Resources:
~ 1 to update
1 unchanged
`,
detailedDiff: map[string]interface{}{
"props[0]": map[string]interface{}{"kind": "UPDATE"},
"props[10]": map[string]interface{}{"kind": "UPDATE"},
"props[11]": map[string]interface{}{"kind": "UPDATE"},
"props[12]": map[string]interface{}{"kind": "UPDATE"},
"props[13]": map[string]interface{}{"kind": "UPDATE"},
"props[14]": map[string]interface{}{"kind": "UPDATE"},
"props[15]": map[string]interface{}{"kind": "UPDATE"},
"props[16]": map[string]interface{}{"kind": "UPDATE"},
"props[17]": map[string]interface{}{"kind": "UPDATE"},
"props[18]": map[string]interface{}{"kind": "UPDATE"},
"props[19]": map[string]interface{}{"kind": "UPDATE"},
"props[1]": map[string]interface{}{"kind": "UPDATE"},
"props[20]": map[string]interface{}{},
"props[2]": map[string]interface{}{"kind": "UPDATE"},
"props[3]": map[string]interface{}{"kind": "UPDATE"},
"props[4]": map[string]interface{}{"kind": "UPDATE"},
"props[5]": map[string]interface{}{"kind": "UPDATE"},
"props[6]": map[string]interface{}{"kind": "UPDATE"},
"props[7]": map[string]interface{}{"kind": "UPDATE"},
"props[8]": map[string]interface{}{"kind": "UPDATE"},
"props[9]": map[string]interface{}{"kind": "UPDATE"},
},
detailedDiff: map[string]interface{}{"props[0]": map[string]interface{}{}},
}
Original file line number Diff line number Diff line change
Expand Up @@ -71,53 +71,11 @@ Plan: 0 to add, 1 to change, 0 to destroy.
[id=id]
[urn=urn:pulumi:test::project::crossprovider:index/testRes:TestRes::example]
~ props: [
~ [0]: "value20" => "value0"
~ [1]: "value0" => "value1"
~ [2]: "value1" => "value2"
~ [3]: "value2" => "value3"
~ [4]: "value3" => "value4"
~ [5]: "value4" => "value5"
~ [6]: "value5" => "value6"
~ [7]: "value6" => "value7"
~ [8]: "value7" => "value8"
~ [9]: "value8" => "value9"
~ [10]: "value9" => "value10"
~ [11]: "value10" => "value11"
~ [12]: "value11" => "value12"
~ [13]: "value12" => "value13"
~ [14]: "value13" => "value14"
~ [15]: "value14" => "value15"
~ [16]: "value15" => "value16"
~ [17]: "value16" => "value17"
~ [18]: "value17" => "value18"
~ [19]: "value18" => "value19"
- [20]: "value19"
- [0]: "value20"
]
Resources:
~ 1 to update
1 unchanged
`,
detailedDiff: map[string]interface{}{
"props[0]": map[string]interface{}{"kind": "UPDATE"},
"props[10]": map[string]interface{}{"kind": "UPDATE"},
"props[11]": map[string]interface{}{"kind": "UPDATE"},
"props[12]": map[string]interface{}{"kind": "UPDATE"},
"props[13]": map[string]interface{}{"kind": "UPDATE"},
"props[14]": map[string]interface{}{"kind": "UPDATE"},
"props[15]": map[string]interface{}{"kind": "UPDATE"},
"props[16]": map[string]interface{}{"kind": "UPDATE"},
"props[17]": map[string]interface{}{"kind": "UPDATE"},
"props[18]": map[string]interface{}{"kind": "UPDATE"},
"props[19]": map[string]interface{}{"kind": "UPDATE"},
"props[1]": map[string]interface{}{"kind": "UPDATE"},
"props[20]": map[string]interface{}{"kind": "DELETE"},
"props[2]": map[string]interface{}{"kind": "UPDATE"},
"props[3]": map[string]interface{}{"kind": "UPDATE"},
"props[4]": map[string]interface{}{"kind": "UPDATE"},
"props[5]": map[string]interface{}{"kind": "UPDATE"},
"props[6]": map[string]interface{}{"kind": "UPDATE"},
"props[7]": map[string]interface{}{"kind": "UPDATE"},
"props[8]": map[string]interface{}{"kind": "UPDATE"},
"props[9]": map[string]interface{}{"kind": "UPDATE"},
},
detailedDiff: map[string]interface{}{"props[0]": map[string]interface{}{"kind": "DELETE"}},
}
Loading

0 comments on commit 93de27b

Please sign in to comment.