Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve set detailed diffs #2451

Merged
merged 233 commits into from
Oct 30, 2024
Merged

Improve set detailed diffs #2451

merged 233 commits into from
Oct 30, 2024

Conversation

VenelinMartinov
Copy link
Contributor

@VenelinMartinov VenelinMartinov commented Sep 26, 2024

This change adds improved TF set handling to the detailed diff v2. The main challenge here is that pulumi does not have native sets, so set types are represented as lists.

Diffing sets using the hash

To correctly find the diff of two sets we calculate the hash of each element ourselves and do the diffs based on that. What makes this somewhat non-trivial is that due to MaxItemsOne flattening we can't just hash the pulumi PropertyValues given to us by the engine. Instead we use makeSingleTerraformInput to transform the values using the schema. We then use the hashes of the elements in the set to calculate the diffs. This allows us to correctly account for shuffling and duplicates, matching the terraform behaviour of sets.

When returning the element indices back to the engine, we need to return them in terms of oldState and newInputs because the engine does not have access to the plannedState (see #2281). To do that we keep the newInputs and match plannedState elements to their newInputs index by the set hash. Note that this is not possible if the set element contains any computed properties - these can change during the planning process, so we do not attempt to match and print a warning about possibly inaccurate diff results instead.

Unknowns in sets

Note that the terraform planning process does not allow a set to contain any unknowns, because that breaks the hashing. Because of that plan should always return an unknown for a set which contains any unknowns. This accounts for cases where resolving the unknown can result in duplicate elements.

Unknown elements in sets - the whole set becomes unknown in the plan, so the algorithm no longer works. Currently we return an update for the whole set to the engine and it does the diff on its side.

Testing

This PR also includes tests for the set behaviour, both unit tests for the detailed diff algorithm and integration tests using pulumi programs for:

  • Single element additions, updates and removals
  • Shuffling, also with additions, updates and removals
  • Multi-element additions, updates and removals
  • Unknowns

Issues

Builds on #2405

Stacked on #2515, #2516, #2496 and #2497

fixes #2200
fixes #2300
fixes #1904
fixes #186

@t0yv0 t0yv0 self-requested a review October 29, 2024 15:41
Copy link
Member

@t0yv0 t0yv0 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for explaining that we prefer to compute using engine indices using TF hashing since this succeeds in more places than computing using PropertyValue equality. I think that's great. That warrants some additional complexity in the code.

VenelinMartinov added a commit that referenced this pull request Oct 29, 2024
This PR changes the logic in the detailed diff v2 calculation to
short-circuit on encountering nils and unknowns.

Previously, when we encountered a null or unknown in either news or olds
we would still recurse down and compare the non-nil values versus a nil
value in order to get any replacements which might be happening. We
would then simplify the diff later to trim these extra diffs but would
propagate the replacement to the right level.

We would now instead short-circuit on encountering a null or unknown and
walk the non-null value to find any properties which can trigger a
replacement. This makes it much easier to handle sets in
#2451 as recursing
into sets is not necessary, as they are only compared by hashes.


This change is not meant to change any behaviour and is tested in
#2405

Stacked on #2515
and #2516
Base automatically changed from vvm/refactor_move_property_path to master October 29, 2024 18:31
@VenelinMartinov
Copy link
Contributor Author

VenelinMartinov commented Oct 29, 2024

I've refactored makeSetDiff into 3 functions and added tests for each one to address https://github.com/pulumi/pulumi-terraform-bridge/pull/2451/files#r1806996735 LMK if you have any comments on that!

@t0yv0
Copy link
Member

t0yv0 commented Oct 29, 2024

We're in code gold territory. I think we can ship this. It's a little clearer, it could be clearer still, but the test coverage is good so that's what matters. Thank you for labeling ints to distinguish hashes and indices.

@VenelinMartinov VenelinMartinov enabled auto-merge (squash) October 30, 2024 12:08
@VenelinMartinov VenelinMartinov merged commit 7b500d2 into master Oct 30, 2024
17 checks passed
@VenelinMartinov VenelinMartinov deleted the vvm/detailed_diff_v2_sets branch October 30, 2024 12:35
@pulumi-bot
Copy link
Contributor

This PR has been shipped in release v3.94.0.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
4 participants