Study Guide · TA-004

TA-004 Cheat Sheet

316 entries · 37 chapters · 8 domains

Infrastructure as Code (IaC) with Terraform

Explain What IaC Is

Read full chapter

Cheat sheet

Sharp facts the exam loves — scan these before test day.

IaC is provisioning via machine-readable config

Infrastructure as Code (IaC) is the practice of managing and provisioning infrastructure through machine-readable configuration files rather than through manual console actions or interactive point-and-click tools.

Trap IaC is not merely a script that automates GUI clicks; the configuration itself codifies the intended infrastructure so it can be versioned and reused.

10 questions test this
Terraform is an IaC tool

Terraform is an infrastructure as code tool that lets you build, change, and version cloud and on-prem resources safely and efficiently by defining them in human-readable configuration files.

5 questions test this
Terraform config is declarative

Terraform's configuration language is declarative: it describes the desired end-state of your infrastructure rather than the ordered steps to build it, and Terraform determines the operations needed to reach that state.

Trap A Terraform configuration is not an imperative or procedural script that lists commands in execution order.

9 questions test this
Terraform vs conventional API-driven management

Compared with conventional management that issues one-off imperative API or CLI calls, Terraform describes infrastructure with version-controlled, repeatable configurations that specify the desired state.

Trap Terraform uses provider APIs rather than replacing them with its own protocol, and it is more than a thin wrapper around those APIs because it tracks state and reconciles to the desired state.

5 questions test this
Manual provisioning is not reproducible

Manual or ad-hoc provisioning (clicking in a console or running undocumented CLI commands) is hard to reproduce, whereas IaC codifies infrastructure so applying the same configuration yields the same result every time.

Trap Undocumented one-off API calls are not IaC just because they use an API; IaC requires codified, versioned, repeatable definitions.

18 questions test this
IaC applies software-engineering practices

Because infrastructure is expressed as code, IaC brings software-engineering practices such as version history, code review, and testing to infrastructure provisioning.

Advantages of IaC Patterns

Read full chapter
  • Config is committed to version control
  • Reviewing a plan before apply
  • Declarative definitions reduce drift
  • Repeatable identical environments
  • Reuse and standardization via modules
  • Immutable infra: less complex upgrades
  • Immutable infra prevents drift
  • Mutable infrastructure changes in place

Unlock with Premium — includes all practice exams and the complete study guide.

Multi-Cloud, Hybrid, and Service-Agnostic Workflows

Read full chapter
  • Same workflow manages multiple clouds
  • One workflow reduces vendor lock-in
  • Providers work with any API
  • Workflow is service-agnostic
  • You can write custom providers
  • Terraform manages cloud and on-prem together
  • Flexible abstraction of resources

Unlock with Premium — includes all practice exams and the complete study guide.

Terraform fundamentals

Install and version Terraform providers

Read full chapter

Cheat sheet

Sharp facts the exam loves — scan these before test day.

required_providers lives inside the terraform block

The required_providers block must be declared inside the top-level terraform block, and each entry maps a module-local name to an object containing a source argument and an optional version argument. It is not valid at the top level of a file or inside a provider block.

Trap Placing required_providers at the top level of the file or inside a provider block instead of nested in the terraform block.

8 questions test this
Provider source address format

A provider source address has the form [HOSTNAME/]NAMESPACE/TYPE (for example hashicorp/aws); when the hostname is omitted Terraform defaults to the public registry registry.terraform.io.

Trap Thinking source is a download URL, or that the hostname registry.terraform.io must always be written explicitly.

10 questions test this
The local name is the required_providers key

The key of each required_providers entry is the provider's local name, which is used to reference that provider elsewhere in the module (in provider blocks and as the prefix of its resource types). By convention it matches the source TYPE but it can differ.

Trap Assuming the local name must exactly equal the TYPE in the source address.

terraform required_version setting

Inside the terraform block, required_version constrains which Terraform CLI/core version may run the configuration using the standard constraint operators (=, !=, >, >=, <, <=, ~>). It applies only to the Terraform binary and is distinct from the per-provider version constraints in required_providers; if the running CLI version does not satisfy the constraint, Terraform prints an error and exits immediately without taking any action.

Trap required_version constrains the Terraform CLI, not providers — provider versions are pinned separately in required_providers under the terraform block.

6 questions test this
Version constraint operators

Provider version constraints support = (or no operator, exact), != (exclude), >, >=, <, <=, and ~>. Multiple constraints separated by commas are combined with logical AND, for example version = ">= 1.2.0, < 2.0.0".

Trap Treating comma-separated constraints as OR rather than AND.

5 questions test this
The ~> pessimistic operator

The ~> operator allows only the right-most specified version component to increment: ~> 1.0.4 permits 1.0.5 and later 1.0.x but not 1.1.0, while ~> 1.1 permits 1.2 and later 1.x but not 2.0.

Trap Believing ~> 1.1 allows 2.0, or that ~> 1.0.4 allows 1.1.0.

4 questions test this
Version constraints are quoted strings

The version requirement is a string assigned to version inside the provider object, with the operator and number both inside the quotes, e.g. version = ">= 3.1". Forms such as version >= 3.1 or version = >= 3.1 are invalid syntax.

Trap Writing the constraint without the = assignment or without quotes, e.g. version >= 3.1.

5 questions test this
Pre-release versions need an exact match

Pre-release versions such as 1.2.0-beta are only selected when requested with an exact = constraint; they never satisfy range operators like >=, <, or ~>.

Trap Expecting >= 1.2.0 to select a 1.2.0-beta pre-release.

terraform init installs providers

terraform init is the command that downloads and installs the provider plugins required by the configuration into the working directory; it must be run before terraform plan or terraform apply can use those providers.

