Objective
By the end of this lab, you will have:
- Created a file outside Terraform.
- Used
terraform importto 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:
- Pre-existing files are real. The file is on disk before Terraform knows about it.
- Import populates the state. The state is the source of truth for what Terraform believes.
- The configuration is written to match the state. The operators job is to write the configuration.
- The plan is empty after the import. The configuration matches the state matches the real world.
- Subsequent applies are normal Terraform. The resource is now managed by Terraform.