Terraform
Use refresh-only mode to sync Terraform state
Terraform tracks information about the resources it manages in your workspace's
state file. When you apply changes to your resources with Terraform, it creates
an execution plan by comparing your workspace's configuration to its current
state. Refreshing your workspace's state updates Terraform's knowledge of your
infrastructure with the current state of your resources as reported by the
configured providers. Terraform plan and apply operations run an implicit
in-memory refresh as part of their operations, reconciling any drift from your
workspace's state before creating a plan for your infrastructure changes. You
can also plan and apply updates to your state file without making modifications to
your infrastructure using the -refresh-only flag.
In this tutorial, you will identify differences between your workspace's state
and your resources using the -refresh-only flag. You will also review
Terraform's implicit refresh behavior and the advantages of the -refresh-only
flag over the deprecated terraform refresh subcommand.
Prerequisites
You can complete this tutorial using the same workflow with either Terraform Community Edition or HCP Terraform. HCP Terraform is a platform that you can use to manage and execute your Terraform projects. It includes features like remote state and execution, structured plan output, workspace resource summaries, and more.
Select the HCP Terraform tab to complete this tutorial using HCP Terraform.
This tutorial assumes that you are familiar with the Terraform workflow. If you are new to Terraform, complete Get Started tutorials first.
In order to complete this tutorial, you will need the following:
- Terraform v1.1+ installed locally.
- An AWS account with local credentials configured for use with Terraform.
Clone example repository
Clone the sample repository for this tutorial.
$ git clone https://github.com/hashicorp-education/learn-terraform-refresh
Change into the repository directory.
$ cd learn-terraform-refresh
Review configuration
Open main.tf to review the sample configuration. It defines an EC2 instance
and a data source to identify the latest Amazon Linux AMI. The provider block
references the region input variable, which defaults to us-east-2.
main.tf
provider "aws" {
region = var.region
default_tags {
tags = {
hashicorp-learn = "refresh"
}
}
}
Create infrastructure
Initialize this configuration.
$ terraform init
Initializing the backend...
##...
Terraform has been successfully initialized!
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
Apply your configuration. Respond yes to the prompt to confirm the operation.
$ terraform apply
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
# aws_instance.server will be created
+ resource "aws_instance" "server" {
## ...
}
Plan: 1 to add, 0 to change, 0 to destroy.
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
aws_instance.server: Creating...
aws_instance.server: Still creating... [10s elapsed]
aws_instance.server: Still creating... [20s elapsed]
aws_instance.server: Creation complete after 22s [id=i-072ef122350d5a3e5]
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
Run a refresh-only plan
A common error scenario that can prompt Terraform to refresh the contents of your state file is mistakenly modifying your credentials or provider configuration. Simulate this situation by updating your AWS provider's region. You will then review the proposed changes to your state file from a Terraform refresh.
Create a terraform.tfvars file in your learn-terraform-refresh directory.
Open the file, and paste in the following configuration to override the default
region variable.
terraform.tfvars
region = "us-west-2"
Since you pass the region variable to your AWS provider configuration in
main.tf, this will reconfigure your provider for the us-west-2 region. The
resources you created earlier are still in us-east-2.
Run terraform plan -refresh-only to review how Terraform would update your state file.
$ terraform plan -refresh-only
aws_instance.server: Refreshing state... [id=i-072ef122350d5a3e5]
Note: Objects have changed outside of Terraform
Terraform detected the following changes made outside of Terraform since the last "terraform apply":
# aws_instance.server has been deleted
- resource "aws_instance" "server" {
## ...
}
This is a refresh-only plan, so Terraform will not take any actions to undo these. If you were expecting these changes then you can apply this plan to
record the updated values in the Terraform state without changing any remote objects.
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly these actions if you run "terraform apply" now.
Because you updated your provider for the us-west-2 region, Terraform tries
to locate the EC2 instance with the instance ID tracked in your state file but
fails to locate it since it's in a different region. Terraform assumes that you
destroyed the instance and wants to remove it from your state file.
If the modifications to your state file proposed by a -refresh-only plan were
acceptable, you could run a terraform apply -refresh-only and approve the
operation to overwrite your state file without modifying your infrastructure.
However, in this tutorial, refreshing your state file would drop your
resources, so do not run the apply operation.
Review Terraform's refresh functionality
In previous versions of Terraform, the only way to refresh your state file was
by using the terraform refresh subcommand. However, this was less safe than
the -refresh-only plan and apply mode since it would automatically overwrite
your state file without giving you the option to review the modifications
first. In this case, that would mean automatically dropping all of your
resources from your state file.
The -refresh-only mode for terraform plan and terraform apply operations
makes it safer to check Terraform state against real infrastructure by letting
you review proposed changes to the state file. It lets you avoid mistakenly
removing an existing resource from state and gives you a chance to correct your
configuration.
A refresh-only apply operation also updates outputs, if necessary. If you have
any other workspaces that use the terraform_remote_state data source to
access the outputs of the current workspace, the -refresh-only mode allows you
to anticipate the downstream effects.
In order to propose accurate changes to your infrastructure, Terraform first
attempts to reconcile the resources tracked in your state file with your actual
infrastructure. Terraform plan and apply operations first run an in-memory
refresh to determine which changes to propose to your infrastructure. Once you
confirm a terraform apply, Terraform will update your infrastructure and
state file.
Though Terraform will continue to support the refresh subcommand in future
versions, it is deprecated, and we encourage you to use the -refresh-only
flag instead. This allows you to review any updates to your state file. Unlike
the refresh subcommand, -refresh-only mode is supported in workspaces using
HCP Terraform as a remote backend, allowing your team to collaboratively
review any modifications.
Clean up resources
Now that you have reviewed the behavior of the -refresh-only flag, you will
destroy the EC2 instance you provisioned.
First, remove your terraform.tfvars file to use default value for the
region variable.
$ rm terraform.tfvars
Now run terraform destroy to destroy your infrastructure. Respond yes to
the prompt to confirm the operation.
$ terraform destroy
aws_instance.server: Refreshing state... [id=i-072ef122350d5a3e5]
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
- destroy
Terraform will perform the following actions:
# aws_instance.server will be destroyed
- resource "aws_instance" "server" {
## ...
}
Plan: 0 to add, 0 to change, 1 to destroy.
Do you really want to destroy all resources?
Terraform will destroy all your managed infrastructure, as shown above.
There is no undo. Only 'yes' will be accepted to confirm.
Enter a value: yes
aws_instance.server: Destroying... [id=i-072ef122350d5a3e5]
aws_instance.server: Still destroying... [id=i-072ef122350d5a3e5, 10s elapsed]
aws_instance.server: Still destroying... [id=i-072ef122350d5a3e5, 20s elapsed]
aws_instance.server: Still destroying... [id=i-072ef122350d5a3e5, 30s elapsed]
aws_instance.server: Destruction complete after 31s
Destroy complete! Resources: 1 destroyed.
If you used HCP Terraform for this tutorial, after destroying your resources,
delete the learn-terraform-refresh workspace from your HCP Terraform organization.
Next steps
You used Terraform's -refresh-only mode to safely compare your infrastructure
and state file. You also reviewed the implicit refresh behavior in standard
Terraform operations.
To learn more about managing state and drift, complete the following tutorials:
- Learn about how HCP Terraform's drift detection feature can help you make sure that your real resources match the Terraform state that tracks them.
- Manage Resource Drift
- Manage Resources in State
- Troubleshoot common issues with Terraform