-
Notifications
You must be signed in to change notification settings - Fork 9.6k
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
Fix panic from a null resources module in a state file #8120
Conversation
af4be59
to
2e69ec5
Compare
f955f98
to
4d55eab
Compare
I ended up squashing all the commits down here, since the there were too many change done and undone by the series of commits. This commit is a little large, but much easier to understand in isolation. |
4d55eab
to
9fddcb7
Compare
Fix checksum issue with remote state If we read a state file with "null" objects in a module and they become initialized to an empty map the state file may be written out with empty objects rather than "null", changing the checksum. If we can detect this, increment the serial number to prevent a conflict in atlas. Our fakeAtlas test server now needs to decode the state directly rather than using the ReadState function, so as to be able to read the state unaltered. The terraform.State data structures have initialization spread out throughout the package. More thoroughly initialize State during ReadState, and add a call to init() during WriteState as another normalization safeguard. Expose State.init through an exported Init() method, so that a new State can be completely realized outside of the terraform package. Additionally, the internal init now completely walks all internal state structures ensuring that all maps and slices are initialized. While it was mentioned before that the `init()` methods are problematic with too many call sites, expanding this out better exposes the entry points that will need to be refactored later for improved concurrency handling. The State structures had a mix of `omitempty` fields. Remove omitempty for all maps and slices as part of this normalization process. Make Lineage mandatory, which is now explicitly set in some tests.
9fddcb7
to
cdb80f6
Compare
@@ -713,7 +752,7 @@ type ModuleState struct { | |||
// Terraform. If Terraform doesn't find a matching ID in the | |||
// overall state, then it assumes it isn't managed and doesn't | |||
// worry about it. | |||
Dependencies []string `json:"depends_on,omitempty"` | |||
Dependencies []string `json:"depends_on"` |
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.
The normalization-serial-bump below will also cover these changes as well, yes?
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.
yes, since every ReadState checks WriteState for changes, we'll always bump the serial on a change.
Looking good on first pass! Trying to structure a "rule of thumb" going forward: never create a |
I don't want to commit yet to a global pattern for handling these, as I'd rather not have this api cruft leak out into provider-land. Right now it should be the case that |
Cool that all makes sense. This LGTM, but let's also get @jen20 to do a triple check here before merge. |
cc @jen20 or @mitchellh for double check review then I'll merge it 👍 |
LGTM. One thing we should probably look into in the future is exposing test helpers via I see there are a lot of ways that that wouldn't have helped but at least for "I need a ready to go state" those cases should ideally be centralized in a single function. This PR LGTM though! |
@@ -742,6 +743,20 @@ func TestRefresh_displaysOutputs(t *testing.T) { | |||
} | |||
} | |||
|
|||
// When creating an InstaneState for direct comparison to one contained in | |||
// terraform.State, all fields must be inintialized (duplicating the |
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.
Small typo here: initialized
, awesome work otherwise! :-)
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.
Good catch! Will fix on master.
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. |
https://gist.github.com/davidneudorfer/39bfdd1854384e57537fc0a5e3a4fc65
Make sure all maps and slices are initialized when reading a state file to prevent nil panics like above.
If we read a state file with "null" objects in a module and they become
initialized to an empty map the state file may be written out with empty
objects rather than "null", changing the checksum. If we can detect
this, increment the serial number to prevent a conflict in atlas.
Our fakeAtlas test server now needs to decode the state directly rather
than using the ReadState function, so as to be able to read the state
unaltered.
The terraform.State data structures have initialization spread out
throughout the package. More thoroughly initialize State during
ReadState, and add a call to init() during WriteState as another
normalization safeguard.
Expose State.init through an exported Init() method, so that a new State
can be completely realized outside of the terraform package.
Additionally, the internal init now completely walks all internal state
structures ensuring that all maps and slices are initialized. While it
was mentioned before that the
init()
methods are problematic with toomany call sites, expanding this out better exposes the entry points that
will need to be refactored later for improved concurrency handling.
The State structures had a mix of
omitempty
fields. Remove omitemptyfor all maps and slices as part of this normalization process. Make
Lineage mandatory, which is now explicitly set in some tests.