Terraform Import Block Generator

Generate import blocks from resource blocks. The id cannot be derived from your configuration, because it identifies the object in your cloud account, so this names the format instead of guessing the value.

Paste below, or drop a file anywhere on this panel

Or drop a file anywhere on this panel. Nothing is uploaded: the analysis runs in this tab.

The answer appears here

Paste on the left and press Generate. Nothing leaves this tab.

Examples

Real input you can load into the tool above. Each one shows a different thing going wrong, because that is what the tool is for.

A bucket and a queue

The queue is the interesting one: it imports by URL, not by name and not by ARN

resource "aws_s3_bucket" "logs" {
  bucket = "my-logs"
}

resource "aws_sqs_queue" "jobs" {
  name = "jobs"
}

A resource with for_each

One import block is not enough, and the error will not mention the missing key

resource "aws_subnet" "private" {
  for_each = var.subnets
  vpc_id   = var.vpc_id
}

Common mistakes

These are the ones that fail silently. The config is accepted, nothing raises an error, and the consequence arrives later.

  1. Using the resource name as the import id

    The id is whatever the provider uses to identify the object. A security group takes sg-..., not the group name, and the failure comes back from the cloud API as not-found.

    Instead:Check the Import section at the bottom of the provider's documentation page for that resource type.

  2. Writing one import block for a resource with for_each

    An import block targets a single instance, so an unindexed address refers to a resource that does not exist and the error does not mention the missing key.

    Instead:Write one block per key, with to = aws_subnet.private["that-key"].

  3. Reaching for terraform import instead

    It writes to state immediately with no plan to review, so a wrong id or a wrong address is discovered after the fact.

    Instead:Use import blocks on 1.5 or later. plan shows exactly what would be imported before anything changes.

Import blocks are planned before they are applied, unlike the old command

The difference is the whole reason to use them. terraform import mutates state immediately with nothing to review; an import block shows up in plan and changes nothing until apply.

The id is the provider's identifier, not the Terraform name

An S3 bucket imports by bucket name, an EC2 instance by i-0123..., a security group by sg-... rather than by group name, an IAM role by role name while an IAM policy takes an ARN, and an SQS queue by queue URL rather than by name or ARN. Getting it wrong produces a not-found from the cloud API rather than a Terraform error, so it reads like a permissions problem.

A resource with count or for_each needs one block per instance

An import block targets one object. to = aws_subnet.private with a for_each on the resource refers to something that does not exist, and the error names the address rather than the missing key. Write one block per key or index.

plan -generate-config-out writes the configuration for you

Point it at a file and Terraform emits resource blocks matching what it found, which saves transcribing forty arguments by hand. The output needs reconciling: it is exhaustive rather than idiomatic, and it includes computed values you do not want to declare.

Leaving the blocks in afterwards is harmless

A second apply sees the resource already in state and does nothing. Some teams remove them so the configuration describes only desired state; others keep them as a record. Both are fine, and drifting between the two is what causes arguments.

The to address includes the module path

A resource inside a module imports to module.network.aws_subnet.private, not to aws_subnet.private. Import blocks live in the root module and the address is absolute.

Terraform 1.5 is the floor

Before that, the only option is terraform import, one resource at a time, with no plan and no dry run. If you are importing more than a handful of resources, the upgrade pays for itself immediately.