The -refresh-only option for terraform plan and terraform apply was introduced in Terraform v0.15.4. For prior versions you must use terraform refresh. It reads the current settings from all managed remote objects and updates the Terraform state to match. Automatically applying the effect of a refresh is risky. If you have misconfigured credentials for one or more providers, Terraform may be misled into thinking that all of the managed objects have been deleted, causing it to remove all of the tracked objects without any confirmation prompt.
The -refresh-only command presents an interactive prompt for you to review the changes that Terraform has detected before committing them to the state.
Please visit my GitHub Repository for Terraform articles on various topics being updated on constant basis.
Let’s get started!
Objectives:
1. Login to AWS Management Console
2. Create infrastructure for resources block
3. Under terraform_files resources directory - Create subfolder - S3.
- Under S3 sub-folder - Create
dynamodb.tf
ands3-bucket.tf
.
4. Deploy Your Backend Resources
5. Under terraform_files resources directory - Create sub-folder - Terraform.
- Under Terraform sub-folder, Create 5 files -
backend.tf
,main.tf
,variables.tf
,outputs.tf
andterrafprm.tfvars
.
6. Create Your Resources
- Under Terraform sub-folder, Create 5 files -
backend.tf
,main.tf
,variables.tf
,outputs.tf
andterraform.tfvars
.
7. Troubleshoot Error
Pre-requisites:
- AWS user account with admin access, not a root account.
- Cloud9 IDE with AWS CLI.
Resources Used:
Terraform documentation.
Terraform documentation for AMI.
What is Amazon S3?.
What is Amazon DynamoDB?
Use refresh-only mode to sync Terraform state
Steps for implementation to this project:
1. Login to AWS Management Console
- Make sure you're in the N. Virginia (us-east-1) region
2. Create infrastructure for resources block
- Let’s create the following organizational structure as shown below.
3. Under terraform_files resources directory - Create subfolder - S3.
- Under S3 sub-folder - Create
dynamodb.tf
ands3-bucket.tf
.
dynamodb.tf
resource "aws_dynamodb_table" "dynamodb-terraform-state-lock" {
name = "backend-state-lock-dynamo"
hash_key = "LockID"
read_capacity = 20
write_capacity = 20
attribute {
name = "LockID"
type = "S"
}
}
- Dynamo DB Name - backend-state-lock-dynamo
s3.tf
provider "aws" {
region = "us-east-1"
}
resource "aws_s3_bucket" "revmybucket" {
bucket = "revbucket123456"
}
- bucket name - revbucket123456
4. Deploy Your Backend Resources
Now run these Terraform commands in the following order:
- Run terraform version displays the current version of Terraform and all installed plugins.
- Run terraform fmt to format the code.
- Run terraform init to initialize Terraform.
- Run terraform validate to check for any syntax errors.
- Run terraform plan to see what resources will be created.
- Run terraform apply executes the actions proposed in a terraform plan and type yes when prompted.
- Run terraform apply --auto-approve flag will prevent Terraform from prompting you to enter yes explicitly before it deploys the code.
- s3 bucket - revbucket123456
- dynamodb table - backend-state-lock-dynamo, no backend state file created
- terraform.tfstate file
5. Under terraform_files resources directory - Create sub-folder - Terraform.
Under Terraform sub-folder, Create 5 files -
backend.tf
,main.tf
,variables.tf
,outputs.tf
andterraform.tfvars
.1. backend.tf
substitute your bucket name and dynamodb table name
terraform {
backend "s3" {
encrypt = true
bucket = "revbucket123456"
dynamodb_table = "backend-state-lock-dynamo"
key = "backend.tfstate"
region = "us-east-1"
}
}
- 2. main.tf
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.23"
}
}
required_version = ">= 0.14.9"
}
provider "aws" {
profile = "default"
region = var.region
}
data "aws_ami" "linux" {
most_recent = true
owners = ["amazon"]
filter {
name = "name"
values = ["amzn2-ami-hvm-*-x86_64-gp2"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
}
resource "aws_instance" "app_server" {
ami = data.aws_ami.linux.id
instance_type = var.instance_type
availability_zone = var.az_1a
tags = {
Name = var.instance_name
}
}
- 3. variables.tf
variable "region" {
description = "region"
type = string
default = "us-east-1"
}
variable "az_1a" {
description = "availability zone 1"
type = string
default = "us-east-1a"
}
variable "instance_type" {
description = "Value of the Name tag for the EC2 instance type"
type = string
default = "t2.micro"
}
variable "instance_name" {
description = "Value of the Name tag for the EC2 instance"
type = string
default = "MyInstance"
}
- 4. outputs.tf
output "instance_id" {
description = "ID of the EC2 instance"
value = aws_instance.app_server.id
}
output "instance_ip" {
description = "Public IP address of the EC2 instance"
value = aws_instance.app_server.public_ip
}
output "instance_name" {
description = "Name of the EC2 instance"
value = aws_instance.app_server.tags.Name
}
- 5. terraform.tfvars
name = "rev"
#region = "us-west-1"
6. Create Your Resources
cd terraform
Now run these Terraform commands in the following order:
- Run terraform version displays the current version of Terraform and all installed plugins.
- Run terraform fmt to format the code.
- Run terraform init to initialize Terraform.
- Run terraform validate to check for any syntax errors.
- Run terraform plan to see what resources will be created.
- Run terraform apply executes the actions proposed in a terraform plan and type yes when prompted.
- Run terraform apply --auto-approve flag will prevent Terraform from prompting you to enter yes explicitly before it deploys the code.
- s3 bucket - revbucket123456, file - backend.tfstate
- dynamodb table - backend-state-lock-dynamo, backend state file created
7. Troubleshoot Error
"In Terraform, refreshing your state file updates Terraform's knowledge of your infrastructure, as represented in your state file, with the actual state of your infrastructure. Terraform plan and apply operations run an implicit in-memory refresh as part of their functionality, reconciling any drift from your state file before suggesting infrastructure changes."
You can update your state file without making modifications to your infrastructure using the -refresh-only flag for plan and apply operations.
This allows you to review any updates to your state file.
Uncomment the region value by removing the hashtag in terraform.tfvars
#region = "us-west-1"
region = "us-west-1"
- run
terraform plan -refresh-only
Because you updated your provider for the us-west-1 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.
Comment the region value by removing the hashtag in terraform.tfvars
region = "us-west-1"
#region = "us-west-1"
- run
terraform plan -refresh-only
- You should now see the following message, "No changes. Your infrastructure still matches the configuration."
Cleanup
- delete the file - backend.tfstate from bucket
terraform destroy
What we have done so far
We have successfuly deployed backend and AWS resources. We reviewed the changes that Terraform has detected before committing them to the state using Terraform refresh-only command, thus demonstated the advantages of when to use that command.
Top comments (0)