-
Statefile Backup:
- If stored locally, the
tfstate.backup
file contains the previous terraform apply results. - If storing in a remote backend, make sure to enable versioning to be able to roll back.
- If your apply operation fails without saving the state file to the remote backend, terraform will save the file locally under the name
errored.tfstate
. You can set up appropriate steps to save this file from your pipeline or CI Server. Alternatively, you can push this state file to the remote backend byterraform state push errored.tfstate
- If your pipeline crashes during the process, the state file may remain locked. In this case, you can run
terraform force-unlock <LOCK_ID>
- If stored locally, the
-
Import existing resources or Handle Manual changes to managed resources: 2.1. How to import a resource configuration for managing via terraform
- Step-1: Create an empty resource block in the terraform file
resource "aws_security_group" "to_be_imported" { # fill later after import }
- Step-2: Run
terraform import <resource_type>.<resource_name> <resource_id>
(For example, aws_security_group.example sg-12345) - Step-3: After the configurations get imported into your state file, run
terraform show
orterraform state show <resource_type>.<resource_name>
- Step-4: Clean up the output-only attributes like
id
,arn
,timestamp
, etc., and add the code block to the terraform configuration file.
- If you had made manual changes to your terraform-managed resource, you could update your statefile by running
terraform apply --refresh-only
orterraform refresh
Other options: For bulk import of resources, you can use tools like
terraformer
&terracognita
-
Avoid Resource modification/deletion (useful for imported/critical resources):
- Option 1: Add a lifecycle block to your code:
lifecycle { ignore_changes = [cidr_block] # or any specific resource config prevent_destroy = true }
- Option 2: Manually remove the resource configuration from the state file.
terraform state rm aws_instance.example
- Option 1: Add a lifecycle block to your code:
- Basic Input Validation: Use
validation
blockvariable "public_ip" { description = "Public IP address for the service" type = string validation { condition = can(regex("^(([0-9]{1,3}\\.){3}[0-9]{1,3})$", var.public_ip)) && length(split(".", var.public_ip)) == 4 && alltrue([for octet in split(".", var.public_ip) : tonumber(octet) <= 255]) error_message = "The Public IP address must be in the format x.x.x.x where x is a number between 0 and 255." } }
- For complex conditions on created resource: Use
condition
block underlifecycle
block. - For more examples, check here.
-
Enforce Default Tags: You can set up default tags during the provider configuration.
provider "aws" { region = "something" default_tags { tags = { deployment = "terraform" } } }
- This adds the mentioned tag if no tag is specified in your resource or module.
- Alternatively, you can use policy as code like OPA, terratest to check your code. For reference, click here
-
Instructions before refactoring existing code:
- Modifying the names of the existing resource/module block may trigger changes causing downtime. So, follow appropriate procedures to move the state file resource configurations using one of the below-mentioned steps:
- State move command:
terraform state mv <OLD_BLOCK_REFEERENCE> <NEW_REFERENCE>
- Use
moved
block:
moved { from = aws_instance.something to = aws_instance.myserver }
-
Force Re-creation of resource: Use either -
-replace
flag with plan or apply step. For ex:terraform apply -replace="aws_something.example"
-
Troubleshooting: Set
TF_LOG
to any debugging level (say, DEBUG) environment variable output. To store the logs in a persistant file, useTF_LOG_PATH
, if not mentioned, you will see the debugging output in the terraform CLI. -
Reference to another state file:
- Use case: Access outputs and resource attributes of another terraform deployment.
- Example:
data "terraform_remote_state" "example" { # For locally stored state files # backend = "local" # config = { # path = "..." # } # For remote backends: backend = "s3" config = { bucket = "my-bucket" key = "example/firewalls/terraform.tfstate" region = "us-east-1" } }
Some parts of this repository contains the codes used for learning purposes from Terraform: Up and Running, originally authored by Yevgeniy Brikman and licensed under the MIT License.