Trap Thinking providers are downloaded during terraform plan/apply rather than during terraform init.

5 questions test this
Where Terraform installs providers from

Terraform can install providers directly from an origin registry (default registry.terraform.io), from a local filesystem mirror (a plugins directory), from an HTTPS network mirror, or reuse a shared plugin cache (plugin_cache_dir / TF_PLUGIN_CACHE_DIR). Terraform never compiles provider source code at runtime.

Trap Believing Terraform compiles provider source code at run time — providers are distributed as pre-built plugin binaries.

6 questions test this
The .terraform.lock.hcl dependency lock file

Running terraform init creates or updates .terraform.lock.hcl in the working directory, recording the exact provider versions selected plus their checksums (hashes); this file should be committed to version control and does not lock module versions.

Trap Assuming the lock file also pins module versions — it only locks providers.

6 questions test this
terraform init -upgrade

Without -upgrade, terraform init re-selects the versions already recorded in .terraform.lock.hcl even if newer releases exist; running terraform init -upgrade reconsiders the constraints, selects newer allowed versions, and updates the lock file.

Trap Expecting a plain terraform init to upgrade providers to the newest matching version.

How Terraform uses providers

Read full chapter

Cheat sheet

Sharp facts the exam loves — scan these before test day.

Providers are plugins Terraform relies on

Terraform relies on plugins called providers to interact with cloud platforms, SaaS providers, and other APIs; Terraform Core itself contains no infrastructure-specific logic and delegates all API interaction to providers.

Trap Thinking Terraform has built-in support for cloud services without a provider.

11 questions test this
Providers are versioned separately from Terraform

Providers are distributed and released separately from the Terraform CLI, each with its own version numbers and release cadence, which is why provider versions are constrained independently of the Terraform version.

Trap Assuming a provider's version tracks the Terraform CLI version.

8 questions test this
Core talks to providers over a plugin protocol

Terraform Core communicates with each provider plugin over an RPC-based plugin protocol, launching the provider as a separate process during operations.

Each provider adds resource types and data sources

Each provider defines a set of resource types and/or data sources that Terraform can manage; a provider is required for every resource type, so Terraform cannot manage any infrastructure without the corresponding provider.

Trap Thinking resource types are built into Terraform Core rather than supplied by providers.

15 questions test this
Providers translate configuration into API calls

A provider translates the resources declared in configuration into the create, read, update, and delete API calls of its target platform, acting as the bridge between Terraform and the remote system's API.

Trap Thinking Terraform Core calls cloud APIs directly rather than through a provider plugin.

9 questions test this
Terraform Core ships with no resource types

Terraform Core ships with no built-in resource types; all resource types and data sources come from providers, which is why a configuration must declare its provider requirements.

Resource type prefix selects the provider

Terraform infers which provider manages a resource from the prefix of the resource type name — for example aws_instance uses the aws provider — unless the resource sets an explicit provider meta-argument.

Trap Assuming the resource's name label (not the type prefix) determines the provider.

10 questions test this
init installs plugins into .terraform

terraform init reads the configuration to determine the required providers and installs their plugin binaries under the .terraform directory of the working directory, recording the selections in the lock file.

Writing configuration with multiple providers

Read full chapter
  • The provider block
  • The default provider configuration
  • Provider arguments are often optional
  • The alias meta-argument
  • Selecting an aliased provider on a resource
  • Unmarked resources still use the default config
  • Child modules inherit the default provider
  • Explicitly passing providers to a module

Unlock with Premium — includes all practice exams and the complete study guide.

How Terraform uses and manages state

Read full chapter
  • State maps configuration to real objects
  • Default local state is terraform.tfstate JSON
  • State is updated after apply
  • State records metadata and dependencies
  • State caches resource attributes
  • -refresh=false uses cached state
  • State is plaintext and includes secrets
  • sensitive does not remove values from state
  • State locking is automatic

Unlock with Premium — includes all practice exams and the complete study guide.

Core Terraform workflow

Describe the Terraform workflow

Read full chapter

Cheat sheet

Sharp facts the exam loves — scan these before test day.

Core workflow is Write, Plan, Apply

The core Terraform workflow has three stages in order: Write (author infrastructure as code), Plan (preview the changes Terraform will make), and Apply (provision the described infrastructure).

Trap Assuming 'init' is one of the three core-workflow stages; init is a prerequisite setup step, not one of the Write/Plan/Apply stages.

6 questions test this
Plan previews, Apply provisions

The Plan stage previews proposed changes without altering any real infrastructure, while the Apply stage carries out the approved plan to create, update, or destroy resources.

Trap Believing terraform plan changes infrastructure; plan is read-only and never modifies remote objects.

6 questions test this
Terraform configuration is VCS-friendly text

Terraform configuration is human-readable declarative text (HCL), so it can be committed to a version control system alongside application code and reviewed with standard tools like Git.

Trap Thinking the state file (rather than the configuration) is the artifact you commit to VCS; state can contain secrets and is generally not committed.

6 questions test this
Reviewing the plan before apply improves reliability

Running terraform plan before terraform apply lets a team review proposed changes before they touch real infrastructure, catching mistakes early and improving change reliability.

Trap Overclaiming that this workflow means invalid configurations can 'never' be deployed; review reduces risk but does not make bad applies impossible.

5 questions test this
-help prints a subcommand's usage

Appending the -help flag to a subcommand (for example, terraform plan -help) prints that command's usage information and its list of available options.

Trap Guessing -usage, -info, or -man; Terraform uses -help (also available as terraform -help ).

20 questions test this
Command structure with global options

The Terraform CLI follows the pattern terraform [global options] [args], where global options such as -chdir and -version precede the subcommand name.

Initialize a working directory

