Objective
By the end of this lab, you will have:
- Created a configuration with a file resource.
- Simulated drift by manually editing the file.
- Used
terraform refreshto update the state. - Used a refresh-only plan to detect drift.
- Verified the state is consistent with the real world.
Requirements
- A Linux or macOS workstation with shell access.
- The Terraform CLI 1.9.x or later installed.
Scenario
You have a configuration that creates a file. The file is managed by Terraform. An engineer manually edits the file without going through Terraform. The drift is intentional from the engineers perspective. The right response is to update the configuration to match the drift.
Tasks
Task 1: Create the working directory
mkdir -p ~/rb-refresh-lab
cd ~/rb-refresh-lab
Task 2: Initial configuration
Create main.tf:
terraform {
required_version = ">= 1.9.0"
required_providers {
local = {
source = "hashicorp/local"
version = "~> 2.5"
}
}
}
resource "local_file" "readme" {
filename = "${path.module}/README.md"
content = "Initial content.\n"
}
Task 3: Initialise and apply
terraform init
terraform apply
Verify the file:
cat ~/rb-refresh-lab/README.md
Task 4: Simulate drift
An engineer manually edits the file to add a section:
cat > ~/rb-refresh-lab/README.md <<EOF
# Project README
This project is managed by Terraform.
## Manual section
This section was added by an engineer manually.
EOF
The drift is simulated. The state has the old content; the real world has the new content.
Task 5: Plan without refresh
terraform plan
The plan proposes to update the file to the configured content. The drift is detected.
Task 6: Refresh-only plan
terraform plan -refresh-only
The plan refreshes the state and detects the drift. The output shows the new attributes.
Task 7: Refresh the state
terraform refresh
The state is updated to match the real world. The file on disk is unchanged.
Task 8: Verify the state
terraform state show local_file.readme
The state has the new content (with the manual section).
Task 9: Plan after refresh
terraform plan
The plan is empty (or close to empty). The state matches the real world.
Task 10: Update the configuration to match the drift
The drift is intentional. Update the configuration to match:
resource "local_file" "readme" {
filename = "${path.module}/README.md"
content = <<EOF
# Project README
This project is managed by Terraform.
## Manual section
This section was added by an engineer manually.
EOF
}
Run the plan:
terraform plan
The plan is empty.
Task 11: Verify the configuration
terraform plan
The plan is empty. The configuration matches the state matches the real world.
Validation
The lab is successful if:
- The drift was simulated.
- The refresh updated the state.
- The plan was empty after the refresh.
- The configuration was updated to match the drift.
- The final plan was empty.
Expected Outcome
At the end of the lab:
+---------------------------------+
| ~/rb-refresh-lab/ |
| .terraform/ |
| .terraform.lock.hcl |
| README.md |
| main.tf |
+---------------------------------+
The README.md file is updated to match the configuration.
The state is consistent with the real world.
Cleanup
cd ~/rb-refresh-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 refresh workflow:
- Refresh updates state from the real world. It does not modify the real world.
- Refresh-only plan is the safest drift detection. It does not propose changes.
- Drift is information, not inconvenience. The decision is the engineer’s.
- Update the configuration to match the drift. The intentional drift is now part of the configuration.
- The plan is empty after the drift is accepted. The configuration matches the state matches the real world.