website: Documentation about the one-to-one object binding assumption

Terraform's design assumes that each remote object in Terraform's care is
bound to one resource instance and one alone. If the same object is bound
to multiple instances then confusing behavior will often result, such as
two resource configurations competing to update a single object, or
objects being "left behind" when all existing Terraform deployments are
destroyed.

This assumption was previously only implied, though. This change is an
attempt to be more explicit about it, although these are additions to some
older documentation sections that have not been revised for some time and
so this is just a best effort to make this information discoverable
without getting drawn into a full-on reorganization of these sections.

While revising this there were some particular oddities that I decided to
revise while I was there, but I'll leave a fuller revision of this older
content for a later commit when we have more time to review it in greater
detail.
This commit is contained in:
Martin Atkins 2020-07-31 15:22:50 -07:00
parent 47dc40d229
commit 08ba58c8c8
5 changed files with 75 additions and 8 deletions

View File

@ -31,6 +31,14 @@ it is the zone ID (`Z12ABC4UGMOZ2N`). Please reference the provider documentatio
on the ID format. If you're unsure, feel free to just try an ID. If the ID
is invalid, you'll just receive an error message.
~> Warning: Terraform expects that each remote object it is managing will be
bound to only one resource address, which is normally guaranteed by Terraform
itself having created all objects. If you import existing objects into Terraform,
be careful to import each remote object to only one Terraform resource address.
If you import the same object multiple times, Terraform may exhibit unwanted
behavior. For more information on this assumption, see
[the State section](/docs/state/).
The command-line flags are all optional. The list of available flags are:
* `-backup=path` - Path to backup the existing state file. Defaults to

View File

@ -20,6 +20,14 @@ This is a great way to slowly transition infrastructure to Terraform, or
to be able to be confident that you can use Terraform in the future if it
potentially doesn't support every feature you need today.
~> Warning: Terraform expects that each remote object it is managing will be
bound to only one resource address, which is normally guaranteed by Terraform
itself having created all objects. If you import existing objects into Terraform,
be careful to import each remote object to only one Terraform resource address.
If you import the same object multiple times, Terraform may exhibit unwanted
behavior. For more information on this assumption, see
[the State section](/docs/state/).
## Currently State Only
The current implementation of Terraform import can only import resources

View File

@ -17,6 +17,14 @@ you can't yet point Terraform import to an entire collection of resources
such as an AWS VPC and import all of it. This workflow will be improved in a
future version of Terraform.
~> Warning: Terraform expects that each remote object it is managing will be
bound to only one resource address, which is normally guaranteed by Terraform
itself having created all objects. If you import existing objects into Terraform,
be careful to import each remote object to only one Terraform resource address.
If you import the same object multiple times, Terraform may exhibit unwanted
behavior. For more information on this assumption, see
[the State section](/docs/state/).
To import a resource, first write a resource block for it in your
configuration, establishing the name by which it will be known to Terraform:

View File

@ -21,6 +21,13 @@ infrastructure. Prior to any operation, Terraform does a
[refresh](/docs/commands/refresh.html) to update the state with the
real infrastructure.
The primary purpose of Terraform state is to store bindings between objects in
a remote system and resource instances declared in your configuration.
When Terraform creates a remote object in response to a change of configuration,
it will record the identity of that remote object against a particular
resource instance, and then potentially update or delete that object in
response to future configuration changes.
For more information on why Terraform requires state and why Terraform cannot
function without state, please see the page [state purpose](/docs/state/purpose.html).
@ -37,15 +44,40 @@ insulates users from any format changes within the state itself. The Terraform
project will keep the CLI working while the state format underneath it may
shift.
Finally, the CLI manages backups for you automatically. If you make a mistake
modifying your state, the state CLI will always have a backup available for
you that you can restore.
Terraform expects a one-to-one mapping between configured resource instances
and remote objects. Normally that is guaranteed by Terraform being the one
to create each object and record its identity in the state, or to destroy
an object and then remove the binding for it.
If you add or remove bindings in the state by other means, such as by importing
externally-created objects with `terraform import`, or by asking Terraform to
"forget" an existing object with `terraform state rm`, you'll then need to
ensure for yourself that this one-to-one rule is followed, such as by manually
deleting an object that you asked Terraform to "forget", or by re-importing it
to bind it to some other resource instance.
## Format
The state is in JSON format and Terraform will promise backwards compatibility
with the state file. The JSON format makes it easy to write tools around the
state if you want or to modify it by hand in the case of a Terraform bug.
The "version" field on the state contents allows us to transparently move
the format forward if we make modifications.
State snapshots are stored in JSON format and new Terraform versions are
generally backward compatible with state snapshots produced by earlier versions.
However, the state format is subject to change in new Terraform versions, so
if you build software that parses or modifies it directly you should expect
to perform ongoing maintenence of that software as the state format evolves
in new versions.
Alternatively, there are several integration points which produce JSON output
that is specifically intended for consumption by external software:
* [The `terraform output` command](/commands/output.html)
has a `-json` option, for obtaining either the full set of root module output
values or a specific named output value from the latest state snapshot.
* [The `terraform show` command](/docs/commands/show.html) has a `-json`
option for inspecting the latest state snapshot in full, and also for
inspecting saved plan files which include a copy of the prior state at the
time the plan was made.
A typical way to use these in situations where Terraform is running in
automation is to run them immediately after a successful `terraform apply`
to obtain a representation of the latest state snapshot, and then store that
result as an artifact associated with the automated run so that other software
can potentially consume it without needing to run Terraform itself.

View File

@ -34,6 +34,17 @@ support tags.
Therefore, for mapping configuration to resources in the real world,
Terraform uses its own state structure.
Terraform expects that each remote object is bound to only one resource
instance, which is normally guaranteed by Terraform being responsible for
creating the objects and recording their identities in the state. If you
instead import objects that were created outside of Terraform, you'll need
to check yourself that each distinct object is imported to only one resource
instance.
If one remote object is bound to two or more resource instances then Terraform
may take unexpected actions against those objects, because the mapping from
configuration to the remote object state has become ambiguous.
## Metadata
Alongside the mappings between resources and remote objects, Terraform must