Back to top
GuidesOverview

Terraform Associate 004

Practice now
HashiCorpAssociateFree~45 min read

Complete guide
Terraform Associate 004

Tap any service to see more details and official docs.

D1

IaC and the purpose of Terraform

15% of the exam

What is Infrastructure as Code?

IaC is the practice of defining and managing infrastructure through machine-readable configuration files, instead of manual configuration or UI tools. Files are versioned in VCS just like application code.

FeatureManual / ConsoleIaC with Terraform
ReproducibilityDepends on the operatorIdentical on every run
VersioningNoGit — full history
ReviewNo diff availablePull request with terraform plan
CollaborationOne operator at a timeMultiple via VCS + locking
RollbackManual, error-pronegit revert + apply
DocumentationImplicitThe code IS the documentation

Advantages of Terraform's declarative approach

Declarative

You describe the DESIRED state, not the steps. Terraform computes the diff and determines the necessary actions.

Provider-agnostic

One language (HCL) for AWS, Azure, GCP, Kubernetes, Datadog, GitHub and hundreds more providers.

Idempotent

Running apply multiple times produces the same result — if it already exists, it isn't recreated.

Dependency DAG

Terraform builds a dependency graph and applies changes in parallel when it is safe to do so.

Terraform vs other IaC tools

ToolTypeWhen to use it
TerraformDeclarative · multi-cloudManaging cloud/on-prem infrastructure. Any provider.
AnsibleProcedural · agentlessOS configuration, software installation, server state management.
CloudFormationDeclarative · AWS onlyAWS infrastructure for teams that don't need multi-cloud.
PulumiDeclarative · multi-cloudSame role as Terraform but using programming languages (Python, TypeScript).
Chef/PuppetProcedural · agent-basedConfiguration management for server fleets with an installed agent.

Terraform is complementary to Ansible, not a competitor. Terraform creates the infrastructure (VMs, networks, DBs). Ansible configures what's inside (installs packages, configures apps). On the exam: Terraform = provisioning, Ansible = configuration management.

D2

Core workflow

11% of the exam

Write → Plan → Apply

Terraform's standard workflow. Each stage has a clear purpose and the order is always the same.

1. Write

Define resources in .tf files with HCL

2. Plan

Terraform shows what will change without applying

3. Apply

Applies the changes and updates the state

Main commands

Click any service to see more details

Additional lifecycle commands

CommandFunction
terraform fmtFormats .tf files to the canonical HCL style. Equivalent to prettier.
terraform validateValidates the configuration's syntax and consistency WITHOUT calling the provider API.
terraform apply -replace=addrForces recreation of a specific resource (replaces terraform taint, deprecated since v0.15.2).
terraform plan -refresh-onlyDetects drift between state and reality without applying configuration changes (replaces terraform refresh, deprecated since v0.15.4).
terraform outputShows the outputs defined in the current state.
terraform showShows the state or a saved plan in a human-readable format.
terraform graphGenerates the dependency graph in DOT format (viewable with Graphviz).
terraform force-unlockManually releases a state lock when an apply failed partway through.
terraform loginAuthenticates with HCP Terraform and stores credentials locally.

On the exam: terraform fmt and terraform validate are safe to run at any time — they don't touch real infrastructure or the state. They're pre-plan quality steps.

D3

Providers and configuration

12% of the exam

Plugin architecture

Terraform Core communicates with providers via RPC. Each provider is a separate binary downloaded during init. This architecture decouples Terraform from each provider's release cycle.

Click any service to see more details

Provider configuration

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

provider "aws" {
  region = var.aws_region
}

# Provider with alias for multiple regions
provider "aws" {
  alias  = "us_east"
  region = "us-east-1"
}
ConstraintMeaningExample
= 5.0.0Exactly that version= 5.0.0
!= 5.0.0Anything except that one!= 4.0.0
> 5.0Greater than> 5.0
~> 5.05.x but not 6.x (free patch)~> 5.0
~> 5.0.05.0.x but not 5.1 (free micro)~> 5.0.4
>= 4.0, < 6.0Explicit range>= 4.0, < 6.0

Terraform Registry

registry.terraform.io is the official repository for providers and modules. Official providers (HashiCorp), verified (Partner) and community.

TierMaintained byBadge
OfficialHashiCorphashicorp/aws, hashicorp/azurerm, hashicorp/google
PartnerCompany with a HashiCorp agreementVerified and supported by the partner
CommunityOpen source communityNo guaranteed support
D4