Read full chapter

Cheat sheet

Sharp facts the exam loves — scan these before test day.

init performs backend, module, and provider setup

terraform init initializes a working directory by initializing the backend, downloading and installing child modules referenced in module blocks, and installing the provider plugins the configuration requires.

Trap Thinking init applies changes or refreshes state; init only prepares the working directory and never provisions infrastructure.

10 questions test this
init is the first command and creates .terraform

terraform init is the first command run against a new or cloned configuration; it creates the local .terraform directory used to store backend configuration, provider plugins, and modules.

5 questions test this
init is safe to run multiple times

terraform init is idempotent and safe to run repeatedly; it installs newly added modules and providers but never deletes existing configuration or state.

-upgrade ignores locked provider selections

terraform init -upgrade upgrades all previously selected providers to the newest versions allowed by the configuration's version constraints, ignoring the versions recorded in the dependency lock file.

Trap Believing a plain terraform init upgrades providers; without -upgrade it honors the versions already recorded in .terraform.lock.hcl.

8 questions test this
init writes the dependency lock file

During provider installation terraform init records the selected provider versions and checksums in .terraform.lock.hcl, which should be committed to version control so future inits select the same versions.

12 questions test this
-plugin-dir forces a local plugin source

terraform init -plugin-dir=PATH forces Terraform to read provider plugins only from the specified directory, bypassing the registry and other install methods.

init -migrate-state moves state to a new backend

After changing the backend configuration, you re-run terraform init; the -migrate-state option copies the existing state file into the newly configured backend.

Trap Reaching for terraform state mv, push, or refresh to move to a new backend; backend migration is done by re-running terraform init.

7 questions test this
-reconfigure skips state migration

terraform init -reconfigure disregards any existing backend configuration and reinitializes from scratch, explicitly preventing migration of existing state to the new backend.

Trap Confusing -reconfigure with -migrate-state; -reconfigure discards the old backend without copying state, while -migrate-state copies it.

8 questions test this
-backend=false initializes without a backend

terraform init -backend=false skips backend initialization, which is useful for installing plugins and modules to validate a configuration without accessing remote state.

Terraform merges all .tf/.tf.json files order-independently

Terraform loads and merges every .tf and .tf.json file in the working (top-level) directory into a single configuration, evaluating the whole module as one document; nested directories are treated as separate modules and are not auto-loaded. Because the language is declarative, the order in which files are loaded does not matter, so splitting code across main.tf, variables.tf, and outputs.tf is purely an organizational convention with no effect on behavior.

Trap Assuming filenames like main.tf/variables.tf/outputs.tf are required or that Terraform executes files in a top-to-bottom or filename order — it does not. The lone exception to flat merging is override files (override.tf, override.tf.json, or any *_override.tf / *_override.tf.json), which are loaded last and merged in to override matching blocks.

6 questions test this

Validate a configuration

Read full chapter

Cheat sheet

Sharp facts the exam loves — scan these before test day.

validate checks syntax and internal consistency

terraform validate verifies that a configuration is syntactically valid and internally consistent, regardless of any provided variables or existing state.

13 questions test this
validate checks attribute names and value types

terraform validate confirms that argument names and value types are correct for the resources and providers referenced, catching type mismatches and unknown attributes before a plan.

8 questions test this
validate does not check remote services

terraform validate does not validate remote services such as provider APIs or remote state, so it cannot confirm that credentials work or that a resource can actually be created.

Trap Assuming a passing validate guarantees a successful apply; it checks configuration correctness only, not real infrastructure or API access.

11 questions test this
validate is not a plan

terraform validate does not read state or generate an execution plan, so it will not surface drift or runtime errors that only appear when Terraform contacts real infrastructure.

validate requires an initialized directory

terraform validate requires an already-initialized working directory with referenced providers and modules installed; run terraform init (optionally with -backend=false) first.

Trap Thinking validate works on a fresh checkout without init; it needs providers and modules installed to type-check the configuration.

12 questions test this
validate supports JSON output and CI use

terraform validate -json produces machine-readable output, and the command is safe to run automatically, for example as an editor post-save check or a CI test step for a reusable module.

Generate and review an execution plan

Read full chapter
  • plan refreshes, compares, then proposes
  • plan does not carry out changes
  • Reading plan action symbols and the Plan summary line
  • -refresh=false skips the state refresh
  • -refresh-only only reconciles state
  • -target and -replace narrow or force actions
  • -replace flag replaces deprecated taint/untaint
  • -out saves a plan for exact apply
  • Saved plan files store sensitive data in cleartext
  • -detailed-exitcode signals diff state

Unlock with Premium — includes all practice exams and the complete study guide.

Apply changes to infrastructure

Read full chapter
  • apply creates a plan and prompts for approval
  • apply makes the configured infrastructure changes
  • -auto-approve skips interactive approval
  • Applying a saved plan does not prompt
  • apply refreshes state before executing
  • apply updates state to record changes

Unlock with Premium — includes all practice exams and the complete study guide.

Destroy managed infrastructure

Read full chapter
  • destroy is an alias for apply -destroy
  • destroy accepts apply options but no plan file
  • destroy removes all managed objects
  • destroy can be scoped or previewed
  • prevent_destroy blocks destruction

Unlock with Premium — includes all practice exams and the complete study guide.

Apply formatting and style adjustments

Read full chapter
  • fmt rewrites files to canonical style
  • fmt formats, it does not validate
  • -check verifies formatting without writing
  • -diff shows formatting changes
  • -recursive extends fmt into subdirectories
  • fmt can read from stdin

Unlock with Premium — includes all practice exams and the complete study guide.

Terraform configuration

Resource and data blocks

Read full chapter

Cheat sheet

