Terraform Associate
Deep Dive
For the exam and for daily work, it's essential to know how to import existing infrastructure, debug issues with log levels, release stuck locks, and use tools like terraform console to inspect expressions.
Contents
The full import process has specific steps you need to know for the exam.
Identify the resource in the cloud
Get the resource ID from the cloud console or CLI. Each resource type has its own ID format (check the provider documentation).
Define the resource block in HCL
You MUST create the resource block in your .tf file BEFORE running terraform import. If the block doesn't exist, the import will fail.
Run terraform import
Command: terraform import <address> <real-id>. Terraform queries the cloud API, retrieves the current state, and writes it into the tfstate.
Run terraform plan
Compares what the tfstate says (actual state) against your resource block (desired configuration). There will almost always be differences.
Adjust the HCL code
Modify the resource block to match the actual configuration of the imported resource. Repeat plan until you see "No changes".
Verify and commit
With "No changes" in the plan, the resource is correctly imported and managed by Terraform.
# Full example: importing an existing VPC
# Step 1: Get the VPC ID from AWS
# aws ec2 describe-vpcs --query 'Vpcs[?Tags[?Key==`Name`&&Value==`legacy-vpc`]].VpcId'
# Output: "vpc-0abc123def456"
# Step 2: Create the resource block (minimum required)
# main.tf:
resource "aws_vpc" "legacy" {
cidr_block = "172.16.0.0/16" # real value — get it from the console
}
# Step 3: Import
terraform import aws_vpc.legacy vpc-0abc123def456
# Step 4: View the plan
terraform plan
# ~ aws_vpc.legacy (modify because attributes are missing)
# Step 5: Update the code with all the attributes
resource "aws_vpc" "legacy" {
cidr_block = "172.16.0.0/16"
enable_dns_support = true # adjust according to the plan
enable_dns_hostnames = true
tags = {
Name = "legacy-vpc"
}
}
# Repeat plan until you see: "No changes. Your infrastructure matches the configuration."
# ALTERNATIVE: import block + generate-config (Terraform 1.5+)
import {
to = aws_vpc.legacy
id = "vpc-0abc123def456"
}
terraform plan -generate-config-out=vpc_legacy.tf # automatically generates the resource block💡 ID formats by AWS resource type
| Resource | ID format |
|---|---|
| aws_instance | i-0123456789abcdef0 |
| aws_vpc | vpc-0abc123def456 |
| aws_s3_bucket | bucket-name |
| aws_iam_role | role-name |
| aws_security_group | sg-0abc123def456 |
| aws_db_instance | db-identifier |
⚠️ terraform taint has been deprecated since v0.15.2
terraform taint marked a resource to be recreated on the next apply, but without showing the plan first. It was replaced by terraform apply -replace=<address>, which is safer because it explicitly shows what will change before acting.
Before (deprecated)
# terraform taint — DO NOT use terraform taint aws_instance.web # Marks the resource but doesn't show the plan # The next apply destroys and recreates it # without you being able to review the change first
Now (modern)
# terraform apply -replace — use this terraform plan -replace=aws_instance.web # Shows the replacement plan first terraform apply -replace=aws_instance.web # Forces recreation of that specific resource # Multiple resources: terraform apply -replace=aws_instance.web -replace=aws_eip.web
🎯 For the exam
terraform taint has been deprecated since v0.15.2 — the exam may mention both, but the correct answer uses -replace-replace shows the plan before acting (symbol -/+ in the plan output)type.name or module.name.type.name for modulesTerraform uses environment variables to control the logging level. They're essential for debugging problems with providers or the core.
| Level | Verbosity | When to use |
|---|---|---|
| TRACE | Maximum — everything | Deep debugging. Shows every API call, full HTTP requests. Very verbose. |
| DEBUG | High | Detailed debugging. Shows internal decisions from the core and providers. |
| INFO | Medium | General information about the execution flow. Recommended for understanding what's happening. |
| WARN | Low — warnings | Warnings only. Non-critical situations that require attention. |
| ERROR | Minimal — errors only | Only critical errors that cause failures. |
| OFF | None (default) | No additional logging (default behavior). |
# Enable logging in the current session export TF_LOG=DEBUG terraform plan # Save logs to a file (without this, they go to stderr) export TF_LOG=TRACE export TF_LOG_PATH=/tmp/terraform-debug.log terraform apply # Separate Core and Provider logs (Terraform 0.15+) export TF_LOG_CORE=INFO # Terraform core logs export TF_LOG_PROVIDER=DEBUG # provider logs (calls to the AWS API, etc.) # Disable logging unset TF_LOG # Or: export TF_LOG=OFF # Windows PowerShell: $env:TF_LOG = "DEBUG" $env:TF_LOG_PATH = "C:\temp\tf-debug.log" terraform plan
🎯 For the exam
The order of verbosity from lowest to highest is: ERROR → WARN → INFO → DEBUG → TRACE. TF_LOG_PATH saves the logs to a file (without this they only go to stderr). TF_LOG_CORE and TF_LOG_PROVIDER let you control logging separately.
When a terraform apply is interrupted abruptly (kill, lost connection, crash), it can leave the state lock unreleased. terraform force-unlock manually releases that lock.
# Typical error when the state is locked: # Error acquiring the state lock: ConditionalCheckFailedException: ... # Lock Info: # ID: 3a1c2fa8-b5d9-4f71-a3c7-123456789abc ← this is the Lock ID # Path: terraform.tfstate # Operation: OperationTypeApply # Who: user@hostname # Version: 1.6.3 # Created: 2024-01-15 10:23:45 UTC # Info: # Release the lock with the ID shown in the error terraform force-unlock 3a1c2fa8-b5d9-4f71-a3c7-123456789abc # Confirm with -force (skips the interactive confirmation) terraform force-unlock -force 3a1c2fa8-b5d9-4f71-a3c7-123456789abc
⚠️ Verify there is no apply in progress before force-unlock
If you release a lock while another Terraform process is running (that you don't see), you can cause two applies to run simultaneously and corrupt the state. Before running force-unlock, verify that the process that set the lock has actually finished.
terraform providers
Lists all providers required by the current configuration and their installed versions.
terraform providers # Providers required by configuration: # . # ├── provider[registry.terraform.io/hashicorp/aws] ~> 5.0 # └── module.vpc # └── provider[registry.terraform.io/hashicorp/aws] >= 4.0 # Update the lock file for multiple platforms: terraform providers lock -platform=linux_amd64 -platform=darwin_arm64
terraform console
Interactive REPL for evaluating HCL expressions. Has access to the state and variables.
terraform console
> var.environment
"prod"
> max(3, 7, 2)
7
> join("-", ["api", "prod", "v1"])
"api-prod-v1"
> jsonencode({env = "prod"})
"{"env":"prod"}"
> cidrsubnet("10.0.0.0/16", 8, 1)
"10.0.1.0/24"
> Ctrl+C or Ctrl+D to exitTerraform runs operations in parallel when resources have no dependencies between them. The -parallelism flag controls how many concurrent operations are allowed.
# Default value: 10 concurrent operations terraform apply # Increase parallelism (faster but more load on the API) terraform apply -parallelism=20 # Reduce parallelism (useful if the cloud API has rate limiting) terraform apply -parallelism=5 # The same flag works with plan and destroy terraform plan -parallelism=15 terraform destroy -parallelism=5 # ⚠️ Increasing it too much can cause throttling errors on cloud APIs # AWS, Azure, and GCP all have rate limits on their APIs
| Environment variable | Purpose | Example |
|---|---|---|
| TF_LOG | Global logging level | TF_LOG=DEBUG |
| TF_LOG_PATH | File where logs are saved | TF_LOG_PATH=/tmp/tf.log |
| TF_LOG_CORE | Logging level for the core only | TF_LOG_CORE=INFO |
| TF_LOG_PROVIDER | Logging level for the provider only | TF_LOG_PROVIDER=TRACE |
| TF_VAR_name | Value of an input variable | TF_VAR_env=prod |
| TF_CLI_ARGS | Additional flags for all commands | TF_CLI_ARGS="-no-color" |
| TF_CLI_ARGS_plan | Additional flags only for terraform plan | TF_CLI_ARGS_plan="-refresh=false" |
| TF_DATA_DIR | Alternate directory for .terraform/ | TF_DATA_DIR=/tmp/tf-plugins |
Did you get this topic?
Test what you just learned
An engineer runs terraform apply and the process is interrupted by a network issue. When trying to run terraform plan again, they receive: 'Error acquiring the state lock'. What should they do?
Put what you learned to the test with original Terraform Associate exam questions.
Start Terraform Associate mock examUnlimited mock exams with the Pro plan
Log in to track your progress.