Variables, outputs and expressions

18% of the exam

Types of values

Click any service to see more details

Data types in HCL

TypeExampleNote
string"us-east-1"Unicode text
number42 / 3.14Integer or decimal
booltrue / falseBoolean
list(type)["a", "b", "c"]Ordered list, indexed access
set(type)toset(["a", "b", "c"])Unordered, no duplicates
map(type){ key = "value" }Key-value pairs of the same type
object({}){ name = string, port = number }Named typed attributes
tuple([])[string, number, bool]List with heterogeneous types
anyany valueDynamic type — Terraform infers it

Built-in HCL functions

CategoryKey functionsExample
Stringformat, join, split, replace, upper, lower, trimspaceformat("Hello %s", var.name)
Collectionlength, concat, flatten, merge, keys, values, lookuplength(var.subnets)
Numericmax, min, ceil, floor, absmax(var.min_size, 2)
Encodingjsonencode, jsondecode, base64encode, base64decodejsonencode({ port = 80 })
Filesystemfile, templatefile, pathexpand, abspathfile("./scripts/init.sh")
Date/Timetimestamp, formatdate, timeaddformatdate("YYYY-MM-DD", timestamp())
IP Networkcidrsubnet, cidrhost, cidrnetmaskcidrsubnet("10.0.0.0/8", 8, 2)

Resource meta-arguments

Meta-argumentFunction
count = NCreates N copies of the resource. Accessed with resource.name[index].
for_each = map/setCreates one instance per element. Accessed with resource.name[key].
depends_on = [...]Explicit dependency when there is no direct reference.
provider = aliasUses a specific provider instance (for multiple regions/accounts).
lifecycle {}Controls behavior: prevent_destroy, create_before_destroy, ignore_changes.
provisioner (avoid)Runs scripts after creation. Discouraged — use cloud-init or user_data instead.

count vs for_each: use for_each when elements have their own identity (keys). With count, removing an element from the middle renumbers all the following ones and can destroy unintended resources.

D5

Modules

12% of the exam

Module structure and usage

Click any service to see more details

# Call a module from the Terraform Registry
module "vpc" {
  source  = "terraform-aws-modules/vpc/aws"
  version = "5.0.0"

  name = var.vpc_name
  cidr = "10.0.0.0/16"
}

# Access the module's output
output "vpc_id" {
  value = module.vpc.vpc_id
}

Module sources

SourceExampleWhen
Terraform Registry"hashicorp/consul/aws"Public official/partner/community modules
Local path"./modules/networking"Your own modules within the same repo
GitHub (HTTPS)"github.com/org/repo//modules/vpc"Private modules on GitHub without a registry
GitHub (SSH)"git@github.com:org/repo.git"GitHub with SSH auth
S3 bucket"s3::https://bucket.s3.amazonaws.com/module.zip"Artifacts stored in S3
HCP Registry"app.terraform.io/org/module/aws"Private modules in an HCP organization

Module best practices

Always version

version = "~> 1.0" for registry modules. No version = always latest, breaks on updates.

variables.tf

Define all inputs in a separate variables.tf. Add description and validation.

outputs.tf

All outputs in outputs.tf. Expose only what's necessary — avoid exposing internals.

README.md

Document inputs, outputs and usage examples. terraform-docs generates this automatically.

D6

State management

15% of the exam

Terraform state

Click any service to see more details

Remote backends

BackendProviderState LockingNote
s3AWSNative (use_lockfile)Most popular backend. Locking with use_lockfile = true (DynamoDB deprecated).
azurermAzureNative blob leaseAzure Blob Storage. Native locking, no extra configuration.
gcsGoogleNativeGoogle Cloud Storage. Native locking.
httpAnyOptionalGeneric backend over HTTP. Useful for custom backends.
kubernetesK8sNativeState in a Kubernetes ConfigMap/Secret.
cloud (HCP)HCP TerraformNativeRecommended. Locking + encryption + version history.

State commands