Sharp facts the exam loves — scan these before test day.

Resource block has two labels

A resource block requires two labels: the resource type (e.g. aws_instance) and a local name (e.g. web). Together they form the resource address aws_instance.web, which must be unique within the module.

Trap Believing the local name must be globally unique or must match a provider-assigned identifier.

3 questions test this
Resource meta-arguments

In addition to provider-defined arguments, a resource block accepts the meta-arguments depends_on, count, for_each, provider, and lifecycle. count and for_each are mutually exclusive within the same block.

Trap Using both count and for_each in one resource block (Terraform errors).

3 questions test this
Managed resource lifecycle

A managed resource block directs Terraform to create, update, or destroy real infrastructure so it matches the configuration.

3 questions test this
count vs. for_each resource meta-arguments

The count meta-argument takes a whole number and creates that many instances addressed by count.index (starting at 0), while for_each takes a map or a set of strings and creates one instance per element keyed by each.key/each.value; you cannot set both count and for_each on the same block. for_each is preferred when instances need stable identity, because instances are tracked by map/set key rather than by positional index, so adding or removing a middle element does not force the shift-and-replace churn that count produces.

Trap count.index is unavailable inside a for_each block (and each.key/each.value are unavailable with count); switching a resource from count to for_each changes every instance address and forces replacement unless you add a moved block.

3 questions test this
Data blocks are read-only

A data source is declared data "<TYPE>" "<NAME>" {}; Terraform performs only read operations on it, fetching information about existing objects without creating or modifying infrastructure.

4 questions test this
When data sources are read

Terraform reads a data source during the plan/refresh phase when its arguments are known, but defers the read until apply when the data block depends on values not yet known (for example attributes of resources changing in the same plan).

Trap Assuming data sources are always read at apply time, or always fully resolved before plan.

4 questions test this
Data source reference syntax

Data source attributes are referenced as data.<TYPE>.<NAME>.<ATTRIBUTE>; the leading data. prefix distinguishes them from managed resource references.

Trap Omitting the data. prefix and referencing the source like a managed resource.

2 questions test this
CRUD ownership differs

A managed resource block owns the full create/update/delete lifecycle of the object, while a data block only reads an existing object and never manages or destroys it.

Trap Thinking a data source can provision or destroy infrastructure.

7 questions test this
Data sources re-read each run

Terraform re-reads each data source during the refresh step of every plan/apply so it reflects the current real-world value, whereas a managed resource is only changed when configuration or state drift requires it.

5 questions test this
provisioners: local-exec vs. remote-exec

A local-exec provisioner runs a command on the machine running Terraform, whereas a remote-exec provisioner runs commands on the newly created remote resource and therefore requires a connection block (SSH or WinRM). Provisioners run at creation time by default, or during destroy when when = destroy is set, and HashiCorp guidance is to use them only as a last resort after purpose-built alternatives.

Trap A failed creation-time provisioner marks the resource as tainted so it is recreated on the next apply; destroy-time provisioners still require a valid connection at destroy time.

8 questions test this
Provisioner failure taints the resource

A creation-time provisioner that exits non-zero fails the apply and marks the resource as tainted, so Terraform destroys and recreates it on the next terraform apply; because Terraform cannot predictably model the changes a provisioner makes, recreation is used instead of a partial repair. The on_failure argument overrides this: the default (fail) aborts the apply, while on_failure = continue makes Terraform ignore the error and proceed.

Trap Assuming a failed provisioner leaves a usable resource, or that continue is the default (it is not — fail is). Destroy-time provisioners behave differently: a failure returns an error and Terraform re-runs the provisioner on the next terraform apply rather than tainting.

5 questions test this
The file provisioner

The file provisioner copies files or directories from the machine where Terraform is running to the newly created resource, using either a source path or inline content plus a destination path on the target. Like remote-exec, it reaches the resource through a connection block over SSH or WinRM.

Trap file completes the provisioner-type triad (local-exec, remote-exec, file); a common misconception is treating file as a generic data/config feature or forgetting it still requires a connection block — unlike local-exec it acts on the remote host, not the Terraform machine.

terraform_data built-in resource (null_resource replacement)

The built-in terraform_data managed resource (added in Terraform 1.4, provider source terraform.io/builtin/terraform, requiring no provider block or required_providers entry) is the modern replacement for the null provider's null_resource: it implements the standard resource lifecycle without managing any real infrastructure object. Its optional input argument stores an arbitrary value that is echoed to the computed output attribute (unknown during plan, equal to input after apply), and it can host standalone provisioners that have no other logical managed resource to attach to. Setting its triggers_replace argument forces the terraform_data instance to be replaced whenever that value changes, so referencing the instance from another resource's lifecycle { replace_triggered_by = [terraform_data.] } propagates a forced replacement onto that dependent resource.

Trap Assuming terraform_data still needs the hashicorp/null provider (a required_providers entry or provider block) the way null_resource did — it does not; terraform_data is always available through Terraform's built-in provider, so no provider is declared or configured.

Referencing resource attributes

Read full chapter

Cheat sheet

Sharp facts the exam loves — scan these before test day.

Attribute reference form

Another resource's exported attribute is referenced as <TYPE>.<NAME>.<ATTRIBUTE>, for example aws_vpc.main.id.

6 questions test this
Indexing count instances

For a resource using count, individual instances are addressed by numeric index such as aws_instance.web[0].id; the bare name aws_instance.web is the whole list of instances.

Trap Referencing aws_instance.web.id directly when count is set, which errors because the value is a list.

5 questions test this
Indexing for_each instances

For a resource using for_each, instances are addressed by their map/set key, such as aws_instance.web["app"].id; the collection is a map keyed by each.key.

Trap Using a numeric index like [0] to address a for_each instance instead of its string key.

