Skip to main content
RunBook Academy

← All labs in Terraform

Lab · intermediate · ~25 min

Lab: Importing an Existing Resource

C · Simulation

Objectives

  • Create a file outside Terraform
  • Use terraform import to adopt the file
  • Write the configuration to match the state
  • Verify the plan is empty after the import

Prerequisites

Objective

By the end of this lab, you will have:

  • Created a file outside Terraform.
  • Used terraform import to adopt the file.
  • Written the configuration to match the state.
  • Verified the plan is empty after the import.

Requirements

  • A Linux or macOS workstation with shell access.
  • The Terraform CLI 1.9.x or later installed.

Scenario

A file has existed for a long time on the workstation. The team has decided to manage it with Terraform. The file is real. The configuration is empty. The import populates the state. The configuration is written to match.

Tasks

Task 1: Create the working directory

mkdir -p ~/rb-import-lab
cd ~/rb-import-lab

Task 2: Create the pre-existing file

echo "Configuration for the project." > ~/rb-import-lab/config.yaml
echo "version: 1.0" >> ~/rb-import-lab/config.yaml

Verify:

cat ~/rb-import-lab/config.yaml

Task 3: Write the empty configuration

Create main.tf:

terraform {
  required_version = ">= 1.9.0"
  required_providers {
    local = {
      source  = "hashicorp/local"
      version = "~> 2.5"
    }
  }
}

# The resource block declares the resource.
# The arguments will be filled in after the import.
resource "local_file" "config" {
  # filename and content will be filled in
}

Task 4: Initialise

terraform init

The provider is downloaded.

Task 5: Plan the adoption

terraform plan

The plan proposes to create the resource. Do not apply.

Task 6: Import the resource

terraform import local_file.config "${PWD}/config.yaml"

The output:

local_file.config: Importing from ID "/home/user/rb-import-lab/config.yaml"...
local_file.config: Import prepared!
  Prepared local_file for import
local_file.config: Refreshing state... [id=abc123def456]

Import successful!

The state has the resource.

Task 7: Inspect the state

terraform state show local_file.config

The state shows the attributes. Note the content and filename.

Task 8: Write the configuration to match

Edit main.tf to match the state:

resource "local_file" "config" {
  filename = "${path.module}/config.yaml"
  content  = <<EOF
Configuration for the project.
version: 1.0
EOF
}

Task 9: Plan the configuration

terraform plan

The plan is empty (or close to empty). The configuration matches the state matches the real world.

Task 10: Verify the file is unchanged

cat ~/rb-import-lab/config.yaml

The file content is unchanged.

Task 11: Verify the state has the resource

terraform state list

The state has the resource.

Task 12: Modify the configuration

Edit main.tf to change the content:

resource "local_file" "config" {
  filename = "${path.module}/config.yaml"
  content  = <<EOF
Configuration for the project.
version: 1.1
EOF
}

Run the plan:

terraform plan

The plan proposes to update the file.

Task 13: Apply the change

terraform apply

The file is updated.

cat ~/rb-import-lab/config.yaml

The file content is updated.

Validation

The lab is successful if:

  • The pre-existing file was adopted via terraform import.
  • The configuration was written to match the state.
  • The plan was empty after the import.
  • The file was not recreated.

Expected Outcome

At the end of the lab:

+---------------------------------+
| ~/rb-import-lab/                   |
|   .terraform/                    |
|   .terraform.lock.hcl            |
|   config.yaml                     |
|   main.tf                        |
+---------------------------------+

The config.yaml file is updated by Terraform. The state has the resource. The plan is empty.

Cleanup

cd ~/rb-import-lab
terraform destroy
rm -rf .terraform .terraform.lock.hcl terraform.tfstate*

The main.tf is the only artefact worth keeping.

What You Learned

You learned the import workflow:

  1. Pre-existing files are real. The file is on disk before Terraform knows about it.
  2. Import populates the state. The state is the source of truth for what Terraform believes.
  3. The configuration is written to match the state. The operators job is to write the configuration.
  4. The plan is empty after the import. The configuration matches the state matches the real world.
  5. Subsequent applies are normal Terraform. The resource is now managed by Terraform.

Deliverables

  • · A pre-existing file outside Terraform
  • · A terraform import adoption
  • · A configuration matching the state
  • · An empty plan after the import

Verification status

Last reviewed
2026-08-12
Executed end to end
not yet run on hardware

The commands and configuration here have been reviewed against the verified software versions, but nobody has run this lab start to finish on a system meeting its prerequisites. Treat the Expected Outcome as the intended result rather than an observed one, and keep the Cleanup section to hand.