CommandFunction
terraform state listLists all resources in the state
terraform state show addrShows detailed attributes of a resource in the state
terraform state mv src dstRenames/moves a resource in the state (without touching infrastructure)
terraform state rm addrRemoves a resource from the state WITHOUT destroying it in the cloud
terraform state pullDownloads and prints the remote state as JSON
terraform state pushUploads a local state to the remote backend (dangerous — can overwrite)
terraform import addr idImports an existing resource into the state
terraform plan -refresh-onlyDetects drift by comparing state vs reality without applying changes (terraform refresh deprecated in v0.15.4)

terraform state rm does NOT destroy the real resource — it only removes it from Terraform's tracking. Useful for "releasing" a resource from Terraform without deleting it. After the rm, Terraform no longer manages that resource.

D7

Advanced CLI and HCP Terraform

14% of the exam

HCP Terraform

Click any service to see more details

TierWhat it includes
FreeUp to 500 resources, unlimited users, remote state, remote execution, 1 concurrent run
Essentials / Standard / PremiumPay per managed resource; more concurrent runs and governance features at each level
Terraform EnterpriseSelf-hosted on your own infrastructure

terraform import

Imports existing infrastructure (created manually or by another system) into Terraform's state so it can be managed with IaC from then on.

# Before importing, define the resource in your .tf:
resource "aws_instance" "web" {
  # terraform import will fill in the attributes
}

# Then import it with the resource's real ID:
terraform import aws_instance.web i-1234567890abcdef0

# Terraform 1.5+: native import block in HCL
import {
  to = aws_instance.web
  id = "i-1234567890abcdef0"
}

After importing, run terraform plan — if the plan shows changes, your .tf configuration doesn't match the real resource. Adjust the attributes until the plan shows "No changes".

terraform apply -replace (replaces taint)

terraform taint has been deprecated since v0.15.2. Forcing a resource to be recreated is now done with the -replace flag.

MethodStatusHow it works
terraform taint resource.addr⚠️ Deprecated v0.15.2Marked the resource; the next apply recreates it. No visible plan beforehand.
terraform apply -replace=resource.addr✅ ModernShows the replacement plan first (-/+). Safer and more explicit.
terraform plan -replace=resource.addr✅ ModernOnly shows what would be recreated, without applying.

Use -replace when a resource is in a bad state and you need to recreate it without destroying all your infrastructure. The plan shows the -/+ symbol (destroy and recreate).

Logging and debugging

VariableValueEffect
TF_LOGTRACE / DEBUG / INFO / WARN / ERROREnables detailed logging on stderr
TF_LOG_PATHpath/to/file.logSaves logs to a file instead of stderr
TF_LOG_CORElevelLogging only for Terraform core
TF_LOG_PROVIDERlevelLogging only for providers

TF_LOG=DEBUG is the most useful level for debugging. TF_LOG=TRACE shows every call to the provider API — very verbose but useful for diagnosing authentication or throttling errors.

Tips for exam day

🔄

Required flow: init → plan → apply. No init, no plan. No plan, no correct apply.

🔒

State locking prevents concurrent applies. The local backend only locks on the same machine; teams should use a remote backend.

⚠️

The state file can contain secrets in plain text. Always use a remote backend with encryption in production.

📦

.terraform.lock.hcl must be committed to VCS. terraform.tfstate must NEVER be committed.

🔑

Variable order: -var CLI > TF_VAR_* > *.auto.tfvars > terraform.tfvars > default.

🏗️

for_each > count for resources with identity. count with indices breaks when inserting/removing elements from the middle.

🌐

Terraform Registry: registry.terraform.io. Providers: hashicorp/aws. Modules: org/name/provider.

☁️

HCP Terraform ≠ CLI workspaces. They are distinct concepts. An HCP workspace = an isolated environment with state, vars and VCS.

🔐

sensitive = true hides it in the CLI but the value IS in the state. ephemeral = true (1.10+) is the only way to ensure a value is NEVER persisted in the state.

🔄

terraform taint deprecated (v0.15.2) → use terraform apply -replace. terraform refresh deprecated (v0.15.4) → use terraform plan -refresh-only.

Want to go deeper?

This guide is a quick summary. Visit the Deep Dive section for an exhaustive walkthrough with real cases, cost analysis and architecture decisions.

Ready to practice?

Put what you learned to the test with original Terraform Associate exam questions.

Start Terraform Associate mock exam

Unlimited mock exams with the Pro plan

Was this guide helpful?

Not ready to start yet?

Save your email so you don't have to type it again — pick up later and unlock Terraform Associate with a Pro plan or individual purchase.

See all plans →·I already have access