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

state/remote: Don't persist snapshot for unchanged state #21811

Merged
merged 2 commits into from
Jun 20, 2019

Conversation

apparentlymart
Copy link
Contributor

Previously we would write to the backend for every call to PersistState, even if nothing changed since the last write, but update the serial only if the state had changed.

The Terraform Cloud & Enterprise state storage have a simple safety check that any future write with an already-used lineage and serial must be byte-for-byte identical. StatesMarshalEqual is intended to detect that, but it only actually detects changes the state itself, and not changes to the snapshot metadata.

Because we write the current Terraform version into the snapshot metadata during serialization, we'd previously have an issue where if the first state write after upgrading Terraform to a new version happened to change nothing about the state content then we'd write a new snapshot that differed only by Terraform version, and Terraform Cloud/Enterprise would then reject it.

The snapshot header is discarded immediately after decoding, so we can't use information from it when deciding whether to increment the serial. The next best thing is to skip sending no-op snapshot updates to the state client in the first place.

These writes are unnecessary anyway, and state storage owners have asked us in the past to elide these to avoid generating noise in their version logs, so we'll also finally meet those requests as a nice side-effect of this change.

We didn't previously have tests for the full flow of retrieving and then successively updating persisted state snapshots, so this includes a test which covers that logic and includes an assertion that a no-op update does not get written to the state client.

This fixes #21773.

These statemgr interfaces are the new names for the older interfaces in
the "state" package. These types alias each other so it doesn't really
matter which we use, but the "state" package is deprecated and we intend
to eventually remove it, so this is a further step in that direction.
Previously we would write to the backend for every call to PersistState,
even if nothing changed since the last write, but update the serial only
if the state had changed.

The Terraform Cloud & Enterprise state storage have a simple safety check
that any future write with an already-used lineage and serial must be
byte-for-byte identical. StatesMarshalEqual is intended to detect that,
but it only actually detects changes the state itself, and not changes
to the snapshot metadata.

Because we write the current Terraform version into the snapshot metadata
during serialization, we'd previously have an issue where if the first
state write after upgrading Terraform to a new version happened to change
nothing about the state content then we'd write a new snapshot that
differed only by Terraform version, and Terraform Cloud/Enterprise would
then reject it.

The snapshot header is discarded immediately after decoding, so we can't
use information from it when deciding whether to increment the serial.
The next best thing is to skip sending no-op snapshot updates to the state
client in the first place.

These writes are unnecessary anyway, and state storage owners have asked
us in the past to elide these to avoid generating noise in their version
logs, so we'll also finally meet those requests as a nice side-effect of
this change.

We didn't previously have tests for the full flow of retrieving and then
successively updating persisted state snapshots, so this includes a test
which covers that logic and includes an assertion that a no-op update does
not get written to the state client.
@apparentlymart apparentlymart requested a review from a team June 20, 2019 01:11
@apparentlymart apparentlymart self-assigned this Jun 20, 2019
@apparentlymart apparentlymart merged commit 85eda8a into master Jun 20, 2019
@apparentlymart apparentlymart deleted the b-push-state-no-changes branch June 20, 2019 13:18
@marcincuber
Copy link
Contributor

@apparentlymart I believe it is going to be part of the next release. When is it planned to be released?

@ghost
Copy link

ghost commented Jul 25, 2019

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 and limited conversation to collaborators Jul 25, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

State snapshot Conflict after upgrading from 0.12.1 to 0.12.2
3 participants