4 questions test this
References create implicit dependencies

When one resource argument references another resource's attribute (e.g. subnet_id = aws_subnet.main.id), Terraform automatically infers a dependency and creates or updates the referenced resource first.

Trap Adding a manual depends_on when a reference already establishes the ordering.

12 questions test this
Unknown referenced values

If a referenced attribute is not yet known at plan time (for example an ID the provider assigns on create), the plan shows the dependent value as (known after apply).

8 questions test this
Named value prefixes

Terraform references named values by prefix: input variables as var.<NAME>, local values as local.<NAME>, data sources as data.<TYPE>.<NAME>, and child-module outputs as module.<NAME>.<OUTPUT>.

Trap Referencing a variable by its bare name instead of var.<name>, or reaching a child module's internal resource instead of its declared output.

11 questions test this
Path and workspace values

path.module, path.root, and path.cwd give filesystem paths and terraform.workspace gives the current workspace name; self, count.index, and each.key/each.value are only valid inside specific block contexts.

locals block for named local values

A locals block assigns names to expressions so a value can be computed once and reused, referenced elsewhere as local. (singular local, even though the block keyword is locals). Local values keep configuration DRY and readable, but unlike input variables they are internal to the module and cannot be set or overridden by callers.

Trap Reference a local with the singular local., not the plural locals.; and because callers cannot set locals, a local is not a substitute for a variable when you need external input.

7 questions test this

Variables and outputs

Read full chapter

Cheat sheet

Sharp facts the exam loves — scan these before test day.

Variables without default are required

A variable block with no default is required; Terraform prompts for its value interactively, or errors in a non-interactive run, when it is not supplied.

Trap Assuming a variable without a default silently becomes null or empty.

4 questions test this
Variable type and nullable

type constrains the accepted value, default supplies a fallback, and nullable = false forbids a null value (the default is nullable = true).

4 questions test this
Access variables with var.

Inside configuration a variable's value is accessed as var.<NAME>, never by the bare variable name.

Trap Referencing a variable as vpc_cidrs instead of var.vpc_cidrs.

4 questions test this
Which tfvars auto-load

