Introduction
Merging two states involves moving resources from one to the other using
terraform state mv [options] SOURCE DESTINATION
[a].
Note: Use the version of Terraform that matches the *desired end state* to perform the operations.
Procedure
1. Obtain both state files. If the configuration has an appropriate backend configuration, this can be done with
terraform state pull > source.tfstate
and terraform state pull > destination.tfstate
[b]
If no backend is configured, the state files can be downloaded directly from their backends (i.e., S3 bucket or Terraform Enterprise workspace).
2. Backup creation. Make a copy of both state files for backups.
3. Create a new, empty directory and place the two states that will be merged into it. This ensures that no initialized backend configurations or other state files may conflict with the following commands.
4. Identify which state will be the end state. In my example, I will use
destination.tfstate
it as the final state. I will move resources from source.tfstate
into destination.tfstate
.
5. View Resources. To view the existing resources in the destination state, use
terraform state list -state=destination.tfstate > destination-resources.txt
. Use terraform state list -state=source.tfstate > source-resources.txt
to view the existing resource in the source state. The `-state` flag is listed as legacy; however, it's necessary when working with two state files in one directory [c].
Note: All resource addresses must be unique if you wish for all resources in both states to be present in the merged/end state [d].
6. Move top-level resources and top-level modules. For each top-level resource (e.g.
aws_instance.foo
) and top-level modules (e.g. module.bar
) listed for source.tfstate
, perform a terraform state mv
to move the resource from the source to the destination [a].
Resources inside modules and modules inside modules (e.g.
module.bar.aws_instance.baz
and module.baz.module.qux
) do not require to be moved, as they will be moved along with the top-level modules.Example: Using the local backend, add options -state=source.tfstate -state-out=destination.tfstate
.
terraform state mv -state=source.tfstate -state-out=destination.tfstate aws_instance.foo aws_instance.foo
terraform state mv -state=source.tfstate -state-out=destination.tfstate module.bar module.bar
7. View source state and destination state files. Once all of the top-level resources and modules have been moved, the source state should be empty, which can be checked with
terraform state list -state=source.tfstate
. All resources should now exist in the destination state, which can be checked similarly with terraform state list -state=destination.tfstate
.
8. Open
destination.tfstate
in a text editor and increment the "serial" value by 1
.
9. Upload the new, merged state to its final destination. Either (1) Copy the state back to the backend destination manually, such as uploading the state to an S3 destination, or (2) upload the state to the backend destination of the merged configuration using
terraform state push
, or (3) use the Terraform Cloud / Enterprise API to create a new state version [e].
Example: Upload state to the backend destination using terraform state push command.
# In the directory where the combined configuration has been initialized using `terraform init`
terraform state push path/to/destination.tfstate
10. Review. The combined state is now in place and should be ready with a combined configuration. Use
terraform state list
to view the state list information from the state in the backend, which was just pushed. Run terraform plan
to see the results and ensure that they are as expected. If the configuration and the states were combined, this should likely show no changes.
If changes are proposed, and this is unexpected, then review the changes to determine the next steps. Either the state or the configuration will require additional modification. This can involve moving resources to different resource addresses, editing the configuration to match the state or other additional changes.
Links