Skip to main content

Import

Use the import block to import existing infrastructure resources into OpenTofu, bringing them under OpenTofu's management. Unlike the tofu import command, configuration-driven import using import blocks is predictable, works with CICD pipelines, and lets you preview an import operation before modifying state.

Once imported, OpenTofu tracks the resource in your state file. You can then manage the imported resource like any other, updating its attributes and destroying it as part of a standard resource lifecycle.

The import block records that OpenTofu imported the resource and did not create it. After importing, you can optionally remove import blocks from your configuration or leave them as a record of the resource's origin.

Syntax

You can add an import block to any OpenTofu configuration file. A common pattern is to create an imports.tf file, or to place each import block beside the resource block it imports into.

Code Block
import {
to = aws_instance.example
id = "i-abcd1234"
}

resource "aws_instance" "example" {
name = "hashi"
# (other resource arguments...)
}

The above import block defines an import of the AWS instance with the ID "i-abcd1234" into the aws_instance.example resource in the root module.

The import block has the following arguments:

If you do not set the provider argument, OpenTofu attempts to import from the default provider.

Import ID

The import block requires you to provide the id argument with a literal string of your resource's import ID. OpenTofu needs this import ID to locate the resource you want to import.

The identifier you use for a resource's import ID is resource-specific. You can find the required ID in the provider's documentation for the resource you wish to import.

Plan and apply an import

OpenTofu processes the import block during the plan stage. Once a plan is approved, OpenTofu imports the resource into its state during the subsequent apply stage.

To import a resource using import blocks, you must:

  1. Define an import block for the resource(s).
  2. Add a corresponding resource block to your configuration , or generate configuration for that resource.
  3. Run tofu plan to review how OpenTofu will import the resource(s).
  4. Apply the configuration to import the resources and update your OpenTofu state.

The import block is idempotent, meaning that applying an import action and running another plan will not generate another import action as long as that resource remains in your state.

OpenTofu only needs to import a given resource once. Attempting to import a resource into the same address again is a harmless no-op. You can remove import blocks after completing the import or safely leave them in your configuration as a record of the resource's origin for future module maintainers. For more information on maintaining configurations over time, see Refactoring.

Resource configuration

Before importing, you must add configuration for every resource you want OpenTofu to import. Otherwise, OpenTofu throws an error during planning, insisting you add resource configuration before it can successfully import. You can create resource configuration manually or generate it using OpenTofu.

We recommend writing a resource block if you know what most of the resource's arguments will be. For example, your configuration may already contain a similar resource whose configuration you can copy and modify.

We recommend generating configuration when importing multiple resources or a single complex resource that you do not already have the configuration for.

Add a resource block

Add a resource block for the resource to import. The resource address must match the import block's to argument.

Code Block
import {
to = aws_instance.example
id = "i-abcd1234"
}

resource "aws_instance" "example" {
name = "renderer"
}

Generate configuration

OpenTofu can generate HCL for resources that do not already exist in configuration. For more details, see Generating Configuration.

Examples

The following example demonstrates how to import into a module.

Code Block
import {
to = module.instances.aws_instance.example
id = "i-abcd1234"
}

The below example shows how to import a resource that includes count.

Code Block
import {
to = aws_instance.example[0]
id = "i-abcd1234"
}

The below example shows how to import a resource that includes for_each.

Code Block
import {
to = aws_instance.example["foo"]
id = "i-abcd1234"
}

Finally, the below example demonstrates how to import from a custom resource provider.

Code Block
provider "aws" {
alias = "europe"
region = "eu-west-1"
}

import {
provider = aws.europe
to = aws_instance.example["foo"]
id = "i-abcd1234"
}

Importing multiple resources

You can import multiple resources with one import block by using a for_each expression. This expression accepts a set, a tuple or a map and provides the each.key and each.value variables to access the individual elements.

In the example below, you can specify a list of server IDs to be imported. If you specify an empty list, the random_id resource will generate all IDs randomly. If you specify some IDs, the import block will import the specified IDs and the resource will randomly generate the rest. Note, the random_id resource requires the IDs to be in base64 format.

Code Block
variable "server_ids" {
type = list(string)
}

resource "random_id" "test_id" {
byte_length = 8
count = 2
}

import {
to = random_id.test_id[tonumber(each.key)]
id = each.value
for_each = {
for idx, item in var.server_ids: idx => item
}
}

output "id" {
value = random_id.test_id.*.b64_url
}