terraform: don't prune state on init() #10504
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
During graph execution, there are steps that expect that a state isn't
being actively pruned out from under it. Namely: writing deposed states.
Writing deposed states has no way to handle if a state changes
underneath it because the only way to uniquely identify a deposed state
is its index in the deposed array. When destroying deposed resources, we
set the value to
<nil>
. If the array is pruned before the next deposeddestroy, then the indexes have changed, and this can cause a crash.
This PR does the following (with more details below):
init()
no longer prunes.ReadState()
always prunes before returning. I can't think of ascenario where this is unsafe since generally we can always START
from a pruned state, its just causing problems to prune
mid-execution.
Exported State APIs updated to be robust against nil ModuleStates.
Instead, I think we should adopt the following semantics for init/prune
in our structures that support it (Diff, for example). By having
consistent semantics around these functions, we can avoid this in the
future and have set expectations working with them.
init()
(in anything) will only ever be additive, and won't changeordering or existing values. It won't remove values.
prune()
is destructive, expectedly.Deserialization can prune, but it also might not. No expectation should be made either way and anything that uses a deserialized structure should expect either (basically same as last point here to be robust).
Serialization must not prune. We often serialize mid-execution to back up and pruning mid-execution is not allowed. If you must, then DeepCopy prior to serializing. Though in cases like State, this is prohibitively expensive.
Functions on a structure must not assume a pruned structure 100% of
the time. They must be robust to handle nils. This is especially
important because in many cases values such as
Modules
in stateare exported so end users can simply modify them outside of the
exported APIs.
This PR may expose us to unknown crashes but I've tried to cover our
cases in exposed APIs by checking for nil.