HashiCorp Certified: Terraform Associate (004) Quick Review
Quick Review for the HashiCorp Certified: Terraform Associate (004): Terraform workflow, HCL, providers, modules, state, and HCP Terraform.
This Quick Review is an IT Mastery study companion for candidates preparing for the HashiCorp Certified: Terraform Associate (004) exam from HashiCorp, exam code 004. Use it to refresh high-yield Terraform concepts before moving into topic drills, mock exams, original practice questions, and detailed explanations.
High-yield exam mindset
The Terraform Associate exam rewards practical understanding more than memorization. You should be able to look at a small Terraform configuration, predict what Terraform will do, choose the correct CLI command, and identify how state, providers, variables, modules, and HCP Terraform fit together.
What to prioritize first
| Priority | Know how to answer |
|---|---|
| Terraform workflow | What init, fmt, validate, plan, apply, and destroy do — and what they do not do |
| State | Why state exists, where it is stored, what locking protects, and why state may contain sensitive values |
| Providers | How provider plugins are selected, installed, versioned, configured, and aliased |
| HCL configuration | Blocks, arguments, expressions, references, variables, locals, outputs, data sources, and resources |
| Modules | Root vs child modules, module inputs/outputs, sources, versions, and provider inheritance |
| Dependencies | Implicit references, explicit depends_on, lifecycle rules, count, and for_each |
| HCP Terraform | Remote runs, state storage, VCS workflows, variables, private registry, policy features, and collaboration |
Terraform’s purpose in one page
Terraform is an infrastructure as code tool. You write declarative configuration that describes desired infrastructure, and Terraform uses provider plugins to interact with external APIs.
| Concept | Terraform meaning | Common trap |
|---|---|---|
| Declarative configuration | You describe the desired end state | You do not normally write step-by-step imperative API calls |
| Provider | Plugin that knows how to manage a target platform or service | The provider is not the same as the cloud account itself |
| Resource | Managed infrastructure object | Terraform may create, update, replace, or destroy it |
| Data source | Read-only lookup of existing information | Data sources do not manage lifecycle |
| State | Terraform’s record mapping configuration to real objects | State can include sensitive values |
| Plan | Proposed change set | A plan is not a guarantee that apply will succeed |
| Apply | Executes a plan or creates and executes a new plan | Applying without a saved plan can produce a different plan than an earlier review |
Terraform is commonly compared with configuration management tools. The key distinction: Terraform primarily manages infrastructure lifecycle through APIs. It is not a continuous configuration enforcement agent by default.
Core Terraform workflow
flowchart LR
A[Write configuration] --> B[terraform fmt]
B --> C[terraform init]
C --> D[terraform validate]
D --> E[terraform plan]
E --> F{Review changes}
F -->|Accept| G[terraform apply]
F -->|Revise| A
G --> H[State updated]
Essential CLI commands
| Command | Primary purpose | Exam trap |
|---|---|---|
terraform fmt | Rewrites configuration to canonical formatting | Does not check whether the infrastructure is valid |
terraform init | Initializes working directory, backend, providers, and modules | Required before most other commands in a new or changed working directory |
terraform validate | Checks syntax and internal configuration validity | Does not fully verify cloud-side permissions, quotas, or runtime success |
terraform plan | Shows proposed actions | May refresh state first; does not modify infrastructure |
terraform apply | Applies changes | Without a saved plan, Terraform creates a new plan |
terraform destroy | Plans and applies destruction of managed objects | Acts on resources in state for the current configuration/workspace context |
terraform show | Displays state or plan file in human-readable form | Useful for inspecting saved plans and current state |
terraform output | Reads root module output values | Sensitive outputs may be redacted in CLI display |
terraform state | Advanced state inspection and modification | Does not directly change real infrastructure unless paired with later plan/apply effects |
terraform import | Associates existing infrastructure with Terraform state | Importing alone does not mean the configuration is complete or correct |
terraform workspace | Manages named state instances for one configuration | Workspaces are not a complete environment strategy by themselves |
terraform console | Evaluates Terraform expressions interactively | Helpful for testing functions, types, and references |
Saved plan decision rule
Use a saved plan when you need to guarantee that the reviewed plan is the exact plan applied:
- Run
terraform plan -out=tfplan. - Review the saved plan.
- Run
terraform apply tfplan.
If you run terraform apply without the saved plan file, Terraform performs a fresh plan.
Terraform configuration structure
Terraform configuration is written in the Terraform language, commonly stored in .tf files.
| Block type | Example form | Purpose |
|---|---|---|
terraform | terraform { required_providers { ... } } | Terraform settings, provider requirements, backend/cloud settings |
provider | provider "aws" { region = "us-east-1" } | Configures a provider instance |
resource | resource "type" "name" { ... } | Manages an object |
data | data "type" "name" { ... } | Reads existing information |
variable | variable "region" { type = string } | Declares an input variable |
locals | locals { name = "app" } | Defines reusable local expressions |
output | output "id" { value = resource.x.id } | Exposes values from a module |
module | module "network" { source = "./network" } | Calls another module |
moved | moved { from = ... to = ... } | Records resource address refactoring |
import | import { to = ... id = ... } | Declares import of existing objects, where supported by provider/resource behavior |
Blocks, arguments, and expressions
A common exam-style mistake is confusing the syntax elements.
| Syntax item | Meaning |
|---|---|
| Block | Container with a type, optional labels, and body |
| Argument | Assigns a value to a name inside a block |
| Expression | Calculates or references a value |
| Reference | Points to another object, such as aws_instance.web.id |
| Meta-argument | Special Terraform argument like count, for_each, depends_on, provider, or lifecycle |
Example resource address pattern:
resource_type.local_name.attribute
For a resource declared as resource "aws_instance" "web", the address is aws_instance.web.
Providers
Providers are plugins Terraform uses to interact with APIs. HashiCorp Terraform downloads required providers during terraform init based on configuration and dependency lock selections.
Provider requirements vs provider configuration
| Item | Location | Purpose |
|---|---|---|
required_providers | Inside terraform block | Declares provider source and version constraints |
provider block | Top-level block | Configures provider settings such as region, endpoint, or credentials behavior |
.terraform.lock.hcl | Working directory | Records selected provider versions and checksums |
Provider plugin cache / .terraform directory | Local working directory behavior | Stores initialized dependencies for that working directory |
High-yield distinction:
required_providerssays which provider and acceptable versions.providerblocks say how to configure provider instances.
Provider version constraints
| Constraint | Meaning |
|---|---|
>= 1.0.0 | Version must be at least 1.0.0 |
< 5.0.0 | Version must be below 5.0.0 |
= 4.2.0 | Exact version only |
~> 4.16 | Compatible with 4.x beginning at 4.16, but not 5.0 |
~> 4.16.0 | Compatible patch releases beginning at 4.16.0, but not 4.17.0 |
Common trap: terraform init -upgrade can select newer provider versions allowed by constraints. Normal initialization respects the lock file unless changes require selection.
Provider aliases
Provider aliases let one configuration use multiple instances of the same provider, such as multiple regions or accounts.
| Concept | Example use |
|---|---|
| Default provider | Used automatically when no alias is specified |
| Aliased provider | Used by resources with provider = provider_name.alias |
| Module provider passing | Child modules may need explicit provider mapping when aliases are involved |
Trap: Defining an aliased provider does not automatically make every resource use it. A resource or module must be associated with the correct provider instance.
Resources and data sources
Resource vs data source
| Feature | Resource | Data source |
|---|---|---|
| Intent | Manage lifecycle | Read existing information |
| Terraform state | Tracked as managed object | Read result may be stored/known for planning |
| Can destroy real object? | Yes, if managed and plan requires destroy | No, data sources are read-only |
| Typical example | Create a virtual network | Look up an existing image ID |
Decision rule:
- Use a resource when Terraform should own lifecycle.
- Use a data source when Terraform should only look something up.
Resource actions in a plan
Terraform plans use action symbols. Know what they imply.
| Plan symbol | Meaning |
|---|---|
+ | Create |
- | Destroy |
~ | Update in place |
-/+ or +/- | Replace |
<= | Read data source |
Replacement can occur when an argument cannot be updated in place according to provider behavior.
Variables, locals, and outputs
Input variables
Variables parameterize modules. Important attributes include:
| Attribute | Purpose |
|---|---|
type | Constrains expected value type |
default | Makes the variable optional |
description | Documents usage |
sensitive | Redacts value in many CLI/UI displays |
validation | Adds custom validation rules |
nullable | Controls whether null is allowed |
Common trap: sensitive = true helps with display redaction, but it does not guarantee the value is absent from state.
Local values
Use locals for reusable computed expressions. They are not user inputs and cannot be overridden at runtime.
| Use variable when… | Use local when… |
|---|---|
| The caller should provide or override the value | The value is derived internally |
| The value differs by environment or workspace | You want to avoid repeating an expression |
| The module needs an input contract | You want a readable intermediate name |
Outputs
Outputs expose values from the root module or child modules.
| Output context | How it is used |
|---|---|
| Root module output | Displayed by terraform output, available to remote state consumers |
| Child module output | Referenced as module.module_name.output_name |
| Sensitive output | Redacted in normal display, but still may be in state |
Trap: A child module’s internal resources are not directly part of the calling module’s interface. Use outputs to expose needed values.
Type system and expressions
Terraform has primitive, collection, and structural types.
| Type category | Examples |
|---|---|
| Primitive | string, number, bool |
| Collection | list(string), set(string), map(number) |
| Structural | object({ name = string }), tuple([string, number]) |
| Dynamic | any |
Lists, sets, and maps
| Type | Key feature | Common trap |
|---|---|---|
list | Ordered sequence | Index-based addressing can cause churn |
set | Unordered unique values | Do not rely on stable ordering |
map | Key-value collection | Keys are strings |
object | Named attributes with types | Good for structured module inputs |
Useful expression patterns
| Pattern | Purpose |
|---|---|
| Conditional expression | condition ? true_value : false_value |
| For expression | Transform collections |
| Splat expression | Extract attributes from multiple objects |
| Functions | Transform strings, collections, files, encodings, dates, and more |
null | Omit or unset values in many contexts |
try() | Return fallback when expression errors |
can() | Test whether expression can be evaluated |
Do not overuse dynamic expressions in exam scenarios. Many questions test whether you know the simpler, clearer Terraform construct.
Dependencies and resource graph
Terraform builds a dependency graph from references.
Implicit vs explicit dependencies
| Dependency type | Created by | Best use |
|---|---|---|
| Implicit | Referencing another object’s attribute | Preferred in most cases |
| Explicit | depends_on | Only when Terraform cannot infer the dependency |
Example: If a resource uses aws_vpc.main.id, Terraform knows the VPC must exist first.
Common trap: Adding depends_on everywhere is not a best practice. It can make plans more conservative and harder to understand.
Lifecycle meta-argument
The lifecycle block changes how Terraform handles resource changes.
| Lifecycle setting | Purpose | Trap |
|---|---|---|
create_before_destroy | Create replacement before destroying old object | May fail if names or unique constraints conflict |
prevent_destroy | Blocks plans that would destroy the object | Can block legitimate changes until removed |
ignore_changes | Tells Terraform to ignore selected drift/config differences | Can hide unmanaged changes |
replace_triggered_by | Replaces resource when another object changes | Use intentionally; it can force replacements |
count and for_each
This is a frequent source of mistakes.
| Feature | count | for_each |
|---|---|---|
| Input | Whole number | Map or set of strings |
| Addressing | Index-based, such as [0] | Key-based, such as ["prod"] |
| Best for | Simple identical resources | Stable resources keyed by meaningful names |
| Churn risk | Higher when list order changes | Lower when keys remain stable |
Decision rule:
- Use
countfor simple optional creation or identical repeated resources. - Use
for_eachwhen each instance has a stable identity.
Common trap: Removing item 1 from a list used with count can shift indexes and cause unintended changes. A map with for_each often avoids that problem.
Modules
A module is a container for Terraform configuration. Every Terraform configuration has a root module. A module called by another module is a child module.
Module basics
| Concept | Meaning |
|---|---|
| Root module | The current working configuration where Terraform runs |
| Child module | A module called by a module block |
| Module source | Local path, registry address, Git source, or other supported source |
| Module input | Variable value passed into the module |
| Module output | Value exposed back to the caller |
| Module version | Version constraint for registry modules |
Module source examples
| Source style | Example meaning |
|---|---|
| Local path | Use module code from a local directory |
| Public registry | Use a published module from the Terraform Registry |
| Private registry | Use an internal module registry, such as in HCP Terraform |
| VCS source | Use module code from a version control repository |
Trap: terraform init downloads or installs modules. If you add or change module sources, run terraform init again.
Module input and output decision rule
A child module should not rely on hidden assumptions in the root module. Pass required values as inputs, and expose only needed results as outputs.
Bad exam instinct: trying to directly reference a resource inside a child module from the root module.
Correct pattern: expose a child module output, then reference module.child.output_name.
State
Terraform state is central to how Terraform works. State maps configuration resource addresses to real infrastructure objects and stores metadata needed for planning.
Why state exists
| State purpose | Explanation |
|---|---|
| Mapping | Connects aws_instance.web to the actual remote object ID |
| Performance | Avoids querying everything from scratch where possible |
| Dependency metadata | Tracks relationships and object details |
| Drift detection | Helps compare expected state with remote reality |
| Collaboration | Shared state enables teams to work on the same infrastructure safely when using remote state and locking |
Local vs remote state
| State mode | Characteristics |
|---|---|
| Local state | Stored in local files, usually terraform.tfstate |
| Remote state | Stored in a backend or HCP Terraform |
| State locking | Prevents concurrent state writes when supported by backend |
| Encryption/access control | Depends on backend or platform configuration |
High-yield trap: Do not commit local state files to version control. State may contain secrets, IDs, generated passwords, and sensitive metadata.
Backend concepts
A backend defines where Terraform stores state and how operations interact with it.
| Backend fact | Exam relevance |
|---|---|
Backend configuration is initialized by terraform init | Backend changes usually require reinitialization |
| Backends are not providers | Providers manage infrastructure; backends store state |
| Some backends support locking | Locking prevents concurrent state modification |
| HCP Terraform can store state and execute runs | Remote execution changes where credentials and variables must be available |
State commands
Use terraform state commands carefully.
| Command pattern | Effect |
|---|---|
terraform state list | Lists resources in state |
terraform state show ADDRESS | Shows details for one state object |
terraform state mv | Moves/renames an address in state |
terraform state rm | Removes an object from state without destroying the real object |
terraform import | Adds an existing real object to state at a resource address |
Trap: Removing something from state does not delete the infrastructure. It only makes Terraform stop tracking it at that address.
Drift and refresh
Drift occurs when real infrastructure changes outside Terraform.
| Action | Meaning |
|---|---|
| Refresh during plan | Terraform updates state’s view of remote objects before planning, unless disabled |
| Refresh-only plan/apply | Updates state to match remote objects without proposing normal configuration changes |
| Drift correction | Terraform may propose changes to bring remote objects back to configuration |
Common trap: If someone changes infrastructure manually, Terraform does not magically prevent it. Terraform detects or responds to drift during later operations.
Workspaces
Terraform workspaces allow multiple state instances for the same configuration.
| Workspace concept | Meaning |
|---|---|
default | Initial workspace |
| Named workspace | Separate state for same configuration |
| Local workspace | Managed by Terraform CLI locally |
| Remote/HCP Terraform workspace | Managed in HCP Terraform context |
Common traps:
- Workspaces separate state, not code.
- Workspaces are not a universal substitute for separate accounts, projects, directories, or environment-specific architecture.
- The same configuration can behave differently if it uses
terraform.workspacein expressions.
Files and directories to recognize
| File or directory | Purpose |
|---|---|
*.tf | Terraform configuration files |
*.tf.json | JSON syntax variant of Terraform configuration |
terraform.tfvars | Common variable values file |
*.auto.tfvars | Automatically loaded variable values |
.terraform.lock.hcl | Provider dependency lock file |
.terraform/ | Local working directory data created by init |
terraform.tfstate | Local state file when using local backend |
terraform.tfstate.backup | Local backup state file |
.terraformignore | Excludes files from upload in certain remote operation contexts |
Variable value precedence
For local CLI usage, if the same variable is set in multiple places, later/higher-precedence sources override earlier/lower-precedence sources.
| Precedence order | Source |
|---|---|
| Lower | Environment variables such as TF_VAR_name |
terraform.tfvars | |
terraform.tfvars.json | |
*.auto.tfvars and *.auto.tfvars.json, in lexical order | |
| Higher | -var and -var-file options, in command-line order |
Trap: Variable declarations define the input contract. Variable value files provide values; they do not declare variables.
Provisioners
Provisioners run scripts or commands as part of resource creation or destruction. Terraform supports provisioners such as local-exec and remote-exec.
Exam-safe rule: provisioners are a last resort. Prefer provider-native resources, images, cloud-init, configuration management, or other purpose-built mechanisms when possible.
| Provisioner idea | Trap |
|---|---|
local-exec runs on the machine running Terraform | In remote execution, that machine is not your laptop |
remote-exec runs on a remote resource | Requires connectivity and credentials |
| Provisioners can fail | Failures can leave infrastructure partially created |
| Provisioners are not full lifecycle management | They are not a substitute for declarative resources |
HCP Terraform review
HCP Terraform is HashiCorp’s managed platform for Terraform collaboration, automation, state, and governance capabilities. Terraform Enterprise provides related capabilities for self-managed enterprise environments.
HCP Terraform capabilities to recognize
| Capability | What it means for exam scenarios |
|---|---|
| Remote state storage | State is stored centrally rather than only on a local machine |
| State locking | Helps prevent concurrent runs from corrupting state |
| Remote runs | Plan/apply can execute in HCP Terraform instead of locally |
| VCS-driven workflow | Runs can be triggered by version control changes |
| CLI-driven workflow | CLI can initiate runs connected to HCP Terraform |
| Variables and variable sets | Store and reuse workspace variables |
| Private registry | Share internal modules and providers |
| Run history | Review prior plans and applies |
| Team access controls | Manage collaboration permissions |
| Policy and governance features | Apply organizational controls to runs, depending on platform features and configuration |
Remote execution trap
If Terraform runs remotely, credentials, environment variables, files, and network access must be available to the remote execution environment. Do not assume your local shell environment is available.
| Local CLI execution | HCP Terraform remote execution |
|---|---|
| Uses local machine context | Uses remote run environment |
| Local credentials may be available | Workspace/platform variables or integrations are needed |
| Local files are available | Only uploaded/included workspace files are available |
| State may be local or remote | State is managed by HCP Terraform workspace |
Security and sensitive data
Terraform configurations often touch credentials, generated secrets, and infrastructure identifiers.
| Security topic | High-yield point |
|---|---|
| Sensitive variables | Redact display but may still be stored in state |
| Sensitive outputs | Redact normal CLI output but may still be in state |
| State files | Protect them like sensitive data |
| Version control | Do not commit secrets, local state, or private variable files |
| Provider credentials | Prefer secure mechanisms supported by the provider/platform |
| Remote state access | Limit access to people and systems that need it |
Common trap: Marking a value sensitive is not encryption by itself. It is primarily a display-handling feature in Terraform.
Common exam traps and corrections
| Trap | Correct understanding |
|---|---|
terraform fmt validates cloud resources | fmt only formats configuration |
terraform validate proves apply will succeed | It checks configuration validity, not all remote API conditions |
| A plan always applies successfully | Permissions, quotas, drift, API errors, or changes after planning can cause failure |
| A data source manages existing infrastructure | Data sources read; resources manage |
| State is optional | State is fundamental to Terraform operation |
| State is always safe to share | State may contain sensitive data |
| Backends and providers are the same thing | Backends store state; providers manage APIs |
depends_on should be used everywhere | Prefer implicit dependencies from references |
count is always safer than for_each | for_each is often safer for stable keyed resources |
| Child module resources should be referenced directly | Use module outputs |
| Sensitive values never enter state | They can still be present in state |
| Workspaces fully separate environments | They separate state for the same configuration |
| Import creates perfect Terraform code | Import associates state; configuration still must match desired management |
| Removing from state destroys infrastructure | It only stops tracking the object at that address |
apply reuses the last plan automatically | It creates a new plan unless given a saved plan file |
| Provider aliases apply automatically | Resources/modules must use or receive the aliased provider |
Quick decision tables
Which Terraform construct should you choose?
| Need | Use |
|---|---|
| Create and manage infrastructure | resource |
| Look up existing infrastructure | data |
| Parameterize a module | variable |
| Reuse an internal computed value | locals |
| Return a value from a module | output |
| Repeat similar resources by number | count |
| Repeat resources by stable names | for_each |
| Force an otherwise invisible dependency | depends_on |
| Change create/destroy behavior | lifecycle |
| Package reusable configuration | module |
| Store state remotely | Backend or HCP Terraform |
| Collaborate with remote runs and shared state | HCP Terraform |
Which command should you choose?
| Scenario | Best command |
|---|---|
| New working directory with Terraform files | terraform init |
| Changed provider constraints | terraform init or terraform init -upgrade when intentionally upgrading |
| Changed module source | terraform init |
| Check formatting | terraform fmt -check |
| Fix formatting | terraform fmt |
| Check configuration syntax/internal validity | terraform validate |
| Preview changes | terraform plan |
| Apply exactly reviewed changes | terraform plan -out=... then terraform apply ... |
| Show outputs | terraform output |
| Inspect state addresses | terraform state list |
| Import existing object | terraform import or an import block workflow where appropriate |
| Remove object from state only | terraform state rm |
| Destroy managed infrastructure | terraform destroy |
Practice focus for the question bank
When you move from this Quick Review into IT Mastery practice, spend extra time on scenario questions. The exam often feels like “what should Terraform do next?” rather than “define this word.”
Use topic drills and original practice questions to test:
Workflow recognition Identify the correct command for initialization, validation, planning, applying, importing, output inspection, and state inspection.
Configuration reading Read small HCL snippets and predict references, dependencies, variable values, and resource addresses.
State behavior Decide whether a command changes state, changes infrastructure, both, or neither.
Module interfaces Trace inputs into a child module and outputs back to the root module.
Provider setup Distinguish provider requirements, provider configuration, aliases, and lock file behavior.
HCP Terraform scenarios Recognize when a run happens remotely, where variables must live, and how remote state/collaboration changes the workflow.
Common traps Practice questions that contrast
resourcevsdata,countvsfor_each,variablevslocal, backend vs provider, and local execution vs remote execution.
Final rapid review checklist
Before taking the HashiCorp Certified: Terraform Associate (004) exam, confirm that you can answer these without notes:
- What does each core CLI command do?
- What does
terraform initinstall or configure? - What is stored in
.terraform.lock.hcl? - How do provider version constraints work?
- How are provider aliases used?
- What is the difference between a resource and a data source?
- Why does Terraform need state?
- Why is remote state useful for teams?
- Why can state be sensitive?
- When should you use
for_eachinstead ofcount? - How do modules receive inputs and expose outputs?
- What does
depends_onsolve, and why should it be used sparingly? - What does
lifecyclechange? - What changes when Terraform runs in HCP Terraform instead of your local shell?
- What does importing infrastructure do — and not do?
Next step: use a question bank with topic drills, original practice questions, mock exams, and detailed explanations to turn this Quick Review into exam-ready decision speed.
Continue in IT Mastery
Use this Quick Review as a final concept map, then move into IT Mastery for focused topic drills, mixed practice sets, timed mock exams, and detailed explanations. The practice questions are original IT Mastery practice items; they are not official HashiCorp questions, copied live-exam content, or exam dumps.