-
Couldn't load subscription status.
- Fork 10.1k
PSS: Let the init command recognise when there are no changes in configuration.
#37777
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
Conversation
…ing backend state (i.e. no changes)
…iltin and re-attached providers. This makes comparison easier when determining if config has changed since last init.
…d state_store config changes being tested
…a change, but handling this scenario isn't implemented yet
Previously dummy values were fine, but as tests using hashes to identify changes these values need to be accurate!
…der version as described in the backend state file fixture for the test.
…as a change, but handling this scenario isn't implemented yet
…ation in the same provider is detected as a change, but handling this scenario isn't implemented yet
…as a change, but handling this scenario isn't implemented yet
…ut handling this scenario isn't implemented yet
Just to avoid any confusion if copy-pasting happens in future.
…ull, and replace dummy hash values with correct values.
…ce would already exist in this scenario
…no-op for backend state
…& update test to not expect a value for region attr in provider config
We will allow downgrades to succeed as long as the schema version number is unchanged
| "hash": 2116468040 | ||
| }, | ||
| "hash": 2116468040 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a random observation - not a blocker - how is it that these two hashes match exactly? I thought that each hash represents a different part of the configuration, so should differ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah it's odd, but I double checked and the values are correct.
Using a debugger I found an explanation for why they match. To get hashes of the state_store and provider configs we use the (cty.Value) Hash method (used here in Core code). The (cty.Value) Hash method iterates through values to create a slice of bytes which are used to create the final hash number. The process of building those bytes for the hashes in this use case hits this code, which ignore the names of keys and only use values.
The end result is that, because both the state store and provider have 1 attr with the value "foobar", the bytes used to make the hash in both cases is:
"<"test_store";<"foobar";>;>"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah I'm half correct - the tuple is constructed in our calling code so we can make the hashes be distinct:
terraform/internal/configs/state_store.go
Lines 205 to 208 in cbda324
| pToHash := cty.TupleVal([]cty.Value{ | |
| cty.StringVal(b.Type), | |
| pVal, | |
| }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should address this, but in a separate PR
Edit: I've since changed this opinion, after we agreed that we should swap to a single hash for the whole state_store block in this discussion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All commits following this thread, barring removing unused code, are related to this thread.
internal/command/testdata/state-store-changed/state-store-type/.terraform/terraform.tfstate
Outdated
Show resolved
Hide resolved
… impacted by: state store config, provider config, state store type, provider source
…rovider block no longer has its own hash
…e provider block!
|
Ah there are still issues... |
…ted tests and test fixtures
…0 to indicate they're not set accurately.
| toHash := cty.TupleVal([]cty.Value{ | ||
| cty.StringVal(b.Type), // state store type | ||
| ssVal, // state store config | ||
|
|
||
| cty.StringVal(b.ProviderAddr.String()), // provider source | ||
| cty.StringVal(stateStoreProviderVersion.String()), // provider version | ||
| cty.StringVal(b.Provider.Name), // provider name - this is directly parsed from the config, whereas provider source is added separately later after config is parsed. | ||
| pVal, // provider config | ||
| }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Behold the beautiful new hash contents ✨
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's great in terms of comments and clarity 👍🏻 🌟
I am wondering why this is a tuple and why it contains just the values and not the attribute names but I think that is somewhat irrelevant to this PR. Just thinking out loud as I read through the code. 😅
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah this is something that I've copied from the original implementation of hashing for backends and haven't dug into that deeply. I can imagine the reason being that attribute names would be the same each time and not help with producing a unique hash per backend/state_store, and attribute names were less useful for hashing the 2 values from backends, too.
…hat's had a successful prior init using PSS
| } | ||
| }, | ||
| "hash": 12345 | ||
| "hash": 0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we persist zero hash and other values if the state store is being removed instead of removing the entire state_store object attribute from here?
Is that for some sort of consistency with how backends behave today?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I made the hash here zero just to make it really clear that the test fixture doesn't have a valid value for the hash, in case that affects anything in future.
The internal/command/testdata/state-store-to-backend test fixture is intended to be used testing what happens when a user swaps from using a state_store to using a backend. In that scenario the user would have previously run a successful init command, which produces this backend state file. In the intended test scenario, migrating to using a backend, the user would update the config to describe the new backend and then run an init command. This folder represents that in-between state where the config and the backend state file do not match, as the user hasn't run an init command since editing the config.
Does that make sense?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I made the hash here zero just to make it really clear that the test fixture doesn't have a valid value for the hash, in case that affects anything in future.
This was in response to having a painful experience needing to update test fixtures to have accurate hash values 😅
This PR allows the experimental PSS version of
initlogic recognise when there have been no changes since the last init, so init will perform a no-op (in regards to state storage, at least).I've added a test showing that init is a no-op in those circumstances :
TestInit_stateStore_configUnchangedI've also added tests showing that when backend state and config don't match we hit a
not configured yeterror diagnostic - seeTestInit_stateStore_configChanges. To do this I've created sets of test fixtures where the backend state file and config are not in agreement. A special case of this, upgraded provider versions, is inTestInit_stateStore_providerUpgrade.Changes covered:
internal/command/testdata/state-store-changed/store-configinternal/command/testdata/state-store-changed/provider-configinternal/command/testdata/state-store-changed/state-store-typeinternal/command/testdata/state-store-changed/provider-usedinternal/command/testdata/state-store-changed/provider-upgradedTarget Release
N/A
Rollback Plan
Changes to Security Controls
Are there any changes to security controls (access controls, encryption, logging) in this pull request? If so, explain.
CHANGELOG entry