Previously we used a single plan action "Replace" to represent both the
destroy-before-create and the create-before-destroy variants of replacing.
However, this forces the apply graph builder to jump through a lot of
hoops to figure out which nodes need it forced on and rebuild parts of
the graph to represent that.
If we instead decide between these two cases at plan time, the actual
determination of it is more straightforward because each resource is
represented by only one node in the plan graph, and then we can ensure
we put the right nodes in the graph during DiffTransformer and thus avoid
the logic for dealing with deposed instances being spread across various
different transformers and node types.
As a nice side-effect, this also allows us to show the difference between
destroy-then-create and create-then-destroy in the rendered diff in the
CLI, although this change doesn't fully implement that yet.
This allows a provider to retain arbitrary extra data in the plan and
make use of it during apply. The contents are not used by Terraform and
never shown to the user.
We shouldn't really need these because the plan is already filtered to
include diffs only for targeted resources, but we currently rely on this
to filter out non-resource items from the diff, and so we'll retain it
for now to avoid reworking how the apply-time graph builder works.
On the first pass here we erroneously assumed that this was redundant with
the backend settings embedded in the configuration itself. In practice,
users can override backend configuration when running "terraform init"
and so we need to record the _effective_ backend configuration.
Along with this, we also return the selected workspace name at the time
the plan was created so we'll later be able to produce a specialized error
for the situation of having the wrong workspace selected. This isn't
strictly required because we'll also check the lineage of the state, but
the error message that would result from that failure would be relatively
opaque and thus less helpful to the user.
This allows us to record the resource-to-provider associations we made
during the plan phase and ensure that we use the same config during
apply.
This isn't technically necessary, since we can in principle just repeat
the same matching algorithm against the config, but that algorithm is
relatively complicated and so if we execute it just once during plan we
remove the risk of bugs causing different decisions to be made during
the apply phase.
This also includes updates to the plan file format to include the provider
addresses. Since we've not actually shipped any version of Terraform
using our protobuf schema yet, we renumber here all of the fields after
the new one to keep them incrementing consecutively. This example should
not be followed after we have a released version of Terraform using this,
as a courtesy to anyone trying to parse these files (even though we're
not yet guaranteeing compatibility between releases).
The new format is radically different in than the old in physical
structure, but still has the same logical parts: the plan itself, a
snapshot of the input configuration, and a snapshot of the state as it
existed when the plan was created.
Rather than creating plan-specific serializations of state and config, the
new format instead leans on the existing file formats implemented
elsewhere, wrapping the result up in a zip archive with some internal file
naming conventions.
The plan portion of the file is serialized with protobuf, consistent with
our general strategy of replacing all use of encoding/gob with protobuf
moving forward.