Import block
Import blocks are used when you want to import existing infrastructure component (or resources) into the Terraform statefile to bring them under Terraform management. Compared to using the Terraform import command, import blocks provide the ability to review the import operation before Terraform changes the statefile. The import block is available in Terraform v1.5.0 and later.
Once this resource is imported, Terraform will begin tracking it with the state file. You would then be able to manage this imported resource as you would any other, updating its attributes and destroying it if necessary.
Import block syntax
The syntax of a import block is as follows:
import {
id = <source-resource-address-from-infrastructure>
to = <target-resource-address-in-terraform-state>
}
resource resource_type <to> {
# specify only known arguments
}
Here is the breakdown of syntax:
id
: The ID of an already existing resource from your infrastructure that you want to import.
to
: This specifies the address of the resource in your Terraform state at which the imported resource will be inserted.
resource block
: This is where the imported infrastructure will be stored. The placeholder (<to>
) here should match theto
argument in the import block.
- The body of the resource block is where you would declare the known arguments for the imported resource. You should include only the arguments whose values are known, because Terraform would fill in the rest of the attributes from the resource being imported.
For instance, let's say you have an EC2 instance created manually in your infrastructure. To import that instance into your Terraform management (Terraform statefile), you would use the following import block:
import { id = "i-3456138463883" to = aws_instance.dummy_importing_resource } resource "aws_instance" "dummy_importing_resource" { name = "dev-server" instance_type = "t2.micro" # Other arguments if you known }
In the above case, the instance i-3456138463883 will be imported into aws_instance.dummy_importing_resource resource and the attributes defined in the above resource block are the known arguments for this resource.
Once the import operation runs, Terraform will do the following:
Terraform will perform the following actions:
# aws_instance.dummy_importing_resource will be imported
resource "aws_instance" "dummy_importing_resource" {
ami = "ami-abc123"
instance_type = "t2.micro"
name = "dev-server"
tags {
costcenter = "test"
}
credit_specification {
cpu_credits = "unlimited"
}
network_interface {
network_interface_id = "i-282223421"
device_index = 0
}
}
Plan: 1 to import ,0 to add, 0 to change, 0 to destroy.
When you use
terraform import <to> <id>
to bring manually created infrastructure into your Terraform state file, you'll encounter the following limitations:
- The imported resource's details will not be fully populated inside the Terraform output. In an output, you will not be able to view attributes of the resource like instance type, security groups, subnet IDs, and more.
- Once the infrastructure is imported into the Terraform statefile, you'll need to manually define the corresponding resource in your Terraform configuration file (
.tf
) accepting the resource. If you don't, Terraform will think the resource is "unmanaged" and will try to delete it on the next terraform apply execution. With this in mind, you need to include the resource in your configuration file, specifying required attributes and properties.
terraform import "aws_instance.dummy_importing_resource" i-3456138463883
aws_instance.dummy_importing_resource: Importing from ID "i-3456138463883"
aws_instance.dummy_importing_resource: Import prepared!
Import successful!
The resources that were imported are shown above. These resources are now in
your Terraform state and will henceforth be managed by Terraform.
The imported resource will populate attributes in the Terraform state file as follows:
{
"version" : 4
"terraform_version" : 1.5.0
"serial" : 8
"lineage" : 60dd9c0a-caa1-de0e
"outputs" : {}
"resource" : {
"mode" : "managed"
"type" : "aws_instance"
"name" : "dummy_importing_resource"
"provider" : "provider[\"registry.terraform.io/hashicorp/aws\"]"
"aws_security_group" : {
"instances" : {
"schema_version" : 0,
"sensitive_attributes" : [],
"attributes" : {
"id" = i-3456138463883
"ami" = "ami-abc123"
"instance_type" = "t2.micro"
"name" = "dev-server"
"tags" = [costcenter:"test"]
"credit_specification" = [cpu_credits: "unlimited"]
"network_interface" = [network_interface_id: "i-282223421", "device_index": 0]
}
}
}
}
}
Arguments in import block
The Following arguments are supported:
1. id
The id argument in the import block can be either literal string or an expression evaluating to a string. This provided value is an
unique identifier
of a resource you want to import into your Terraform statefile. The import ID needs to be known during the planning phase, meaning during terraform plan, for the whole thing to work. If the ID value, on the other hand, is known only after the resource has been applied (terraform apply), then the planning phase will fail with an error.
2. to
The to argument in the import block of Terraform is the destination address where the imported infrastructure will be kept in the Terraform statefile. If the specified address resource is not in the Terraform configuration, Terraform will return an error. You can prevent that by adding it yourself in the Terraform configuration or maybe let Terraform create it automatically with the flag
-generate-config-out
.
Meta Arguments of import Block
In Terraform, a meta-argument is a special kind of argument that can be used to customize the
behavior
of a resource block, Module block, and Data block.
Meta-arguments are the way to give you more control over how Terraform creates, updates, and destroys your infrastructure. Using them, you will be able to build complex and flexible configurations of the infrastructure.
Types of Meta Arguments Resource
Terraform provides several meta-arguments that can be utilized to customize the behavior of the import block. Import block supports the following two meta-arguments:
- for_each
- provider
1. for_each
Each instance is handled independently, with its own infrastructural object associated with it. This means each instance will be independently imported based on the changes you've made when applying your Terraform configuration.
Map Example
In the following example, we will use the for_each meta-argument with a map to import multiples AWS S3 buckets. We will then define a collected set of buckets operating under different names and regions, and Terraform will simply import the buckets for each of them.
local { buckets = { dev = "dev-bucket" staging = "stage-bucket" prod = "prod-bucket" } } import { for_each = tomap(locals.buckets) id = each.value to = aws_s3_bucket.s3[each.key] } resource "aws_s3_bucket" "buckets" { for_each = tomap(locals.buckets) name = each.value # Other arguments if you known }
The tomap() here is a Terraform function that converts a list of key-value pairs into a map. The for_each meta-argument will step through the map, importing one instance of the aws_s3_bucket resource for each key-value pair. The
each.key
and each.value
expressions are used to access the key and value of each pair, respectively.
Set Example
Here is an example where for_each is used on a set of strings to import many AWS RDS:
import { for_each = toset ([ "database-1", "database-2", "database-3" )] id = each.value to = aws_db_instance.database[each.key] } resource "aws_db_instance" "database" { for_each = toset ([ "database-1", "database-2", "database-3" )] allocated_storage = 10 engine = "mysql" instance_class = "db.t2.micro" db_name = each.key username = "myuser" password = "mypassword" }
Here, toset() is a Terraform function that takes a list of strings in and returns a set. The for_each meta-argument will iterate over that set and import one instance of the aws_db_instance resource for every string in that set. Finally, the
each.key
expression is used to access the string value of each item of that set using the db_names variable as the database name.
The provider Meta-Argument
The provider meta-argument in Terraform is special and is used to choose which provider configuration to use with a particular import block. It overrides Terraform's default behavior, which looks for a provider configuration with a matching
to
argument in import block.
By default, Terraform will automatically select a provider configuration based on the
to
argument in import block. For instance, if you declare the aws_instance.s3 in to
argument, it will automatically select the default AWS provider configuration. However, in some cases, you may wish to use a different provider configuration.
The provider meta-argument is available to set explicitly which provider configuration is used for a import block. It takes the form of adding the provider name and alias (when using multiple configurations of the one provider type) to the block declaration.
Provider Syntax
The syntax for using the provider meta-argument is:
<PROVIDER>.<ALIAS>
<PROVIDER>
: This is the name of provider such as "google", "aws", or "azure".
<ALIAS>
: This is the name of the configuration or alias for this provider. This is an optional part of this syntax. It is utilized to differentiate between configurations for the same provider, such as us-east1, europe, staging, and so on.
Example
Suppose you have two configurations of provider for AWS Cloud:
- First, there is the default AWS configuration, with its region set to "us-east-1".
- The other configuration would be an alternative to AWS with an alias named "europeregion" and a region set to "eu-west-1".
provider "aws" { region = "us-east-1" } provider "aws" { alias = "europeregion" region = "eu-west-1" }
Now you want to import an AWS instance, using the alternative "europeregion" configuration and not the default configuration. You can achieve that by adding the provider meta-argument to the import block declaration:
import { provider = aws.europeregion id = "i-3456138463883" to = aws_instance.importing_using_diff_provider } resource "aws_instance" "importing_using_diff_provider" { name = "server" instance_type = "t2.micro" # Other arguments if you known }
Here, the provider meta-argument has been used to specify that the import block should use this "europeregion" configuration instead of using the default configuration. In other words, the EC2 instance will be imported from "eu-west-1" region as defined in "europeregion".
Import Block Behavior
Import Block in Terraform have a special property called idempotence. With idempotence, once you import a resource, when you run terraform plan again, it does not recreate the import action. The resource remains in your Terraform state, and Terraform will not try to import it again.
It only needs to import a resource once in Terraform. If you import the same resource again to the same address, Terraform will just do nothing, that is, it will be a "no-op". This is harmless and won't cause any issues.
When you have imported a resource, you can safely remove the import block from your configuration because it is no longer useful, or You may choose to leave the import block in your configuration as a record of where the resource came from, which is helpful for any future maintainers of this module.
Generating configuration
Before you actually import a resource, you should also have an already defined configuration for that resource in your Terraform code. Otherwise, Terraform will equally throw an error at planning, asking you to add the configuration of such a resource before it can successfully import it.
Resources can be configured manually if you know most of its arguments. However, when many resources are to be imported or you are importing one resource which is complex and you don't have the config at hand, then it is better to generate the configuration for it.
To create the resource configuration, run the following command:
terraform plan -generate-config-out=<filename>.tf
Make sure to provide a new file path for the generated configuration. Do not supply an existing file path because Terraform will error. If any of the resources targeted by an import block do not yet exist in your current configuration, Terraform will generate and write the configuration for those resources to the file specified. Once the configuration is generated into the file, you can make changes in that configuration to add, remove, or variablize the arguments, if you want.
# Generating Resource in file import { id = "i-767267332573" to = aws_instance.generating_resource } # Importing infrastructure into defined Resource import { id = "i-3456138463883" to = aws_instance.known_ec2 } resource "aws_instance" "known_ec2" { name = "server" instance_type = "t2.micro" # Other arguments if you known }
terraform plan -generate-config-out=generatedfile.tf
Terraform will perform the following actions:
aws_instance.generating_resource: Preparing import... [id=i-767267332573]
aws_instance.generating_resource: Refreshing state... [id=i-767267332573]
# aws_instance.dummy_importing_resource will be imported
# (config will be generated)
resource "aws_instance" "generating_resource" {
ami = "ami-abc456"
instance_type = "t2.large"
name = "prod-server"
tags {
appname = "hoster"
}
# Other arguments
}
# aws_instance.known_ec2 will be imported
resource "aws_instance" "known_ec2" {
ami = "ami-abc123"
instance_type = "t2.small"
name = "server"
tags {
appname = "hoster"
}
# Other arguments
}
Plan: 2 to import, 0 to add, 0 to change, 0 to destroy.
Terraform has generated configuration and written it to generatedfile.tf. Please review the configuration and edit it as necessary before adding it to version control.
In this case, we do not know anything about arguments in the first scenario, so used Generating configuration by terraform method generates a file ./generatedfile.tf with the resource configuration. When we apply your Terraform configuration, the generating_resource (name given in
to
argument of that import block) resource generated in this file will be added to the statefile. In the second scenario, we know about the resource arguments, so we imported the infrastructure directly into the known_ec2 resource definition. Once you apply our Terraform configuration, the infrastructure being imported will be added into our state file.
Related Pages
Feedback
Was this page helpful?