Terraform Import: Managing Existing Infrastructure with IaC
Terraform import allows you to bring existing cloud infrastructure under Terraform management without recreating resources, enabling gradual adoption of Infrastructure as Code.
What You'll Learn
In this tutorial, you will learn how to use Terraform import to adopt existing resources, use the import block for declarative imports, generate configuration from state, and import resources at scale.
Why It Matters
Most organizations have existing infrastructure created before IaC adoption. Recreating everything is risky and time-consuming. Import brings existing resources under Terraform management safely, enabling incremental migration without downtime.
Real-World Use
DodaTech imported over 200 existing AWS resources into Terraform management when adopting IaC. Durga Antivirus Pro's production database clusters, CDN distributions, and DNS zones were all imported without a single minute of downtime.
Import Command
The <a href="/devops/terraform/">terraform</a> import command attaches an existing resource to a Terraform resource block:
terraform import aws_instance.web i-0abcd1234efgh5678
Expected output:
aws_instance.web: Importing from ID "i-0abcd1234efgh5678"...
aws_instance.web: Import prepared!
aws_instance.web: Refreshing state...
Import successful!
The resource is now tracked in state. However, the configuration block must exist before importing.
Prerequisite: Configuration Block
Create a matching resource block in your configuration before importing:
resource "aws_instance" "web" {
# Arguments will be populated after import
}
Expected output: After import, <a href="/devops/terraform/">terraform</a> plan shows the configuration differs from the imported resource. Copy the state attributes into the configuration to converge.
Import Block (Terraform 1.5+)
The import block provides a declarative way to import resources:
import {
to = aws_instance.web
id = "i-0abcd1234efgh5678"
}
import {
to = aws_s3_bucket.data
id = "existing-data-bucket"
}
resource "aws_instance" "web" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
}
resource "aws_s3_bucket" "data" {
bucket = "existing-data-bucket"
}
Expected output: Running <a href="/devops/terraform/">terraform</a> plan shows the import as part of the plan. Running <a href="/devops/terraform/">terraform</a> apply executes the import alongside any resource changes.
Import Blocks at Scale
locals {
instances = {
web = "i-0abcd1234efgh5678"
worker = "i-0efgh5678ijkl9012"
batch = "i-0ijkl9012mnop3456"
}
}
resource "aws_instance" "this" {
for_each = local.instances
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
}
import {
for_each = local.instances
to = aws_instance.this[each.key]
id = each.value
}
Expected output: All three instances are imported in a single apply. The for_each on the import block mirrors the resource's for_each.
Generating Configuration
After import, generate the resource configuration from the state:
terraform show -no-color > imported.tf
Expected output: The <a href="/devops/terraform/">terraform</a> show command outputs the full configuration with all attributes. You can extract resource blocks and copy them into your configuration files.
Using Terraform Config Inspect
terraform providers schema -json | jq '.resource_schemas["aws_instance"].block'
Expected output: The JSON schema for the AWS instance resource shows all attributes, their types, and whether they are required or computed.
Bulk Import Strategy
For importing many resources, use a scripted approach:
# List all EC2 instances via AWS CLI
aws ec2 describe-instances --query 'Reservations[*].Instances[*].[InstanceId,Tags[?Key==`Name`].Value|[0]]' --output text | while read id name; do
cat > "import-${name}.tf" << EOF
import {
to = aws_instance.${name}
id = "${id}"
}
EOF
done
Expected output: One import block file per EC2 instance. Run <a href="/devops/terraform/">terraform</a> apply to import all instances with a single command.
State Operations for Import
List Resources in State
terraform state list
Expected output: Shows all resources currently tracked in state, including imported ones.
Remove Imported Resources
terraform state rm aws_instance.web
Expected output: Removes the resource from state without destroying it. The resource exists but Terraform no longer manages it.
Common Mistakes
1. Importing Without Configuration
Running <a href="/devops/terraform/">terraform</a> import without a matching resource block fails. Create the resource block first.
2. Missing Required Arguments
After import, <a href="/devops/terraform/">terraform</a> plan shows changes because required arguments differ from the imported resource. Copy state attributes to converge.
3. Not Backing Up State Before Bulk Import
Bulk imports can corrupt state if interrupted. Back up state before running large imports.
4. Importing Resources That Belong to Another Configuration
Resources already managed by another Terraform configuration cause state conflicts. Verify ownership before importing.
5. Forgetting to Update Configuration After Import
Imported resources remain in state but diverge from configuration. Always update configuration to match the resource after import.
Practice Questions
1. What does <a href="/devops/terraform/">terraform</a> import do?
Attaches an existing cloud resource to a Terraform resource block, adding it to the state file without modifying the resource.
2. What is the advantage of the import block over the <a href="/devops/terraform/">terraform</a> import command?
The import block is declarative, supports for_each, and runs as part of <a href="/devops/terraform/">terraform</a> plan and <a href="/devops/terraform/">terraform</a> apply.
3. How do you generate Terraform configuration from an imported resource?
Run <a href="/devops/terraform/">terraform</a> show -no-color to view the full state, then extract resource attributes into configuration files.
4. Why do you need a resource block before importing?
The resource block provides the address (aws_instance.web) that the import command attaches to. Without it, there is no address.
5. Challenge: Create an S3 bucket through the AWS console, then import it into Terraform using the import block, generate configuration, and verify <a href="/devops/terraform/">terraform</a> plan shows no changes.
Mini Project: Infrastructure Migration
Create an EC2 instance through the AWS CLI or console. Write a Terraform configuration that manages it. Use the import block to bring it under Terraform management. Generate the configuration from state, verify a clean plan, then add a tag through Terraform.
Related Concepts
What's Next
Master Terraform import to adopt existing infrastructure, then learn Testing to validate configurations with validate, fmt, tflint, and tfsec.
Built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro