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

allow plan data state comparison with legacy SDK #25857

Merged
merged 1 commit into from
Aug 19, 2020
Merged

Conversation

jbardin
Copy link
Member

@jbardin jbardin commented Aug 14, 2020

In order to determine if we need to re-read a data source during plan,
we need to compare the newly evaluated configuration with the stored
state. To do that we create a ProposedNewVal, which if there
are no changes, should match the existing state.

A problem arises if the remote data source contains any blocks, and they
are not set in the configuration. Terraform always decodes configuration
blocks as empty containers, however the legacy SDK cannot correctly
handle empty blocks and may return a null value which is saved to the
state. In order to correctly make the comparison for planning, we need
to reify those null blocks as empty containers in the cty value.

The createEmptyBlocks helper converts any null NestingList or NestingSet
blocks to empty list or set cty values. We only need to be concerned
with List and Set, because those are the only types that can be defined
with the legacy SDK. In hindsight these could have been normalized in
the legacy SDK shims had this problem been uncovered earlier, but for the
sake of compatibility we will now normalize these in core.

Fixes #25812

@jbardin jbardin added the core label Aug 14, 2020
@jbardin jbardin added this to the v0.13.1 milestone Aug 14, 2020
@jbardin jbardin requested a review from a team August 14, 2020 16:00
@codecov
Copy link

codecov bot commented Aug 14, 2020

Codecov Report

Merging #25857 into master will increase coverage by 0.01%.
The diff coverage is 84.31%.

Impacted Files Coverage Δ
terraform/eval_read_data_plan.go 83.33% <84.31%> (-0.88%) ⬇️
terraform/node_resource_plan.go 91.80% <0.00%> (-1.64%) ⬇️
states/statefile/version4.go 57.83% <0.00%> (+0.28%) ⬆️
backend/remote/backend_common.go 55.25% <0.00%> (+0.67%) ⬆️

@mildwonkey
Copy link
Contributor

mildwonkey commented Aug 14, 2020

I'm curious (as someone who doesn't know much of anything useful here): are there any concerns about how this might interact with providers not using the legacy SDK, or is that not a concern because those wouldn't (couldn't) get into this situation in the first place?

Edit: I saw this in the linked issue, thank you it's helpful info!

Unfortunately we don't have an indication at that point when the data source was using the legacy SDK, so any changes here need to take into account that they will apply to any new SDK versions as well.

@jbardin
Copy link
Member Author

jbardin commented Aug 14, 2020

The idea with this change is that a correctly functioning provider should not be able to get into this situation.

Since a block should never be decoded from the config as null in the first place, we should not have to compare between a null block and an empty block. So a theoretical non-legacy provider specifically returning null for a List or Set block in a data source would be an error, but that would need to be caught at ReadDataSource rather than here. Unfortunately we don't have a legacy flag to check for, so we can't catch it and be as strict as we would like, but because the comparison wold otherwise not make sense, we can safely normalize these to the expected empty value.

@jbardin jbardin force-pushed the jbardin/data-diffs branch from 4319f09 to a6c5f01 Compare August 14, 2020 17:23
In order to determine if we need to re-read a data source during plan,
we need to compare the newly evaluated configuration with the stored
state. To do that we create a ProposedNewVal, which if there are no
changes, should match the existing state exactly.

A problem arises if the remote data source contains any blocks, and they
are not set in the configuration. Terraform always decodes configuration
blocks as empty containers, however the legacy SDK cannot correctly
handle empty blocks and may return a null block which is saved to the
state. In order to correctly make the comparison for planning, we need
to reify those null blocks as empty containers in the cty value.

The createEmptyBlocks helper converts any null NestingList or NestingSet
blocks to empty list or set cty values. We only need to be concerned
with List and Set, because those are the only types that can be defined
with the legacy SDK. In hindsight these could have been normalized in
the legacy SDK shims had this problem been uncovered earlier, but for the
sake of compatibility we will now normalize these in core.
@jbardin jbardin force-pushed the jbardin/data-diffs branch from a6c5f01 to 93246bd Compare August 14, 2020 17:37
Copy link
Contributor

@mildwonkey mildwonkey left a comment

Choose a reason for hiding this comment

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

LGTM!

@jbardin jbardin merged commit 7ef4e7f into master Aug 19, 2020
@jbardin jbardin deleted the jbardin/data-diffs branch August 19, 2020 15:11
@ghost
Copy link

ghost commented Oct 11, 2020

I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues.

If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.

@ghost ghost locked as resolved and limited conversation to collaborators Oct 11, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Handle semantically equivalent changes from the legacy SDK when planning data sources
2 participants