Terraform automatically loads terraform.tfvars, terraform.tfvars.json, and any *.auto.tfvars/*.auto.tfvars.json files from the working directory with no extra flags; other .tfvars files must be passed explicitly with -var-file.

Trap Thinking terraform.tfvars is ignored unless passed with -var-file, or that only *.auto.tfvars files auto-load.

8 questions test this
TF_VAR_ environment variables

An environment variable named TF_VAR_<name> sets the value of the input variable <name>.

6 questions test this
Variable precedence order

When a variable is set in multiple places, precedence from highest to lowest is: -var/-var-file (command line, last one wins), *.auto.tfvars (processed in lexical filename order), terraform.tfvars.json, terraform.tfvars, TF_VAR_ environment variables, then the default.

Trap Believing environment variables or terraform.tfvars override a command-line -var value.

8 questions test this
Output block value argument

An output block exposes data through its required value argument; root-module outputs are printed after apply and by the terraform output command.

8 questions test this
Accessing child module outputs

A parent module reads a child module's output as module.<MODULE_NAME>.<OUTPUT_NAME>; only declared outputs are exposed, not the child's internal resources.

Trap Attempting to reference a child module's resource directly instead of through a declared output.

2 questions test this
Sensitive output behavior

sensitive = true on an output redacts it as <sensitive> in CLI output but the value is still stored in state, and terraform output -json/-raw reveal it.

Trap Assuming a sensitive output is omitted from or encrypted in the state file.

4 questions test this

Complex types

Read full chapter
  • Collection type distinctions
  • List to set conversion
  • Object vs tuple
  • Optional object attributes
  • Indexing maps vs lists
  • Automatic primitive conversion

Unlock with Premium — includes all practice exams and the complete study guide.

Expressions and functions

Read full chapter
  • No user-defined functions
  • Function call syntax and ellipsis
  • Function categories
  • terraform console interactive REPL
  • Ternary conditional syntax
  • Conditional result type
  • For expression syntax
  • Splat operator
  • dynamic blocks for repeatable nested blocks
  • String interpolation, heredocs, and template directives

Unlock with Premium — includes all practice exams and the complete study guide.

Resource dependencies

Read full chapter
  • Implicit dependencies preferred
  • Graph ordering direction
  • depends_on accepts references only
  • When to use depends_on
  • Default replacement order
  • create_before_destroy
  • prevent_destroy and replace_triggered_by
  • lifecycle ignore_changes suppresses out-of-band update proposals

Unlock with Premium — includes all practice exams and the complete study guide.

Custom condition validation

Read full chapter
  • Validation block syntax
  • Validation fails on false
  • Where pre/postconditions live
  • Pre vs post timing and self
  • Failed conditions block operations
  • Check block syntax
  • Checks are non-blocking

Unlock with Premium — includes all practice exams and the complete study guide.

Managing sensitive data

Read full chapter
  • sensitive redacts output only
  • State is plain text
  • Securing state
  • Ephemeral values omitted from state
  • Ephemeral usage contexts
  • Write-only arguments
  • Ephemeral resource block as a producer
  • Vault provider purpose
  • Vault secrets still land in state
  • Prefer short-lived credentials

Unlock with Premium — includes all practice exams and the complete study guide.

Terraform modules

How Terraform sources modules

Read full chapter

Cheat sheet

Sharp facts the exam loves — scan these before test day.

Local paths must begin with ./ or ../

A local path module source must begin with either ./ or ../ so Terraform recognizes it as a filesystem path rather than a registry address; for example source = "./modules/vpc". A bare relative name like modules/vpc is interpreted as a registry address, not a local path.

Trap Believing a bare relative path such as modules/vpc (without a leading ./) loads a local directory.

5 questions test this
Local modules are loaded in place, not downloaded

Terraform treats a local path module as part of the same package as the calling configuration and loads it directly from disk instead of fetching a cached copy. Edits to a local module take effect on the next plan or apply without re-running terraform get.

Trap Assuming local modules are copied into .terraform/modules and must be re-downloaded after every edit.

4 questions test this
The source value must be a literal string

The source argument must be a literal string and cannot contain variables, expressions, or interpolation, because module sources are resolved during terraform init before input variables are evaluated. This applies to every source type, local or remote.

Trap Trying to build a source dynamically, e.g. source = "./modules/${var.name}".

3 questions test this
Public registry address is //

A public Terraform Registry module is addressed with the three-part form <NAMESPACE>/<NAME>/<PROVIDER>, for example source = "hashicorp/consul/aws". The final PROVIDER segment is required, not optional.

Trap Thinking a registry address is only / and omitting the trailing provider segment.

5 questions test this
Private registry addresses add a host prefix

A module in a private registry is addressed by prepending the registry hostname to the standard address: <HOST>/<NAMESPACE>/<NAME>/<PROVIDER>, for example source = "app.terraform.io/example-corp/vpc/aws". Public registry modules omit the host.

Trap Using a git:: URL for a private-registry module instead of the host/namespace/name/provider address.

7 questions test this
HCP Terraform private module registry keeps modules confidential and versioned

A private module registry in HCP Terraform shares modules confidentially within an organization while still supporting Terraform's semantic version constraints and providing a browsable directory of published modules. A plain Git URL provides sharing but not the browsable versioned catalog.

Trap Assuming the public Terraform Registry can host organization-confidential modules.

5 questions test this
Git and GitHub module sources

Terraform installs modules from generic Git repositories with the git:: prefix (over HTTPS or SSH), and from GitHub with the shorthand source = "github.com/org/repo". Bitbucket URLs are also detected automatically.

Trap Believing every remote source needs the git:: prefix, even the github.com/ shorthand.

6 questions test this
S3, GCS, and HTTP archive sources

Terraform can source modules from object storage using the s3:: prefix (e.g. s3::https://s3-eu-west-1.amazonaws.com/bucket/vpc.zip) or the gcs:: prefix, and from plain HTTP URLs that point to a .zip archive. These sources fetch a compressed archive rather than cloning a repository.

Trap Thinking S3/GCS sources support a version argument like registry modules do.

7 questions test this
Double-slash selects a sub-directory within a package

For sources that fetch a whole package (Git, archive, object storage), the // double-slash selects a module in a sub-directory, for example git::https://example.com/network.git//modules/vpc. Everything before // identifies the package; everything after is the path inside it.

Variable scope within modules

Read full chapter
  • Child modules receive only explicitly passed inputs
  • Each module declares its own variables locally
  • Modules cannot reach into another module's variables
  • Parents read only explicitly declared child outputs
  • Output reference syntax is module.
  • Default provider configurations are inherited by child modules
  • Aliased providers must be passed explicitly
  • Reusable modules should not define provider blocks

Unlock with Premium — includes all practice exams and the complete study guide.

Using modules in configuration

Read full chapter
  • A module block needs a local name and a source
  • Inputs are passed as arguments matching child variable names
  • Modules must be installed before plan or apply
  • count creates numbered module instances
  • for_each creates keyed module instances
  • count and for_each cannot both be set
  • The providers meta-argument maps parent providers into a child
  • depends_on on a module applies to all its resources

Unlock with Premium — includes all practice exams and the complete study guide.

Managing module versions

Read full chapter
  • The version argument works only for registry modules
  • Omitting version installs the newest registry release
  • Version constraint operators for modules
  • Pin Git modules with the ?ref= query argument
  • ref accepts a branch, tag, or commit SHA
  • Pinning module versions is a best practice
  • terraform init installs modules
  • terraform get downloads and updates only modules
  • terraform get -update vs terraform init -upgrade

Unlock with Premium — includes all practice exams and the complete study guide.

Terraform state management

Describe the local backend

Read full chapter

Cheat sheet

Sharp facts the exam loves — scan these before test day.

Local backend is the default and writes terraform.tfstate

If a configuration has no backend or cloud block, Terraform uses the local backend, which stores state as a file named terraform.tfstate in the root module's working directory and performs all operations on the local machine.

Trap The local backend is not 'no backend' — it is a real backend Terraform selects by default.

8 questions test this
The path argument overrides the local state file location

The local backend's optional path argument sets the filename and location of the state file; when omitted it defaults to terraform.tfstate relative to the root module.

7 questions test this
Local backend locks state using system APIs

The local backend supports state locking, acquiring the lock through operating-system file-locking APIs rather than an external service.

Trap State locking is not exclusive to remote backends; the default local backend also locks state.

-state and -state-out override read/write state files

For the local backend, -state=FILENAME overrides the file Terraform reads prior state from and -state-out=FILENAME overrides the file it writes the new state snapshot to; when -state-out is unset it defaults to the -state path.

10 questions test this
-backup writes a state backup and -backup=- disables it

The local backend writes a backup of the previous state to .backup by default; the -backup=FILENAME flag overrides that path, and -backup=- disables backups entirely.

Legacy -state flags override workspace file selection

When you pass -state or -state-out, the selected workspace no longer determines the state filename, so you must manage distinct filenames per workspace yourself.

Trap Using -state does not switch workspaces; it bypasses workspace-based file selection entirely.

6 questions test this
Non-default workspaces live under terraform.tfstate.d

With the local backend, each non-default workspace's state is stored at terraform.tfstate.d//terraform.tfstate instead of the top-level state file.

12 questions test this
The default workspace uses the plain terraform.tfstate path

The default workspace stores its state directly at terraform.tfstate (or the configured path), not inside the terraform.tfstate.d directory.

Trap Only non-default workspaces use terraform.tfstate.d; the default workspace is not placed in a subdirectory.

9 questions test this
workspace_dir sets the non-default workspace directory

The local backend's optional workspace_dir argument overrides the default terraform.tfstate.d directory used to hold non-default workspace state files.

terraform workspace subcommands

The terraform workspace command family manages named workspaces that each keep their own separate state: new creates and switches to a workspace, select switches to an existing one, list shows all workspaces (marking the current one with an asterisk), show prints the current workspace name, and delete removes an empty workspace. Terraform always starts with a workspace named default, which cannot be deleted.

Trap You cannot delete the workspace you are currently on or the default workspace, and delete refuses to remove a workspace whose state still tracks resources unless forced.

5 questions test this

Describe state locking

Read full chapter
  • Locking happens automatically on state-writing operations
  • Terraform halts if it cannot acquire the lock
  • Locking support depends on the backend
  • -lock=false disables state locking
  • -lock-timeout retries lock acquisition for a duration
  • terraform force-unlock needs the lock ID
  • -force skips the force-unlock confirmation
  • Only force-unlock a lock you own

Unlock with Premium — includes all practice exams and the complete study guide.

Configure remote state with the backend block

Read full chapter
  • One backend block, nested in the terraform block
  • Built-in backend types for remote state
  • Backend blocks cannot reference variables
  • Partial configuration supplies backend args at init
  • Partial configuration keeps credentials out of code
  • HCP Terraform uses a cloud block, not a backend block
  • Changing the backend requires re-running terraform init
  • Why remote state (vs. default local state)

Unlock with Premium — includes all practice exams and the complete study guide.

Manage resource drift and Terraform state

Read full chapter
  • Drift is state diverging from real infrastructure
  • plan and apply refresh state in memory to detect drift
  • plan -refresh-only shows drift without config changes
  • apply -refresh-only updates state to match reality
  • terraform refresh is deprecated
  • -refresh-only replaced the refresh subcommand
  • state rm stops managing a resource without destroying it
  • state mv rebinds an object to a new address
  • moved block is the declarative alternative to state mv
  • removed block forgets resources via plan/apply

Unlock with Premium — includes all practice exams and the complete study guide.

Maintain infrastructure with Terraform

Import existing infrastructure

Read full chapter

Cheat sheet

Sharp facts the exam loves — scan these before test day.

Import requires a pre-existing resource block

Before running terraform import ADDRESS ID, you must already have written the target resource block in your configuration; the classic CLI import binds an existing object to that pre-existing address and cannot import into an address that has no matching resource block.

Trap Assuming terraform import writes the resource block for you — it only updates state, so the configuration must exist first.

4 questions test this
Two positional arguments: ADDRESS and ID

terraform import takes exactly two positional arguments, terraform import ADDRESS ID, where ADDRESS is the resource address in your configuration and ID is the provider-specific identifier of the real object; the ID format varies by resource type.

Trap Thinking the ID is a Terraform-chosen name — it is the provider's own object identifier and differs per resource type.

3 questions test this
CLI import only writes state

The terraform import CLI command only records the existing object in Terraform state; it does not generate configuration and does not create, modify, or destroy any real infrastructure.

Trap Expecting import to auto-generate HCL — the classic CLI command never generates configuration.

5 questions test this
No provider-specific import command

There is no provider-specific import command such as terraform import-gcp, and terraform refresh does not adopt unmanaged objects; the only CLI way to bring existing infrastructure under management is terraform import ADDRESS ID (or a config-driven import block).

Trap Believing a command like terraform import-gcp exists or that terraform refresh discovers and adopts unmanaged resources.

3 questions test this
import block uses to and id

The configuration-driven import block (Terraform 1.5+) declares an import with two arguments: to, the resource address to import into, and id, the provider-specific identifier of the existing object.

Trap Swapping the arguments — to is the Terraform resource address and id is the real object's provider ID, not the reverse.

7 questions test this
Import blocks run through plan and apply

An import block is executed through the normal workflow: terraform plan previews the planned import and terraform apply performs it; there is no separate import subcommand, and the id must be a literal or known value at plan time.

Trap Thinking import blocks need a special command — they are planned and applied like any other configuration change.

8 questions test this
Import blocks can be removed after apply

Because an import block only affects state (recording an existing object at its address), you can safely remove the block from configuration after a successful apply without destroying the resource.

-generate-config-out generates HCL

Running terraform plan -generate-config-out=<FILE> together with an import block generates HCL resource configuration for the imported objects into the given file; this config generation is a feature of import blocks, not of the classic terraform import CLI command.

Trap Trying to use -generate-config-out with the classic terraform import CLI command — only the config-driven import block supports generated configuration.

11 questions test this
Generated config is a starting point

Configuration produced by -generate-config-out is a starting point that you should review and edit before applying, since generated blocks may include attributes that need adjustment to produce a valid plan.

Inspect state with the CLI

Read full chapter
  • state list prints resource addresses
  • state show displays one resource's attributes
  • state show output is for humans
  • terraform state pull vs terraform state push
  • terraform show reads state or a plan file
  • terraform output prints root outputs
  • -json and -raw reveal sensitive values
  • terraform graph emits DOT
  • terraform providers prints requirement tree
  • terraform version reports versions

Unlock with Premium — includes all practice exams and the complete study guide.

Use verbose logging

Read full chapter
  • TF_LOG enables logs on stderr
  • TRACE is the most verbose level
  • TF_LOG=JSON emits JSON logs
  • Separate core and provider logging
  • Core and provider vars share the same levels
  • TF_LOG_PATH still needs TF_LOG set
  • When to use verbose logging
  • A crash prints a stack trace to stderr

Unlock with Premium — includes all practice exams and the complete study guide.

HCP Terraform

Use HCP Terraform to Create Infrastructure

Read full chapter

Cheat sheet

Sharp facts the exam loves — scan these before test day.

Remote execution runs Terraform on HCP Terraform VMs

In a workspace using Remote execution mode (the default), HCP Terraform (formerly Terraform Cloud) performs plan and apply on its own disposable virtual machines using that workspace's configuration, variables, and state. Switching a workspace to Local execution mode makes it act only as a remote state backend while runs execute on your own workstation or CI, which disables policy checks, cost estimation, and remote runs.

Trap Assuming Local execution mode also stores state locally — it still stores state remotely; only the run execution moves to your machine.

5 questions test this
Agent execution mode reaches private infrastructure

Agent execution mode runs Terraform on self-hosted HCP Terraform agents installed inside a private network, letting HCP Terraform manage runs against isolated or on-premises infrastructure it cannot reach directly.

State is stored remotely per workspace

HCP Terraform stores Terraform state remotely and separately for each workspace, automatically retaining prior state versions. When you use the cloud integration you do not add a separate backend block, and state is never committed to version control.

Trap Thinking you still need a backend block alongside the cloud integration — the cloud block replaces backend configuration and manages state itself.

10 questions test this
Remote run stage order

A remote run moves through ordered stages: it queues (pending), executes a plan, then runs cost estimation, then any policy check, and finally performs the apply (plan -> cost estimation -> policy check -> apply). HCP Terraform surfaces the output of both the plan and apply phases on the run's details page.

Trap Thinking the policy check precedes cost estimation, or that they are one combined step; cost estimation always runs first (plan -> cost estimation -> policy check -> apply), which is why a Sentinel policy can gate on the cost estimate.

6 questions test this
Manual apply pauses for Confirm & Apply

With manual apply (the default), a finished plan pauses and a user with apply permission must click Confirm & Apply to proceed or Discard the run. Auto-apply, when enabled on the workspace, automatically applies plans that complete without errors.

Trap Assuming auto-apply is the default — HCP Terraform requires manual confirmation unless auto-apply is explicitly turned on.

5 questions test this
Each workspace processes its run queue in order

Every workspace maintains its own run queue and processes apply-capable runs one at a time, in order. Changing variables or configuration only affects future runs, not a run that has already been planned.

HCP Terraform cost estimation run stage

In an HCP Terraform run, cost estimation is a distinct stage that runs after the plan and BEFORE the policy check (order: plan -> cost estimation -> policy check -> apply), which is why a Sentinel policy can reference the estimate via the tfrun import. It produces the estimated total monthly cost of the resources in the plan plus the monthly delta (the cost change from the proposed run) for supported major providers (AWS, Azure, GCP), and is enabled per-organization in the organization settings.

Trap Assuming cost estimation runs after, or together with, the policy check; it actually runs before the policy check, which is exactly what lets a Sentinel policy gate on the estimated cost.

6 questions test this
Three run workflows: UI/VCS, CLI, and API driven

HCP Terraform can start runs three ways: UI/VCS-driven (webhooks from a connected repository), CLI-driven (running terraform plan/apply locally with the cloud block configured), and API-driven (uploading a configuration version through the Runs API).

6 questions test this
Speculative plans preview but cannot apply

A speculative plan is a plan-only run that previews proposed changes and policy results but can never apply changes or modify state. Because it cannot alter infrastructure, it bypasses the workspace lock and does not block other runs.

Trap Believing a speculative plan can be confirmed into an apply — it is strictly read-only and has no Confirm & Apply.

9 questions test this
Commit triggers a full run, PR triggers a speculative plan

For a VCS-connected workspace, a commit or merge to the tracked branch triggers a full run (plan then apply), while opening a pull request triggers only a speculative plan whose result is posted back to the PR.

4 questions test this

HCP Terraform Collaboration and Governance

Read full chapter
  • Team management is gated to paid editions
  • Every organization has a permanent owners team
  • Permissions apply at organization, project, and workspace scope
  • Policy sets bundle Sentinel or OPA policies
  • Policies are checked between plan and apply
  • Sentinel policy enforcement levels
  • Audit trails require Standard or Premium
  • Private registry shares modules internally on all tiers
  • SSO and run approvals support secure collaboration
  • HCP Terraform health assessments

Unlock with Premium — includes all practice exams and the complete study guide.

Organizing HCP Terraform Workspaces and Projects

Read full chapter
  • HCP workspaces differ from CLI workspaces
  • Each workspace owns its state, variables, and runs
  • Workspaces keep historical state versions
  • Execution mode and apply method are per-workspace
  • Locking a workspace blocks applies
  • Workspaces share data through outputs
  • terraform_remote_state data source
  • HCP Terraform run triggers
  • Projects are folders that group workspaces
  • Permissions can be granted at the project level
  • New workspaces land in the Default Project

Unlock with Premium — includes all practice exams and the complete study guide.

Configure and Use HCP Terraform Integration

Read full chapter
  • The cloud block lives in the terraform block
  • workspaces uses name for one, tags for many
  • hostname defaults to app.terraform.io
  • terraform login retrieves an API token
  • Token is saved in credentials.tfrc.json
  • VCS integration installs a webhook to trigger runs
  • Terraform variables vs environment variables
  • Variable sets reuse variables across workspaces
  • Sensitive variables are write-only
  • HCP Terraform dynamic provider credentials

Unlock with Premium — includes all practice exams and the complete study guide.