Courseiva

HashiCorp Certified: Terraform Authoring and Operations Professional (AWS provider) (AWS provider) (AWS provider) — Questions 1–75

278 questions total · 4 pages · All types, answers revealed

Page 1 of 4

Page 2
1
MCQeasy

You are defining an input variable for a Terraform module that will accept a list of AWS subnet IDs. You want to ensure that the variable only accepts a list of strings and that it is required. Which variable declaration correctly achieves this?

A.variable "subnet_ids" { type = set(string) }
B.variable "subnet_ids" { type = list(string) default = [] }
C.variable "subnet_ids" { type = string }
D.variable "subnet_ids" { type = list(string) }
AnswerD

This declaration defines a required variable of type list(string). Since no default is provided, it is required. The type constraint ensures that only a list of strings is accepted, which is exactly what is needed for subnet IDs.

Why this answer

The correct variable declaration uses type = list(string) and does not provide a default, making it a required variable. This ensures that callers must supply a list of strings. The other options either make the variable optional, use a different collection type, or use a scalar type, all of which fail to meet the specified requirements.

Exam trap

The trap here is overlooking that providing a default value, even an empty list, makes the variable optional rather than required.

2
MCQhard

If a Terraform run is stuck in a 'Policy Check' phase, which step should an administrator take?

A.Check the Policy Set configuration and execution logs.
B.Trigger a new plan.
C.Delete and recreate the workspace.
D.Disable the policy check.
AnswerA

A run stalled at Policy Check usually means Sentinel cannot evaluate the policy set, often through misconfiguration or an execution error. Reviewing the policy set configuration and its execution logs identifies the blocking cause so the run can proceed.

Why this answer

A run stuck in the Policy Check phase means the policy evaluation is either failing, erroring, or awaiting override. The administrator should inspect the Policy Set configuration and the run's policy execution logs to identify which policy is blocking and why. This is the direct diagnostic step before considering overrides or fixes.

Exam trap

The trap is reaching for destructive or bypass actions (recreate workspace, disable policy) instead of the diagnostic step — exams reward troubleshooting over circumvention.

How to eliminate wrong answers

Option B is wrong because triggering a new plan does not resolve a policy block — the same policy will evaluate the new plan and likely block again, wasting time and potentially creating duplicate runs. Option C is wrong because deleting and recreating the workspace destroys state history and configuration for no reason; the issue is policy-related, not workspace-related. Option D is wrong because disabling the policy check bypasses governance rather than diagnosing it, and may violate organizational controls; it should only be a last resort after understanding the failure.

3
MCQhard

Your organization uses HCP Terraform to manage AWS infrastructure. You need to grant a team the ability to create and manage workspaces within a specific project, but prevent them from deleting the project itself or modifying project-level settings. Which HCP Terraform team permission should you assign?

A.Project Read
B.Organization Owner
C.Project Admin
D.Project Write
AnswerD

Project Write permission allows a team to create and manage workspaces within the project, including running applies and managing workspace variables, but it does not permit deleting the project or changing project-level settings. This aligns exactly with the requirement to delegate workspace management without granting project administration rights.

Why this answer

Project Write permission is designed for teams that need to manage workspaces within a project without administrative control over the project itself. It allows workspace creation, configuration, and runs, but not project deletion or settings changes. Project Admin and Organization Owner grant excessive privileges, while Project Read is too limited.

Exam trap

The trap here is assuming that Project Admin is needed to create workspaces, when Project Write already provides that capability without project deletion rights.

4
MCQmedium

A downstream workspace in HCP Terraform needs to automatically trigger a plan after a successful apply in an upstream workspace. How do you configure this?

A.Configuring Run Triggers in the downstream workspace
B.Enabling 'Auto-apply' in the upstream
C.Setting a 'TF_VAR' environment variable
D.Using a local variable
AnswerA

Run Triggers let a downstream workspace watch specified upstream workspaces and queue a plan automatically once their apply succeeds. This directly satisfies the stem's requirement for automatic triggering, since no manual run or webhook scripting is needed.

Why this answer

Run Triggers in HCP Terraform allow a downstream workspace to automatically queue a run when a specified upstream workspace completes a successful apply. This is the native mechanism for chaining workspaces, ensuring that dependent infrastructure is updated only after its dependencies are provisioned.

Exam trap

The trap is confusing Auto-apply with Run Triggers; Auto-apply automates the apply step within a single workspace, while Run Triggers automate cross-workspace run initiation.

How to eliminate wrong answers

Option B is wrong because enabling 'Auto-apply' in the upstream workspace only controls whether runs in that workspace are automatically applied after a plan; it does not trigger runs in other workspaces. Option C is wrong because setting a 'TF_VAR' environment variable provides input variables to Terraform configurations but does not trigger runs across workspaces. Option D is wrong because local variables are used within a Terraform module for internal calculations and have no effect on cross-workspace orchestration.

5
MCQmedium

When defining a provider in Terraform, what does the 'alias' meta-argument signify?

A.It links to a different provider type.
B.It defines the provider's short name.
C.It allows using multiple configurations of the same provider.
D.The provider is deprecated.
AnswerC

The alias meta-argument creates a named, separate instance of a provider configuration, letting one module address multiple regions, accounts or endpoints of the same provider. Without it, only a single default configuration per provider could be declared.

Why this answer

The 'alias' meta-argument lets you declare multiple configurations of the same provider within a single configuration, each with different settings (e.g., different AWS regions or accounts). Resources then reference the aliased provider to control which configuration they use.

Exam trap

The trap is thinking alias renames or re-points the provider type — candidates confuse it with the local name in required_providers, but alias is strictly for multiple configurations of the same provider.

How to eliminate wrong answers

Option A is wrong because alias does not link to a different provider type — it creates a named variant of the same provider. Option B is wrong because the provider's short name is defined by the local name in required_providers, not by alias. Option D is wrong because alias has nothing to do with deprecation; it is purely a mechanism for multiple provider configurations.

6
MCQhard

You want to trigger a run only when a specific file within a module path changes. How do you configure this?

A.Use the 'VCS Triggers' setting in the workspace.
B.Use a 'trigger_path' variable in the Terraform code.
C.Modify the '.terraform-version' file.
D.Use a Sentinel policy to filter changes.
AnswerA

VCS Triggers let you filter runs by file path patterns, so specifying the module path ensures a run triggers only when files within it change, satisfying the constraint of scoping runs to a specific module directory.

Why this answer

HCP Terraform (formerly Terraform Cloud) workspaces support VCS Triggers, which let you specify file or directory paths so that a run is only queued when changes are detected in those paths. This is the native mechanism for path-based run triggering tied to version control commits.

Exam trap

HCP Terraform exams often test the confusion between VCS Triggers (path-based run filtering) and run triggers (workspace-to-workspace dependencies), or invent non-existent variables like 'trigger_path'.

How to eliminate wrong answers

Option B is wrong because 'trigger_path' is not a Terraform variable or configuration primitive — there's no such built-in variable for controlling run triggers. Option C is wrong because '.terraform-version' specifies the Terraform CLI version to use, not run trigger behavior. Option D is wrong because Sentinel is a policy-as-code framework for enforcing compliance on plans, not for filtering which file changes trigger runs.

7
MCQmedium

What is the primary risk of relying solely on 'create_before_destroy' without considering dependency chains?

A.It can lead to resource contention or naming conflicts.
B.It causes infinite loops in Terraform.
C.It increases the cost of the plan.
D.It creates a security risk.
AnswerA

Relying on create_before_destroy duplicates dependent resources before the originals are removed, so unique names, tags, or quotas collide. This directly satisfies the stem's dependency-chain constraint: Terraform cannot sequence replacements, producing naming conflicts and resource contention during the overlap window.

Why this answer

'create_before_destroy' makes Terraform create the replacement resource before destroying the old one. When resources have unique names, fixed IPs, or other globally unique identifiers, the new resource cannot be created while the old one still exists, causing naming conflicts or resource contention. This is the primary risk when dependency chains are not carefully considered.

Exam trap

The trap is assuming 'create_before_destroy' is always safe for zero-downtime — candidates forget that unique naming constraints and dependency chains can force a conflict, making 'resource contention or naming conflicts' the correct risk.

How to eliminate wrong answers

Option B is wrong because 'create_before_destroy' does not cause infinite loops — Terraform's graph is acyclic and the lifecycle flag only reorders create/destroy operations. Option C is wrong because plan cost is not affected by lifecycle ordering; cost estimation depends on resource types and counts, not on create/destroy sequencing. Option D is wrong because 'create_before_destroy' is not inherently a security risk — it is an availability/ordering concern, not a security control.

8
MCQhard

Your team maintains a Terraform configuration that uses the AWS provider with an S3 backend. A security review requires that provider credentials never be stored in plaintext in the configuration or state. You currently use a shared credentials file referenced by the `profile` argument. Which change best satisfies this requirement while keeping the configuration portable across CI and developer machines?

A.Create a `terraform.tfvars` file containing the access key and secret key as variables and reference them in the provider block.
B.Remove credential arguments and rely on the standard AWS credential provider chain, such as environment variables, IAM roles, or SSO profiles.
C.Hardcode the access key and secret key as arguments in the `provider "aws"` block and mark them `sensitive = true`.
D.Store the credentials in the S3 backend configuration using the `access_key` and `secret_key` arguments.
AnswerB

The AWS provider automatically uses the default credential provider chain when no explicit credentials are set. This includes environment variables, shared credentials files, IAM roles for EC2 or ECS, and AWS SSO. Relying on this chain keeps secrets out of the configuration and state, and allows each environment to supply credentials through its native mechanism, satisfying portability and security.

Why this answer

The AWS provider integrates with the standard AWS credential provider chain when no explicit credentials are supplied. This allows credentials to be sourced from environment variables, shared files, IAM roles, or SSO, keeping secrets out of Terraform configuration and state. It also supports portability, since CI systems and developer machines can use their own credential mechanisms without changing the Terraform code.

Exam trap

The trap here is thinking that marking credentials as sensitive or placing them in tfvars or backend configuration removes plaintext exposure, when in fact only relying on the credential provider chain avoids storing secrets in Terraform artifacts.

9
Multi-Selectmedium

Which THREE of the following are components of the 'source' string when using the Terraform Registry?

Select 3 answers
A.Git branch name.
B.Provider.
C.Operating system.
D.Module name.
E.Namespace.
AnswersB, D, E

The provider segment identifies which plugin Terraform must download, formatted as `namespace/type` (for example `hashicorp/aws`), and optionally constrains the version. It satisfies the stem's requirement by naming a mandatory component of the source address, alongside the hostname and module subdirectory, enabling correct registry resolution.

Why this answer

The Terraform Registry module source string follows the format <NAMESPACE>/<MODULE_NAME>/<PROVIDER>, so option B (Provider) is correct because the provider segment (e.g., aws, azurerm, google) identifies which provider the module targets. Option D (Module name) is correct because it is the middle segment that names the specific module being referenced. Option E (Namespace) is correct because it is the first segment, identifying the organization or user that publishes the module.

Option A (Git branch name) is not part of the Registry source string; branch/ref syntax (e.g., ?ref=) applies to generic Git sources, not the Registry's three-part address. Option C (Operating system) is irrelevant, as the Registry source string does not encode any OS information.

Exam trap

The trap is confusing the registry source format with Git-based module sources — candidates may include 'branch' or 'ref' thinking it is always required, but the registry shorthand only needs namespace, name, and provider.

10
MCQhard

During a CI pipeline run, `terraform init` fails with an error stating that the checksums recorded in `.terraform.lock.hcl` do not match any of the packages available from the configured provider mirror. The mirror is an internal registry serving only linux_amd64 builds, while the lock file was generated on a developer's darwin_arm64 laptop. Which action resolves the failure while keeping the lock file authoritative for CI?

A.Add a `provider_installation` block that maps the AWS provider to the mirror and re-run `terraform init -upgrade` to refresh the hashes.
B.Delete `.terraform.lock.hcl` in the pipeline and let `terraform init` recreate it from the mirror on every run.
C.Set the environment variable `TF_CLI_CONFIG_FILE` to point at a CLI configuration that disables checksum verification during init.
D.Run `terraform providers lock` with `-platform=linux_amd64` against the internal mirror and commit the updated lock file.
AnswerD

`terraform providers lock` records checksums for the platforms you name, so adding linux_amd64 lets CI verify the mirror's package against the lock file. Because the mirror only serves linux_amd64, this is the platform whose hashes must be present, and regenerating the file against the mirror captures the correct values.

Why this answer

The lock file pins provider packages by version and by platform-specific checksums. A lock file containing only darwin_arm64 hashes cannot validate a linux_amd64 package, regardless of mirror configuration. Re-running `terraform providers lock` with the target platform against the internal mirror records the linux_amd64 hashes, after which CI can verify and install the provider.

Exam trap

The trap here is treating the lock file as platform-neutral, when its checksums are recorded per operating system and architecture.

11
MCQmedium

You are authoring a Terraform module that must accept a map of environment names to instance counts. The map is provided by callers and may contain up to 20 entries. You need to derive a flat list of instance names in the form "<env>-<index>" (e.g., "prod-0", "prod-1") so that a downstream resource can use `for_each` with stable keys. Which expression correctly produces this list?

A.concat([for env, count in var.instance_counts : "${env}-${count}"])
B.[for env, count in var.instance_counts : "${env}-${count}"]
C.flatten([for env, count in var.instance_counts : [for i in range(count) : "${env}-${i}"]])
D.[for env, count in var.instance_counts : { name = "${env}-${count}" }]
AnswerC

This nested for expression first builds, for each environment, a list of names from 0 to count-1, then flattens the resulting list of lists into a single flat list. It correctly expands each environment's count into individual instance names, matching the required "<env>-<index>" format for use with for_each.

Why this answer

The requirement is to expand each environment's count into individual instance names and then combine them into one flat list. A nested for expression with flatten achieves this by generating a list of names per environment and then merging them. The other options either produce the wrong data shape or fail to expand the count into multiple entries.

Exam trap

The trap here is assuming that a simple for expression over a map can expand a numeric count into multiple elements without an inner loop or flatten.

12
MCQmedium

Which meta-argument is used to explicitly associate a resource with a non-default provider instance?

A.configuration
B.alias
C.provider
D.instance
AnswerC

The provider meta-argument explicitly binds a resource block to a named provider configuration, such as aws.west, overriding the default instance. This satisfies the requirement to associate a resource with a non-default provider instance within the same configuration.

Why this answer

The `provider` meta-argument is used within a resource block to explicitly specify which provider configuration to use, especially when multiple provider configurations exist (e.g., different regions or accounts). For example, `provider = aws.west` tells Terraform to use the `aws` provider instance with the alias `west`. This overrides the default provider configuration for that resource.

Exam trap

The trap here is confusing the `alias` argument in a provider block with the `provider` meta-argument in a resource block; candidates often mistakenly select `alias` because it is associated with provider instances, but the correct meta-argument for resource association is `provider`.

How to eliminate wrong answers

Option A is wrong because `configuration` is not a valid meta-argument in Terraform; it does not exist for associating resources with providers. Option B is wrong because `alias` is used within a provider block to create a named instance, not within a resource block to reference one. Option D is wrong because `instance` is not a Terraform meta-argument; it might be confused with provider instance terminology but is not used in resource configuration.

13
MCQhard

An operations engineer runs `terraform init` and notices Terraform downloads the AWS provider from `registry.terraform.io`. The organization requires all provider packages to come from an internal mirror at `mirror.example.com` for compliance. The engineer adds a `provider_installation` block to the CLI configuration file. Which CLI configuration file location and block structure will make Terraform use the mirror for the AWS provider while still allowing other providers from the public registry?

A.Create a `.terraform.lock.hcl` entry mapping the AWS provider to the mirror hostname so `terraform init` reads the source from the lock file.
B.Set the `TF_REGISTRY_CLIENT_TIMEOUT` environment variable to the mirror URL so Terraform prefers the mirror over the public registry.
C.Add a `provider_installation` block inside the root module's `terraform` block so it applies to every workspace using that configuration.
D.Place a `provider_installation` block with a `filesystem_mirror` or `network_mirror` directive in the `.terraformrc` file in the user's home directory, or in `terraform.rc` on Windows.
AnswerD

The CLI configuration file is `~/.terraformrc` on Unix-like systems and `terraform.rc` in the user's `%APPDATA%` directory on Windows. A `provider_installation` block there can define a `network_mirror` or `filesystem_mirror` source, optionally scoped to the `hashicorp/aws` provider, so only AWS resolves from the mirror while other providers continue from the public registry.

Why this answer

Provider install sources are controlled by the CLI configuration file, which lives at `~/.terraformrc` on Unix-like systems and `terraform.rc` under `%APPDATA%` on Windows. A `provider_installation` block there can declare a `network_mirror` or `filesystem_mirror` and include or exclude specific provider source addresses, so the AWS provider resolves from the internal mirror while others continue to use the public registry.

Exam trap

The trap here is confusing Terraform language configuration with CLI configuration and attempting to place `provider_installation` inside a `terraform` block or the lock file.

14
Multi-Selecthard

Which TWO factors must be considered when using 'replace_triggered_by' with multiple resources?

Select 2 answers
A.The trigger only works on the 'tags' attribute.
B.The trigger requires 'create_before_destroy' to be false.
C.The trigger cannot cause a circular dependency loop.
D.The referenced resource must be in the same state file.
E.The trigger only works with AWS resources.
AnswersC, D

Because replace_triggered_by creates a dependency edge from the triggering resource to the replaced one, referencing resources that already depend on each other forms a cycle, which Terraform rejects during graph construction. Avoiding circular dependency loops is therefore mandatory for valid configuration.

Why this answer

Option C is correct because replace_triggered_by creates a dependency edge from the referencing resource to the referenced resource, so if the referenced resource already depends on the referencing one (directly or transitively), Terraform will detect a circular dependency and fail the plan. Option D is correct because replace_triggered_by can only reference resources (or attributes) that Terraform knows about within the same configuration/state; cross-state references are not resolvable as trigger sources, so the referenced resource must live in the same state file. Option A is wrong because replace_triggered_by works against any resource or attribute reference, not just the tags attribute.

Option B is wrong because replace_triggered_by has no requirement that create_before_destroy be false; the two settings are independent. Option E is wrong because replace_triggered_by is provider-agnostic and works with any Terraform resource, not only AWS resources.

Exam trap

The trap is assuming `replace_triggered_by` works across state files or with any attribute; actually, it requires same-state references and cannot form cycles.

15
Multi-Selecthard

Which TWO of the following are required to successfully integrate VCS with HCP Terraform?

Select 2 answers
A.A direct peering link.
B.A VPN connection between AWS and HCP Terraform.
C.A static IP address for the organization.
D.An OAuth application created in the VCS provider.
E.A configured VCS connection in the organization settings.
AnswersD, E

Creating an OAuth application in the VCS provider is mandatory: HCP Terraform uses its OAuth client ID and secret to obtain authorisation tokens, letting it read repositories and register webhooks for automatic runs. Without this OAuth handshake, no VCS connection can be established.

Why this answer

Option D is correct because integrating a VCS provider with HCP Terraform requires registering an OAuth application (OAuth client) in the VCS provider, such as GitHub, GitLab, or Bitbucket, so that HCP Terraform can be authorized to access repositories on the organization's behalf. Option E is correct because, after the OAuth credentials (OAuth app ID and secret) are supplied, you must create and configure a VCS connection within the HCP Terraform organization settings, which links the organization to the VCS provider and enables VCS-driven workspaces. Options A and B are incorrect because HCP Terraform communicates with VCS providers over the public internet via HTTPS APIs and webhooks; no direct peering link or AWS-to-HCP Terraform VPN is needed for VCS integration.

Option C is incorrect because a static IP address for the organization is not a prerequisite for VCS integration; HCP Terraform's agent and VCS communication do not depend on a fixed organization-level IP.

Exam trap

The trap is overcomplicating the requirements with network concepts like peering or VPN. Candidates might think a direct connection is needed, but VCS integration is purely API-based over the internet. The exam tests the specific components: OAuth app and VCS connection.

16
MCQeasy

What is the recommended approach for managing a module that has grown too large?

A.Use 'terraform import' to split the resources.
B.Combine all files into a single 'main.tf'.
C.Rename the module to something more generic.
D.Break the module into smaller, focused sub-modules.
AnswerD

Splitting an oversized module restores single responsibility, so each sub-module owns one concern and exposes a narrow interface. This directly resolves the stem's constraint of a module that has grown too large, cutting blast radius and making plans, reviews and reuse manageable.

Why this answer

Breaking a large module into smaller, focused sub-modules is the recommended approach because it improves reusability, testability, and blast-radius control. Each sub-module encapsulates a single logical concern (e.g., networking, compute, IAM), making plans faster and state operations safer. Terraform's module composition model is designed for this kind of decomposition, and refactoring can be done with 'moved' blocks to avoid destroying resources.

Exam trap

The trap here is confusing 'terraform import' (a state-management tool) with a refactoring tool — candidates see 'split the resources' and assume import is involved, but import never restructures modules.

How to eliminate wrong answers

Option A is wrong because 'terraform import' only brings existing infrastructure under Terraform state management — it does not split or refactor a module, and using it to 'split' resources would cause state churn and potential destruction. Option B is wrong because merging everything into a single 'main.tf' makes the module larger and harder to maintain, the opposite of the recommended practice. Option C is wrong because renaming a module changes nothing about its size, coupling, or maintainability — it is a cosmetic change with no architectural benefit.

17
MCQeasy

Where do module outputs appear after a 'terraform apply'?

A.In a file named 'outputs.json'.
B.They are automatically emailed to the Terraform administrator.
C.In the CLI output and the state file.
D.In the '.terraform/modules' directory.
AnswerC

Terraform prints root module outputs to the CLI after apply, and persists every output value in the state file for later retrieval. This satisfies the question's requirement that outputs appear in both locations, since child module outputs remain accessible via the state even when not displayed directly.

Why this answer

After 'terraform apply', module outputs are displayed in the CLI output (as part of the apply summary) and are persisted in the Terraform state file. The state file records output values so they can be referenced by other configurations or retrieved later via 'terraform output'.

Exam trap

Terraform exams often test the misconception that outputs are written to a separate file or emailed, when they actually appear in CLI output and the state file.

How to eliminate wrong answers

Option A is wrong because Terraform does not create an 'outputs.json' file automatically — outputs live in state and CLI, not a standalone JSON file (though 'terraform output -json' can print them). Option B is wrong because Terraform has no email notification feature; that's not part of its behavior. Option D is wrong because '.terraform/modules' stores downloaded/cached module source code, not output values.

18
Multi-Selectmedium

Which THREE of the following are true regarding 'create_before_destroy'?

Select 3 answers
A.It is intended to minimize downtime during updates.
B.It is defined within the resource lifecycle block.
C.It requires sufficient quota to temporarily have two resources.
D.It automatically resolves all name collision issues.
E.It is only available for AWS providers.
AnswersA, B, C

The lifecycle argument reverses Terraform's default destroy-then-create order, provisioning the replacement first so the old resource keeps serving traffic until the new one is ready. This directly satisfies the stem's downtime constraint, since the default ordering leaves a gap where no resource exists.

Why this answer

Option A is correct because create_before_destroy changes Terraform's default destroy-then-create ordering so the replacement resource is provisioned first, keeping the old resource serving until the new one is ready and thereby minimizing downtime during updates. Option B is correct because create_before_destroy is a meta-argument configured inside a resource's lifecycle block, for example lifecycle { create_before_destroy = true }. Option C is correct because running both the old and new resource simultaneously requires enough provider quota/capacity to temporarily hold two instances of that resource.

Option D is not correct because create_before_destroy does not automatically resolve name collisions; unique-name constraints (such as fixed Name tags or DNS names) can still cause the create step to fail and often require name generators or other workarounds. Option E is not correct because create_before_destroy is a core Terraform lifecycle meta-argument available across providers, not an AWS-only feature.

Exam trap

The trap is assuming create_before_destroy magically solves all replacement problems — candidates forget it can actually CAUSE name-collision failures and that it consumes double the quota temporarily.

19
Multi-Selecthard

Which TWO of the following are valid ways to handle a resource that has become 'tainted'?

Select 2 answers
A.Run 'terraform apply' to recreate it.
B.Run 'terraform untaint <resource_name>' to clear the status.
C.Run 'terraform refresh' to clear the taint.
D.Use 'terraform state rm' to fix the taint.
E.Use 'terraform plan -force-apply'.
AnswersA, B

A tainted resource is marked for destruction and recreation on the next apply, so running terraform apply replaces it, satisfying the requirement to handle the taint. Terraform reads the taint flag from state and plans a destroy-then-create cycle without further intervention.

Why this answer

Option A is correct because running 'terraform apply' after a resource has been tainted causes Terraform to destroy and recreate that resource, which is the standard way to replace a tainted object. Option B is correct because 'terraform untaint <resource_name>' explicitly removes the taint marker from the resource in the state, leaving the existing object in place without forcing replacement. Option C is wrong because 'terraform refresh' only reconciles state with real infrastructure and does not clear taint status.

Option D is wrong because 'terraform state rm' removes the resource from state entirely, which is not a taint-handling operation and can cause orphaned infrastructure. Option E is wrong because 'terraform plan' has no '-force-apply' flag; it only previews changes and cannot apply or clear a taint.

Exam trap

The trap here is confusing state-reconciliation commands (refresh) or state-removal commands (state rm) with taint management — only apply and untaint actually change the tainted status.

20
MCQmedium

Your organization uses HCP Terraform with a private module registry. A developer wants to use a module from the registry in a new configuration. The module is versioned and published. What is the correct way to reference this module in the Terraform configuration?

A.Use a Git URL pointing to the module's repository.
B.Use the module source address in the format 'app.terraform.io/<namespace>/<module-name>/<provider>' with a version constraint.
C.Download the module manually and place it in a local 'modules' directory, then reference it with a relative path.
D.Use the module's API endpoint URL directly in the source argument.
AnswerB

Private modules in HCP Terraform are referenced using the registry's hostname, namespace, module name, and provider, followed by a version constraint. This allows Terraform to fetch the specified version from the registry, ensuring consistency and leveraging registry features like versioning and access control.

Why this answer

Private modules in HCP Terraform are consumed by specifying a source address that includes the registry hostname, namespace, module name, and provider, along with a version constraint. This ensures Terraform retrieves the correct version from the registry, enabling version pinning and access control.

Exam trap

The trap here is assuming that any URL or local path can substitute for the registry source address, ignoring the standardized format required for private module consumption.

21
MCQhard

What happens if you use a dynamic block with a 'for_each' expression that evaluates to an empty set?

A.It pauses execution and waits for input
B.It throws a configuration error
C.It renders no blocks
D.It generates a single block with null values
AnswerC

A dynamic block iterates its for_each collection to generate nested blocks. When that collection is an empty set, the iterator produces zero iterations, so no nested blocks are rendered at all and the resource is created without them.

Why this answer

Terraform's dynamic blocks iterate over the collection given to 'for_each'; if that collection is empty (empty set, list, or map), the iterator produces zero iterations and therefore zero nested blocks are rendered. This is the documented and intended behaviour, allowing conditional block generation without 'count' hacks.

Exam trap

The trap is assuming Terraform treats an empty 'for_each' as an error or as a null block — candidates who have not tested this often pick 'throws a configuration error' or 'generates a single block with null values' instead of the correct 'renders no blocks'.

How to eliminate wrong answers

Option A is wrong because Terraform never pauses for interactive input during plan/apply — it is non-interactive by design and would error or proceed, not wait. Option B is wrong because an empty 'for_each' is a valid, supported case; Terraform only errors if 'for_each' is given a value it cannot iterate (e.g., null in some versions) or a non-collection type. Option D is wrong because Terraform does not synthesize a placeholder block with nulls — it simply emits no block at all, which is why downstream references to the block must be guarded.

22
MCQhard

How do you pass a provider instance from a root module into a child module?

A.Use a module output.
B.Use a variable.
C.Use the 'providers' map in the module block.
D.You cannot pass providers.
AnswerC

The providers map inside a module block passes a configured provider instance, aliased or default, into the child module, so the child uses the parent's configuration rather than instantiating its own. This satisfies explicit provider inheritance across module boundaries.

Why this answer

The providers map inside a module block explicitly passes a configured provider instance (or alias) from the root module into the child module, allowing the child to use a specific provider configuration rather than inheriting the default. This is required when the child module needs a non-default provider alias, a differently configured region, or a provider defined only in the parent. The syntax is providers = { aws = aws.us_east_1 } inside the module block.

Exam trap

The trap is assuming variables or outputs can carry provider configurations — they cannot, because providers are special runtime objects that must be passed via the providers map in the module block.

How to eliminate wrong answers

Option A is wrong because module outputs flow data out of a child module to the parent, not provider configurations into the child — outputs cannot carry provider instances. Option B is wrong because input variables pass values (strings, numbers, lists, objects) but cannot carry provider configurations, which are special runtime objects. Option D is wrong because Terraform explicitly supports passing providers via the providers map, and this is the documented mechanism for provider aliasing across module boundaries.

23
MCQeasy

You have a module `terraform-aws-modules/vpc/aws` version `3.14.0` from the public Terraform Registry. You want to ensure that your configuration always uses this exact version and does not automatically upgrade to newer versions. Which version constraint should you specify in the module block?

A.version = "~> 3.14.0"
B.version = "3.14.0"
C.version = "3.14.*"
D.version = ">= 3.14.0"
AnswerB

Specifying `version = "3.14.0"` without any operators pins the module to exactly that version. Terraform will not select any other version, ensuring consistency. This satisfies the requirement to always use the exact version and prevents automatic upgrades. It is the correct way to lock a module version in a module block.

Why this answer

To pin a module to an exact version, specify the version string without any operators or wildcards. This ensures Terraform uses only that version. Other constraints like `~>`, `>=`, or wildcards allow some degree of version flexibility, which can lead to unexpected changes.

Exact pinning is appropriate when stability is paramount.

Exam trap

The trap here is confusing the pessimistic constraint operator `~>` with exact pinning; it allows patch-level updates.

24
Multi-Selectmedium

You are creating a Terraform module that will be used by multiple teams. You want to ensure that the module is reusable and maintainable. Which TWO practices should you follow when designing the module's interface? (Choose two.)

Select 2 answers
A.Validate variable inputs using validation blocks where appropriate.
B.Expose outputs for all resources created by the module.
C.Use a single variable of type any to accept all inputs for simplicity.
D.Provide default values for all variables to make the module easy to use.
E.Define variables with descriptive names and include descriptions.
AnswersA, E

Validation blocks allow you to enforce constraints on variable values, catching errors early. This improves module robustness and provides clear error messages to consumers. It is a best practice to validate critical inputs, such as ensuring CIDR blocks are valid or instance types are in an allowed list.

Why this answer

Descriptive variable names with descriptions and validation blocks are key to a well-designed module interface. They enhance clarity, usability, and error prevention. Avoiding type any and unnecessary defaults or outputs keeps the module focused and secure.

These practices make the module easier to understand, use, and maintain across teams.

Exam trap

The trap here is thinking that providing defaults for every variable always improves usability, but some variables should remain required to prevent misconfiguration.

25
MCQmedium

What is the primary function of the 'source' attribute in the 'required_providers' block?

A.To define the local path of the provider code.
B.To define the AWS region.
C.To specify the registry address.
D.To enable debugging.
AnswerC

The source attribute gives the provider's registry address, such as registry.terraform.io/hashicorp/aws, telling Terraform where to resolve and download the plugin. This satisfies the requirement to identify the provider's origin rather than merely its local name or version constraint.

Why this answer

The 'source' attribute in the 'required_providers' block specifies the global source address of the provider, which is the registry hostname, namespace, and type. This tells Terraform where to download the provider from, such as 'hashicorp/aws' or 'registry.terraform.io/hashicorp/aws'. It does not define a local path or region.

Exam trap

The trap here is confusing the 'source' attribute with the provider's configuration block, where region and other settings are defined. Candidates might think 'source' refers to a local path or region due to its name.

How to eliminate wrong answers

Option A is wrong because the local path of provider code is not defined by 'source'; instead, a filesystem mirror or local registry can be used, but that is configured via CLI or provider installation methods. Option B is wrong because the AWS region is configured in the provider block or via environment variables, not in 'required_providers'. Option D is wrong because debugging is enabled via TF_LOG environment variable, not through the 'source' attribute.

26
MCQhard

You want to remove a resource from Terraform management without destroying the actual AWS resource. Which command accomplishes this?

A.terraform destroy -target
B.terraform untrack
C.terraform apply -ignore
D.terraform state rm
AnswerD

terraform state rm deletes the resource's entry from the state file only, leaving the real AWS infrastructure untouched. Subsequent plans no longer track it, which matches the stem's requirement to remove it from management without destroying it.

Why this answer

The `terraform state rm` command removes a resource from the Terraform state file without touching the actual infrastructure. This is the correct way to 'orphan' a resource so Terraform no longer manages it, while the real AWS resource continues to exist. It is commonly used when migrating resources to another state file or handing them off to manual management.

Exam trap

The trap here is confusing 'remove from management' with 'destroy the resource' — candidates often pick `terraform destroy -target` thinking it only detaches, but it actually deletes the real infrastructure.

How to eliminate wrong answers

Option A is wrong because `terraform destroy -target` actually destroys the targeted resource in AWS, which is the opposite of what is needed. Option B is wrong because `terraform untrack` is not a real Terraform command — it is a fabricated option. Option C is wrong because `terraform apply -ignore` is not a valid command; there is no `-ignore` flag for apply, and apply would not remove a resource from state anyway.

27
MCQmedium

You want to enforce a policy that prevents creating AWS EC2 instances larger than 't3.medium'. Where do you configure this?

A.By modifying the Terraform provider source.
B.Inside an HCP Terraform Policy Set.
C.In the Private Module Registry settings.
D.Within the workspace's variables.
AnswerB

HCP Terraform policy sets enforce Sentinel or OPA policies against Terraform runs, evaluating planned EC2 instance types before apply. This blocks instance sizes exceeding t3.medium at the Terraform layer, satisfying the stem's requirement to prevent creation of larger instances.

Why this answer

HCP Terraform (formerly Terraform Cloud) Policy Sets use Sentinel or OPA policies to enforce governance rules such as restricting EC2 instance types. You attach a policy set to workspaces or projects, and the policy evaluates the plan before apply, blocking non-compliant resources like instances larger than t3.medium. This is the correct place for cross-cutting, organization-wide enforcement.

Exam trap

The trap is confusing module registry governance with runtime policy enforcement — candidates pick the Private Module Registry because it sounds like a control point, but it only governs module distribution, not resource attributes.

How to eliminate wrong answers

Option A is wrong because modifying the provider source is not a supported governance mechanism — providers are versioned binaries, and forking them is impractical and unmaintainable. Option C is wrong because the Private Module Registry controls module distribution and versioning, not runtime policy enforcement on resource attributes. Option D is wrong because workspace variables only supply input values; they cannot inspect or block a plan based on resource attributes like instance type.

28
Multi-Selecthard

Which THREE of the following items can be included in a Variable Set?

Select 3 answers
A.Terraform variables.
B.Environment variables.
C.Terraform provider configurations.
D.Sentinel policy sets.
E.Scope definition (Projects or Organization).
AnswersA, B, E

Variable sets hold Terraform input variables, including sensitive and HCL values, which are then applied across every workspace the set is assigned to. This satisfies the scenario because Terraform variables are precisely the reusable input values a set distributes.

Why this answer

In Terraform Cloud/Enterprise, a Variable Set is a reusable container of variables that can be applied across multiple workspaces, and it can hold Terraform variables (option A), which are the input variables (e.g., terraform.tfvars-style key/value pairs) consumed by the Terraform configuration during a run. It can also hold environment variables (option B), which are injected into the run environment as shell environment variables (for example, credentials like AWS_ACCESS_KEY_ID or TF_LOG). Additionally, a Variable Set includes a scope definition (option E) that determines whether it applies to the entire Organization or is limited to specific Projects, controlling which workspaces inherit the variables.

Terraform provider configurations (option C) are not stored in Variable Sets; providers are configured in the Terraform configuration or via environment variables/credentials, not as a Variable Set item type. Sentinel policy sets (option D) are a separate governance feature managed independently of Variable Sets and are not an includable item within them.

Exam trap

The trap is thinking that provider configurations or Sentinel policies can be part of a Variable Set — candidates may confuse Variable Sets with other HCP Terraform features that manage providers or policies.

29
MCQeasy

You are using Terraform to manage an AWS EC2 instance. During a planned update, you expect the instance to be destroyed and recreated because of a change to the user_data attribute. However, you want to ensure that the old instance is destroyed only after the new instance is successfully created, to minimize downtime. Which lifecycle meta-argument should you add to the aws_instance resource?

A.ignore_changes = [user_data]
B.replace_triggered_by = [aws_instance.example]
C.prevent_destroy = true
D.create_before_destroy = true
AnswerD

This meta-argument ensures that the replacement resource is created before the existing one is destroyed. It is specifically designed to reduce downtime during updates that force replacement. By setting it to true, Terraform will create the new EC2 instance first, then destroy the old one, achieving the desired behavior.

Why this answer

The create_before_destroy meta-argument is the correct choice because it instructs Terraform to create the replacement resource before destroying the existing one, minimizing downtime. The other options either prevent destruction, ignore the change, or trigger replacement without controlling order.

Exam trap

The trap here is assuming that replace_triggered_by controls the order of operations, but it only triggers replacement, not the sequence.

30
MCQmedium

You need to automate the publication of a module to the Private Module Registry. What should you do?

A.Run the 'terraform publish' command.
B.Push a release tag to the linked VCS repository.
C.Manually upload the zip file to the registry.
D.Configure a webhook in the workspace settings.
AnswerB

The Private Module Registry publishes a new module version when a semver release tag is pushed to the linked VCS repository. Tagging the commit triggers automatic publication, satisfying the stem's requirement to automate module publication without manual upload.

Why this answer

HCP Terraform's Private Module Registry is VCS-driven: publishing a module happens automatically when you push a new release tag (e.g., v1.0.0) to the repository linked to the registry. The tag triggers the registry to ingest and version the module.

Exam trap

The trap is looking for a CLI command to publish — candidates expect a 'terraform publish' verb, but HCP Terraform publication is entirely VCS-tag-driven.

How to eliminate wrong answers

Option A is wrong because there is no 'terraform publish' command in the Terraform CLI — publishing is handled by the registry integration, not a CLI verb. Option C is wrong because manual zip uploads are not supported for the Private Module Registry; modules are sourced from VCS. Option D is wrong because webhooks in workspace settings relate to run notifications and triggers, not module publication.

31
MCQmedium

A module author wants to prevent callers from accidentally overriding a critical naming convention. The module already computes a `bucket_name` local. The author wants to expose it to callers without allowing them to set it. Which approach correctly enforces this behavior?

A.Declare the value as an input variable marked `sensitive = true` so callers cannot read or modify it.
B.Declare the value as an input variable with `nullable = false` and a validation block that rejects changes.
C.Declare the value as a local and expose it through an output block so callers can reference it read-only.
D.Declare the value as an input variable with a default, and document that callers should not change it.
AnswerC

A local value is computed entirely inside the module and cannot be set by callers. Exposing it through an output makes the value available to the root configuration as a read-only reference, such as `module.vpc.bucket_name`. This achieves the goal of sharing the naming convention while structurally preventing any override.

Why this answer

Input variables are inherently caller-controlled, so any value that must remain fixed belongs in a local and is shared outward through an output. Outputs are read-only references from the caller's perspective, meaning the module can publish `bucket_name` without offering a mechanism to override it. Validation and sensitivity flags affect acceptance and display, not write protection.

Exam trap

The trap here is treating variable validation or the sensitive flag as a mechanism for enforcing immutability, when only removing the input entirely prevents overrides.

32
MCQeasy

Your team uses HCP Terraform with a VCS-connected workspace. A developer pushes a commit to the tracked branch while a plan is already running. What does HCP Terraform do with the newly triggered run by default?

A.It discards the in-progress run and immediately starts the new run with the latest commit.
B.It merges the new commit into the running plan and re-plans automatically without user action.
C.It blocks the push from reaching the VCS provider until the running plan is approved.
D.It queues the new run, and the previous run continues until it finishes or is canceled.
AnswerD

A new commit creates a new run that enters the workspace queue while the current run finishes. This preserves an ordered history and prevents overlapping operations. Depending on workspace settings, an older queued run may later be discarded, but the in-flight run is not interrupted by default.

Why this answer

By default, a commit that triggers a run while another run is active creates a queued run rather than interrupting the active one. The workspace serializes runs to protect state, so the new commit waits its turn. Teams can enable run discarding to drop stale queued runs, but the in-progress run is left to finish.

Exam trap

The trap here is assuming a newer commit cancels the currently running plan by default.

33
MCQmedium

A platform team maintains a shared Terraform module that must run in three AWS regions simultaneously within a single root configuration. The module itself declares only a generic `aws` provider requirement with no alias, and the team wants each module instance to use a different region without editing the module source. Which configuration approach satisfies this requirement?

A.Add an `alias` argument inside the shared module's terraform block so the module can select its own region at runtime.
B.Create three separate root modules, one per region, and invoke the shared module from each with a different workspace.
C.Set the `region` argument directly on the module block so Terraform forwards it to the module's implicit aws provider.
D.Declare one aliased provider per region in the root module, then pass the matching provider configuration into each module block using the `providers` argument.
AnswerD

The `providers` argument maps a module's provider requirement to a specific provider configuration from the calling module, so three module blocks can each receive a differently aliased aws provider targeting a distinct region. This keeps the shared module region-agnostic and avoids duplicating its source.

Why this answer

Provider configurations are defined once, typically in the root module, and child modules receive them through the `providers` argument on the module block. Declaring aliased aws providers for each region and mapping each module instance to the appropriate one lets a single root configuration deploy the same module across multiple regions while the module source stays generic.

Exam trap

The trap here is assuming a module block can accept provider-specific arguments such as region, when only provider configuration blocks accept them.

34
MCQmedium

Your organization uses HCP Terraform with the AWS provider. A platform team wants to ensure that any workspace in the 'production' project can only use AWS credentials from a pre-approved OIDC role, and that no static AWS access keys are ever stored as workspace variables. Which HCP Terraform feature should you configure to enforce this requirement?

A.A team API token with read-only permissions on the production project.
B.Run triggers that automatically start a run whenever the AWS credentials in the workspace are modified.
C.Policy sets with a Sentinel policy that inspects the run's variables and blocks runs if any AWS access key variables are present.
D.Workspace variable sets with the 'sensitive' flag enabled for all AWS credential variables.
AnswerC

Sentinel policies can evaluate the plan and run metadata, including variables. A policy set attached to the production project can inspect for AWS access key variables and reject runs that include them, directly enforcing the no-static-keys requirement while allowing OIDC-based credentials.

Why this answer

Sentinel policy sets are the governance mechanism in HCP Terraform that can evaluate run context, including variables and plan data, and enforce rules such as disallowing static AWS access keys. Attaching the policy set to the production project ensures every run in that project is checked, providing the required guardrail without relying on manual review.

Exam trap

The trap here is assuming that marking variables as sensitive or using read-only tokens provides enforcement, when only a policy check can actively block non-compliant runs.

35
MCQmedium

Your organization uses HCP Terraform to manage AWS infrastructure. The security team requires that all runs consuming AWS credentials must be evaluated against a policy that checks the CIDR blocks of any aws_security_group resource. They want the policy to block the run if a CIDR is 0.0.0.0/0. Where should you implement this policy so it is enforced across all workspaces in the organization?

A.Define an AWS IAM policy that denies the CreateSecurityGroup action when the CIDR is 0.0.0.0/0.
B.Create a Sentinel policy in the organization's policy sets and assign it to all workspaces.
C.Use Terraform's built-in validation blocks in the aws_security_group resource to reject 0.0.0.0/0.
D.Configure a pre-plan run task that runs a script to check the Terraform configuration for 0.0.0.0/0.
AnswerB

Sentinel policies in HCP Terraform are configured at the organization level via policy sets, which can be applied to all workspaces. This enforces governance centrally, ensuring every run that plans AWS resources is evaluated. The policy can inspect the plan for aws_security_group CIDR blocks and block non-compliant configurations, meeting the requirement without per-workspace configuration.

Why this answer

Sentinel policies in HCP Terraform are managed at the organization level and can be applied to all workspaces through policy sets. They evaluate the Terraform plan and can block runs that violate rules, such as allowing 0.0.0.0/0 in security group CIDRs. This provides centralized, consistent enforcement across the organization.

Exam trap

The trap here is assuming that AWS IAM policies or Terraform validation blocks can inspect Terraform plan data to enforce governance, when only Sentinel policies have that capability.

36
MCQmedium

A DevOps engineer runs `terraform init` in a CI pipeline that has no internet access. The configuration uses the AWS provider from the public Terraform Registry. The pipeline fails because Terraform cannot download the provider. The team wants to use a local filesystem mirror containing the required provider packages. Which Terraform CLI configuration block should be used to point Terraform to the local mirror?

A.terraform { required_providers { aws = { source = "local/aws" } } }
B.provider_installation { network_mirror { url = "file:///opt/terraform/providers" } }
C.provider_installation { filesystem_mirror { path = "/opt/terraform/providers" } }
D.provider_installation { direct { exclude = ["hashicorp/aws"] } }
AnswerC

The provider_installation block with filesystem_mirror configures Terraform to install providers from a local directory. This is the correct way to use an offline mirror. The path points to a directory structured with provider packages, allowing terraform init to succeed without internet access.

Why this answer

To use a local filesystem mirror for provider installation, the CLI configuration must include a provider_installation block with filesystem_mirror and the path to the mirror directory. This allows Terraform to install providers without network access, which is essential for air-gapped CI pipelines.

Exam trap

The trap here is confusing network_mirror with filesystem_mirror, or attempting to change the provider source in required_providers instead of using CLI configuration.

37
MCQeasy

Which of the following is a valid lifecycle meta-argument in Terraform?

A.delete_on_success
B.wait_for_completion
C.create_before_destroy
D.create_after_update
AnswerC

`create_before_destroy` is a genuine Terraform lifecycle meta-argument, controlling replacement ordering so a new resource is provisioned before the old one is destroyed. It satisfies the stem's requirement for a valid lifecycle meta-argument, unlike `depends_on` (a meta-argument but not lifecycle-scoped) or `prevent_destroy` variants.

Why this answer

create_before_destroy is a valid lifecycle meta-argument in Terraform, used to ensure that a new resource is created before the old one is destroyed during replacement. This is one of the four supported lifecycle meta-arguments: create_before_destroy, prevent_destroy, ignore_changes, and replace_triggered_by. The other options are not valid Terraform lifecycle meta-arguments.

Exam trap

The trap is that candidates may confuse Terraform lifecycle meta-arguments with similar-sounding options from other tools or invent new ones; only the four documented meta-arguments are valid.

How to eliminate wrong answers

Option A is wrong because delete_on_success is not a Terraform lifecycle meta-argument; it is not recognized by Terraform and would cause a configuration error. Option B is wrong because wait_for_completion is not a Terraform lifecycle meta-argument; it is a concept used in other tools but not in Terraform's lifecycle block. Option D is wrong because create_after_update is not a valid Terraform lifecycle meta-argument; the correct meta-argument for creation order is create_before_destroy.

38
MCQeasy

Which argument in a module block allows you to provide a custom name to the module instance?

A.The label immediately following the 'module' keyword.
B.'name'
C.'instance_name'
D.'alias'
AnswerA

The identifier written directly after the module keyword is the local instance name, letting you reference outputs as module.<label>.<output>. It is not an argument inside the block; the block's source argument only supplies the module's location.

Why this answer

In Terraform, a module block is declared as `module "<LABEL>" { ... }`, where the label immediately following the `module` keyword is the local name (instance name) used to reference the module within the configuration. This label is how you distinguish multiple instances of the same module source and how you reference module outputs (e.g., `module.my_module.output_name`).

Exam trap

The trap is looking for a named argument like `name` or `instance_name` when Terraform actually uses the block label syntax `module "label" {}` to identify module instances.

How to eliminate wrong answers

Option B is wrong because `name` is not a valid argument in a module block — Terraform uses the block label, not an argument, to name the instance. Option C is wrong because `instance_name` is not a recognized Terraform argument; it does not exist in the module block schema. Option D is wrong because `alias` is used with provider blocks to create alternate provider configurations, not with module blocks to name instances.

39
MCQeasy

What is the purpose of the 'terraform providers lock' command?

A.To secure the provider versions and checksums.
B.To encrypt the state file.
C.To prevent others from running init.
D.To download all providers.
AnswerA

The command writes provider checksums into the dependency lock file for multiple platforms, securing the exact provider versions and their hashes. This satisfies the requirement to verify provider integrity across platforms, preventing tampering or unexpected version drift during init.

Why this answer

The 'terraform providers lock' command is used to update the dependency lock file (.terraform.lock.hcl) with the checksums of provider packages. It ensures that the provider versions and their checksums are recorded, which helps in verifying the integrity of providers during subsequent init operations. This is particularly useful in air-gapped environments or when you want to ensure consistent provider versions across teams.

Exam trap

AWS provider exam often tests the misconception that 'terraform providers lock' encrypts state or prevents init, rather than its actual role in securing provider versions and checksums.

How to eliminate wrong answers

Option B is wrong because encrypting the state file is not the purpose of this command; state encryption is handled differently (e.g., using backend encryption). Option C is wrong because the command does not prevent others from running init; it only locks provider versions and checksums. Option D is wrong because while it may download providers to compute checksums, its primary purpose is to lock versions and checksums, not just download.

40
Multi-Selectmedium

Which TWO of the following are true regarding variable validation in modules?

Select 2 answers
A.Validation blocks must return a boolean value.
B.Validation errors will only show during 'terraform apply'.
C.Validation blocks can read from other modules.
D.Variable names can be arbitrary but must be unique.
E.You can only validate string variables.
AnswersA, D

A validation block's condition argument must evaluate to true or false; Terraform reports the error_message when it returns false. This satisfies the stem's boolean requirement, since non-boolean expressions such as strings or numbers cannot be evaluated as pass/fail conditions.

Why this answer

Option A is correct because a Terraform variable validation block uses a condition expression that must evaluate to a boolean (true/false); if it evaluates to false, Terraform raises the error_message. Option D is correct because within a module, input variable names are arbitrary identifiers chosen by the author, but each variable name must be unique within that module's variable namespace. Option B is wrong because validation failures are surfaced during terraform plan (and validate), not only at apply time.

Option C is wrong because validation conditions can only reference the variable itself and cannot read values from other modules or resources. Option E is wrong because validation blocks work with any variable type, including number, bool, list, map, and object, not just strings.

Exam trap

The trap here is confusing when validation errors appear (validate/plan vs apply) and assuming validation can cross module boundaries or is limited to strings.

41
MCQeasy

A module outputs an AWS S3 bucket name. The root configuration needs to pass this output to another module as an input variable. How should the root configuration reference the output from the first module?

A.var.bucket.bucket_name
B.output.bucket.bucket_name
C.data.terraform_remote_state.bucket.bucket_name
D.module.bucket.bucket_name
AnswerD

In Terraform, outputs from a module are accessed using the syntax module.<MODULE_NAME>.<OUTPUT_NAME>. If the module is named bucket and it defines an output named bucket_name, the root configuration references it as module.bucket.bucket_name. This value can then be passed to another module's input variable. This is the standard way to chain modules.

Why this answer

Module outputs are referenced using the module.<MODULE_NAME>.<OUTPUT_NAME> syntax. This allows the root configuration to consume values from child modules and pass them to other modules or resources. The other options refer to different constructs: output blocks declare root outputs, var references input variables, and terraform_remote_state accesses external state files.

The correct syntax is module.bucket.bucket_name.

Exam trap

The trap here is confusing module output references with root output declarations or input variable references, which use different prefixes.

42
MCQhard

A module uses for_each over a map to create several IAM roles, and the map keys are derived from a variable that callers may change. The team wants to avoid replacing roles when only the map's values change. Which change to the module is required?

A.Replace for_each with count and index into the list
B.Add lifecycle { create_before_destroy = true } to the role resource
C.Mark the for_each map as sensitive in the variable definition
D.Ensure the for_each keys are stable and derived only from values that should not change
AnswerD

Terraform identifies for_each instances by their map keys. If keys remain constant while values change, Terraform updates attributes in place rather than replacing resources. Stable keys are therefore the correct fix to prevent unnecessary role replacement.

Why this answer

for_each instances are addressed by their map keys, so key stability is what determines whether Terraform updates or replaces resources. When only values change, in-place updates occur. count and lifecycle rules do not change instance identity, and sensitivity is unrelated to addressing, so ensuring stable keys is the correct approach.

Exam trap

The trap here is assuming create_before_destroy prevents replacement, when it only changes the order of replacement operations.

43
MCQmedium

You have defined a resource and set 'prevent_destroy = true'. If you perform a 'terraform destroy', what will happen?

A.Terraform will destroy all resources except the one with the rule.
B.Terraform will ignore the rule and destroy the resource anyway.
C.Terraform will return an error and abort the destroy operation.
D.Terraform will prompt for confirmation twice.
AnswerC

Terraform's lifecycle `prevent_destroy` meta-argument causes the plan phase to fail whenever a destroy action targets that resource, so `terraform destroy` errors out and aborts before removing anything. This satisfies the stem's protection requirement, halting the entire operation rather than skipping the resource silently.

Why this answer

When a resource has `prevent_destroy = true` in its lifecycle block, Terraform treats any plan that would destroy that resource as invalid. During `terraform destroy`, Terraform first generates a destroy plan; because that plan includes deleting the protected resource, Terraform immediately returns an error and aborts the entire operation before any resource is destroyed. This is a safety mechanism to prevent accidental deletion of critical infrastructure.

Exam trap

The trap here is assuming that Terraform will skip the protected resource and destroy everything else, or that it will prompt for extra confirmation—when in fact it aborts the entire operation with an error.

How to eliminate wrong answers

Option A is wrong because Terraform does not selectively skip the protected resource and destroy the rest; it aborts the entire destroy operation. Option B is wrong because Terraform does not ignore the `prevent_destroy` rule—it enforces it strictly and will not destroy the resource under any circumstances unless the rule is removed. Option D is wrong because Terraform does not add extra confirmation prompts; it simply errors out and stops, regardless of how many times you confirm.

44
Multi-Selecthard

Which TWO of the following are limitations of 'ignore_changes'?

Select 2 answers
A.It can be difficult to manage for deeply nested attributes.
B.It cannot ignore changes to the resource type itself.
C.It is only compatible with the AWS provider.
D.It requires all attributes to be ignored.
E.It only works with primitive types.
AnswersA, B

ignore_changes accepts attribute paths, and for deeply nested blocks or complex structures those paths become unwieldy and error-prone to maintain. This manageability constraint is the recognised limitation, not any effect on resource type or provider behaviour.

Why this answer

Option A is correct because 'ignore_changes' in Terraform must reference attribute paths, and for deeply nested attributes you have to spell out the full path (for example, using index or key syntax like tags["Name"] or nested block paths), which becomes verbose and error-prone as nesting grows. Option B is correct because 'ignore_changes' only suppresses diffs on specified attributes within a resource; it cannot ignore a change to the resource type itself, since changing the type means replacing the resource block and Terraform will plan to destroy and recreate it. Option C is incorrect because 'ignore_changes' is a core Terraform lifecycle meta-argument and works with all providers, not just AWS.

Option D is incorrect because you can list any subset of attributes to ignore, not all of them. Option E is incorrect because 'ignore_changes' works with complex types such as lists, maps, and nested blocks, not only primitive types.

Exam trap

The trap is assuming 'ignore_changes' is more powerful than it is, such as thinking it can ignore resource type changes or that it requires all attributes to be ignored. Candidates might also think it's provider-specific.

45
MCQeasy

Two engineers on your team both run `terraform apply` against the same HCP Terraform workspace that uses remote state, and their runs overlap in time. The second engineer's apply is rejected with a message that the workspace is locked. Which HCP Terraform behavior explains this outcome?

A.The second engineer lacks the Write permission, so HCP Terraform rejects the run with a lock-style error.
B.HCP Terraform serializes runs per workspace, so only one run can hold the state lock and modify state at a time.
C.The AWS provider imposes a DynamoDB-based lock on the S3 backend, which blocks the second run regardless of workspace settings.
D.Remote state is read-only during any apply, so the second engineer must first download state and apply locally.
AnswerB

HCP Terraform enforces per-workspace run concurrency: a run acquires the workspace lock while it plans and applies, and a second run waits or is canceled rather than proceeding concurrently. This prevents two applies from corrupting remote state. The rejection the second engineer sees is the expected result of that lock, not a misconfiguration.

Why this answer

HCP Terraform allows only one run at a time to hold a workspace's state lock, so concurrent applies are serialized. The second run is blocked until the first completes or is canceled, which matches the lock rejection. Read-only remote state, AWS-side DynamoDB locking, and permission errors do not produce this behavior in an HCP Terraform workspace.

Exam trap

The trap here is attributing the lock to an AWS S3/DynamoDB backend when state lives in HCP Terraform, which manages locking itself.

46
MCQmedium

You have a Terraform configuration that uses a module from the public registry. How do you ensure your team uses a specific version?

A.By manually deleting other versions
B.By configuring a Sentinel policy
C.Using a provider block
D.Using the 'version' argument
AnswerD

The version argument inside a module block pins the registry module to an exact or constrained release, such as 5.1.0. This satisfies the requirement that the team uses a specific version, preventing automatic upgrades to newer releases that could introduce breaking changes.

Why this answer

Terraform modules sourced from the public registry support a 'version' argument inside the module block, which constrains the module to a specific published version (or version constraint). This is the supported mechanism for pinning module versions so all team members and CI pipelines resolve the same code. It uses the same version constraint syntax as providers (e.g., '1.2.0', '~> 1.2').

Exam trap

The trap here is confusing provider version pinning (provider block) with module version pinning (version argument in the module block) — candidates often pick the provider block because it also has a 'version' argument.

How to eliminate wrong answers

Option A is wrong because manually deleting other versions from the registry is not possible for public registry modules and is not a version-control mechanism — it also doesn't affect what Terraform resolves. Option B is wrong because a Sentinel policy is a policy-as-code guardrail (HashiCorp Sentinel) that can enforce rules at plan/apply time, but it does not select or pin a module version; it can only reject non-compliant versions after the fact. Option C is wrong because a provider block configures the cloud provider plugin (AWS, Azure, etc.) and its version — it has nothing to do with module versioning.

47
Multi-Selecteasy

Which TWO of the following are benefits of using HCP Terraform for teams?

Select 2 answers
A.Centralized state management
B.Automated run triggers
C.Local execution only
D.No need for version control
E.Lower costs
AnswersA, B

HCP Terraform stores state remotely and centrally, so every team member reads and writes the same authoritative state rather than local copies. This satisfies the benefit of eliminating drift and conflicts arising from scattered local state files across a team.

Why this answer

Option A (Centralized state management) is correct because HCP Terraform stores Terraform state remotely in a shared, versioned workspace, enabling team members to collaborate on the same infrastructure without manually passing around terraform.tfstate files or configuring their own remote backends, and it provides state locking to prevent concurrent runs from corrupting state. Option B (Automated run triggers) is correct because HCP Terraform supports run triggers that automatically queue a dependent workspace's run when an upstream workspace completes successfully, as well as VCS-driven runs triggered by commits and API-driven runs, which streamlines multi-workspace and CI/CD workflows for teams. Option C (Local execution only) is incorrect because HCP Terraform's value comes from remote execution of runs in its managed environment, not from restricting execution to a single local machine.

Option D (No need for version control) is incorrect because HCP Terraform integrates with VCS providers like GitHub, GitLab, and Bitbucket and relies on version-controlled configurations to drive runs. Option E (Lower costs) is incorrect because HCP Terraform is a paid platform with tiered pricing based on resources and seats, so it is not inherently a cost-reduction benefit.

Exam trap

The trap is picking 'no need for version control' or 'lower costs' as benefits — candidates assume a managed platform replaces git or saves money, when HCP Terraform actually depends on VCS and is a paid service.

48
MCQeasy

A team wants to ensure their Terraform configuration uses a specific major version of the AWS provider to prevent breaking changes. Which block should they use?

A.terraform { required_providers { aws = { source = "hashicorp/aws", version = "~> 4.0" } } }
B.provider "aws" { version = "~> 4.0" }
C.terraform { version = "~> 4.0" }
D.provider_version = "4.0"
AnswerA

The `~>` pessimistic constraint operator permits patch and minor upgrades within major version 4, blocking the breaking changes that version 5 would introduce. Placing it inside `required_providers` within the `terraform` block satisfies the stem's requirement to pin a specific major version of the AWS provider.

Why this answer

The `terraform { required_providers { ... } }` block is the canonical location for declaring a provider's source and version constraint in modern Terraform (0.13+). The `version = "~> 4.0"` pessimistic constraint operator allows any 4.x release but blocks 5.0 and above, which is exactly what's needed to prevent breaking major-version upgrades. This block is also what `terraform init` reads when resolving and locking provider versions in `.terraform.lock.hcl`.

Exam trap

The trap here is confusing the `terraform` block's own `required_version` (Terraform CLI version) with `required_providers` (provider version), and assuming the legacy `provider { version = ... }` syntax still works.

How to eliminate wrong answers

Option B is wrong because the `version` argument inside a `provider` block was deprecated in Terraform 0.13 and removed in later versions — version constraints must live in `required_providers`. Option C is wrong because the `version` argument directly inside the `terraform` block sets the required Terraform CLI version, not the AWS provider version. Option D is wrong because `provider_version` is not a valid Terraform argument anywhere in the configuration language.

49
Multi-Selecthard

Your organization is standardizing on HCP Terraform and needs to decide which workspaces should use remote execution with a self-hosted agent pool rather than HCP Terraform's hosted runners. Which TWO conditions justify using a self-hosted agent pool? (Choose two.)

Select 2 answers
A.The organization requires that Terraform provider credentials never leave its own network perimeter.
B.The team wants faster plan times by caching the provider plugin binary across runs.
C.The workspace must reach private AWS resources inside a VPC that is not exposed to the public internet.
D.The workspace needs to run terraform plan without writing state after a pull request is opened.
E.The workspace configuration exceeds the maximum size allowed in the private module registry.
AnswersA, C

When credentials must remain inside a controlled network boundary, running Terraform on a self-hosted agent keeps provider authentication traffic within that perimeter. Hosted runners would require the credentials to be usable from HashiCorp-operated infrastructure, which violates the stated policy, making an agent pool the appropriate choice.

Why this answer

Self-hosted agent pools exist to solve reachability and data-residency problems that hosted runners cannot. Private VPC resources that are not internet-exposed require an agent inside the network, and a policy that keeps provider credentials within the organization's perimeter likewise demands execution on organization-controlled infrastructure. Other requirements such as speculative plans or module storage limits are satisfied by the hosted platform.

Exam trap

The trap here is assuming self-hosted agents improve performance or are needed for plan-only runs, when they exist for network reachability and credential perimeter control.

50
MCQhard

You are authoring a module that creates an AWS RDS instance. The module must enforce that the `engine` input is one of `mysql`, `postgres`, or `mariadb`. A consumer passes `engine = "aurora"`. What is the most appropriate way to handle this in the module to provide a clear error message and enforce the constraint?

A.Rely on the AWS provider's own validation of the `engine` argument, since the provider will reject invalid values when the API call is made.
B.Use a `validation` block inside the `variable "engine"` declaration with a `condition` that checks `contains(["mysql", "postgres", "mariadb"], var.engine)` and an `error_message` describing the allowed values.
C.Use a `locals` block to compute a boolean and then use the `count` meta-argument on the `aws_db_instance` resource to create zero instances when the engine is invalid.
D.Add a `precondition` block to the `aws_db_instance` resource that checks the engine value and fails if it is not in the allowed list.
AnswerB

Variable validation blocks are evaluated during plan and apply, and they produce a clear, custom error message when the condition is false. This enforces the constraint at the module boundary and gives consumers immediate feedback. It is the intended Terraform mechanism for validating input values and is evaluated before any resources are created, preventing invalid configurations from reaching AWS.

Why this answer

Variable validation blocks are the correct Terraform construct for enforcing constraints on input values. They run during plan and apply, produce a custom error message, and fail fast before any resources are provisioned. This gives module consumers immediate, actionable feedback and keeps invalid values from reaching the AWS provider or API.

Exam trap

The trap here is thinking that provider-level validation or resource preconditions are a substitute for input variable validation when the goal is a clear, early error message.

51
MCQmedium

You have an AWS EC2 instance managed by Terraform. The operations team occasionally updates the instance's tags directly in the AWS Console to reflect temporary maintenance status. You want Terraform to ignore these external tag changes and not revert them during the next apply. However, you still want Terraform to manage other attributes of the instance. Which lifecycle meta-argument should you use?

A.ignore_changes = [tags]
B.replace_triggered_by = [aws_ec2_tag.example]
C.ignore_changes = all
D.prevent_destroy = true
AnswerA

ignore_changes = [tags] tells Terraform to ignore any changes to the tags attribute of the EC2 instance. This means that if tags are modified outside of Terraform, the next plan will not show a diff for tags, and apply will not revert them. Other attributes remain managed, which aligns with the requirement to ignore only tags.

Why this answer

The ignore_changes meta-argument allows you to specify which attributes Terraform should ignore when detecting drift. By listing tags, Terraform will not plan updates for tag changes made outside of Terraform, while still managing other attributes. This precisely matches the scenario where tags are updated manually but other instance properties must remain under Terraform control.

Exam trap

The trap here is using ignore_changes = all, which would ignore all attributes and thus stop managing the instance entirely, rather than just tags.

52
MCQmedium

In a dynamic block, you need to access the current iteration item. What is the default label assigned to the iterator object?

A.count.index
B.The name of the block
C.each.value
D.item
AnswerB

When no explicit iterator is declared, Terraform names the iterator object after the dynamic block's label itself, so a block labelled 'ingress' exposes each element as 'ingress.value'. This satisfies the default-label constraint without requiring an iterator argument.

Why this answer

In a dynamic block, the iterator object defaults to the name of the block being generated. For `dynamic "ingress" { ... }`, the iterator is `ingress`, so you reference `ingress.value` and `ingress.key`. You can override this with the `iterator` argument, but the default is the block label.

This is why `each.value` and `count.index` are not used inside dynamic blocks.

Exam trap

The trap is reaching for `each.value` or `count.index` out of habit — those belong to `for_each`/`count` on resources, while dynamic blocks use the block label as the default iterator.

How to eliminate wrong answers

Option A is wrong because `count.index` belongs to the `count` meta-argument on resources/modules, not to dynamic blocks. Option C is wrong because `each.value` is used with `for_each` on resources/modules, not inside dynamic blocks — dynamic blocks use the block-name iterator. Option D is wrong because `item` is not a default label; it would only apply if you explicitly set `iterator = item`, which is not the default.

53
MCQhard

You are writing a Terraform configuration that reads a list of environment names from a variable and creates one aws_s3_bucket for each environment. The order of the list may change over time, and you want to avoid unnecessary bucket replacement. Which configuration snippet achieves this with stable resource addressing?

A.resource "aws_s3_bucket" "env" { for_each = toset(var.environments) bucket = each.value }
B.resource "aws_s3_bucket" "env" { count = length(var.environments) bucket = element(var.environments, count.index) }
C.resource "aws_s3_bucket" "env" { for_each = var.environments bucket = each.value }
D.resource "aws_s3_bucket" "env" { count = length(var.environments) bucket = var.environments[count.index] }
AnswerA

Converting the list to a set with toset and using for_each creates one bucket per unique environment, keyed by the environment name itself. Because the keys are the values, reordering the original list does not change the resource addresses, so buckets are not replaced. This provides the stable addressing required.

Why this answer

To achieve stable resource addressing when order may change, the resource instances must be keyed by a value that does not depend on list position. Using for_each with toset(var.environments) creates instances keyed by the environment names themselves, so reordering the input list does not alter the resource addresses. The count-based approaches all depend on index positions and therefore do not provide stability.

Exam trap

The trap here is believing that count with element or index provides stable addressing, when any index-based approach remains sensitive to list order.

54
MCQmedium

You are refactoring a Terraform configuration by moving an `aws_s3_bucket` resource into a child module. The bucket already exists and is tracked in state at the root. You want to avoid destroying and recreating the bucket. Which command should you use to update the state address without touching the real infrastructure?

A.terraform import aws_s3_bucket.logs module.storage.aws_s3_bucket.logs
B.terraform state mv aws_s3_bucket.logs module.storage.aws_s3_bucket.logs
C.terraform refresh
D.terraform state rm aws_s3_bucket.logs
AnswerB

terraform state mv renames the address of a resource within state, preserving the association with the real object. Moving the bucket from the root address to the module address means Terraform will plan no changes after the move, because the object is already tracked under the new address. This avoids any destroy or recreate.

Why this answer

terraform state mv is the correct tool for relocating a resource within state, whether moving between modules, renaming, or restructuring. It preserves the mapping to the real object so no infrastructure is destroyed or recreated. The import command is for adopting objects not yet in state, state rm deletes the tracking entry, and refresh only updates attributes.

Exam trap

The trap here is reaching for terraform import to adopt a resource that is already in state, when the actual need is to move an existing state entry with terraform state mv.

55
MCQmedium

You are building a module that needs to be consumed by multiple teams. How should you structure your module to ensure that the root module can provide values for variable definitions without hardcoding them in the module itself?

A.Hardcode the values into the resource blocks directly.
B.Use terraform.tfvars files inside the module folder.
C.Define all values in a locals.tf file within the module.
D.Define variables in a variables.tf file within the module directory.
AnswerD

Declaring inputs in variables.tf exposes them as named parameters, letting each consuming root module supply values through its own module block or tfvars. This satisfies the requirement that callers provide values without hardcoding them inside the module.

Why this answer

Using input variables allows the module to be generic and reusable by accepting values defined in the calling configuration.

56
Multi-Selectmedium

Which TWO types of variables can be set in HCP Terraform?

Select 2 answers
A.Environment variables
B.Policy-level variables
C.State-level variables
D.Hardcoded module variables
E.Terraform variables
AnswersA, E

Environment variables are injected into the run's shell environment as key-value pairs, so they reach providers and tooling that read credentials or settings from the operating system rather than from Terraform's input variable mechanism. HCP Terraform supports them at workspace and variable-set scope.

Why this answer

In HCP Terraform (formerly Terraform Cloud), workspaces support two distinct categories of user-settable variables: environment variables (option A) and Terraform variables (option E). Environment variables (A) are injected into the Terraform run environment and are commonly used for provider credentials such as AWS_ACCESS_KEY_ID or TF_LOG, and they can optionally be marked sensitive. Terraform variables (E) correspond to input variables declared in the configuration (variable blocks) and are supplied as key/value pairs (e.g., via terraform.tfvars or the HCP Terraform UI/API) to parameterize a run, including HCL and sensitive variants.

The other options are not valid HCP Terraform variable types: policy-level variables (B) do not exist as a settable category (Sentinel policies are managed separately), state-level variables (C) are not a Terraform concept since state stores resource data, and hardcoded module variables (D) are simply literal values written in code rather than a configurable variable type.

Exam trap

The trap here is confusing HCP Terraform's variable types with generic Terraform concepts like state or policies, leading candidates to select plausible-sounding but non-existent options.

57
MCQeasy

You want to optionally create an S3 bucket only if a specific variable 'create_bucket' is set to true. Which HCL feature is best for this?

A.conditional expression (ternary)
B.try()
C.dynamic block
D.for_each
AnswerA

Setting count = var.enabled ? 1 : 0 is the common pattern for optional resource creation.

Why this answer

The conditional expression (ternary) in HCL uses the syntax `condition ? true_val : false_val` and can be applied to a resource's `count` argument, e.g., `count = var.create_bucket ? 1 : 0`. This is the idiomatic way to conditionally create a resource based on a boolean variable. When `create_bucket` is true, one instance is created; when false, zero instances are created.

Exam trap

AWS provider exams often test the distinction between conditional expressions and other HCL features like `dynamic` blocks or `for_each`, tricking candidates into choosing `for_each` for conditional creation when it cannot produce zero instances.

How to eliminate wrong answers

Option B is wrong because `try()` is used to gracefully handle errors when accessing attributes that may not exist, not to conditionally create resources. Option C is wrong because a `dynamic` block generates repeated nested blocks within a resource based on a collection, not conditional resource creation. Option D is wrong because `for_each` iterates over a map or set to create multiple resource instances, but it cannot conditionally create zero instances based on a boolean.

58
MCQeasy

An operations engineer runs 'terraform init' in a directory where the configuration requires the AWS provider from the public registry. The machine has no direct internet access but can reach an internal Terraform registry mirror. Which action must be taken so that init succeeds using the mirror?

A.Configure a provider_installation block in the CLI configuration file (~/.terraformrc or terraform.rc) with a network_mirror or filesystem_mirror directive
B.Add a source argument pointing to the mirror URL inside the terraform block of the root configuration
C.Run 'terraform providers lock' with the -platform flag to pre-populate the lock file from the mirror
D.Set the TF_REGISTRY_CLIENT_TIMEOUT environment variable to a longer value and re-run init
AnswerA

Terraform's CLI configuration file supports a provider_installation block where you can declare network_mirror or filesystem_mirror sources. When direct registry access is blocked but an internal mirror is reachable, this block redirects provider downloads to the mirror, allowing init to install the AWS provider without public internet access.

Why this answer

Terraform reads provider installation settings from the CLI configuration file, not from the working directory configuration. A provider_installation block with network_mirror or filesystem_mirror directs Terraform to fetch providers from an internal source, which is the correct solution when the public registry is unreachable but a mirror is available.

Exam trap

The trap here is conflating the provider source argument in required_providers with mirror configuration, when mirror redirection is controlled only by the CLI configuration file.

59
Multi-Selectmedium

Which TWO of the following are valid uses of the 'for' expression?

Select 2 answers
A.Defining a resource
B.Generating a list
C.Managing provider blocks
D.Creating dynamic blocks
E.Generating a map
AnswersB, E

A for expression iterating over a collection and wrapping the result in square brackets produces a new list, optionally filtered by an if clause. This matches the stem's requirement, whereas the curly-brace form yields a map instead.

Why this answer

In Terraform, the 'for' expression is used to transform and produce collection values: option B is correct because a 'for' expression over a list or set returns a tuple/list, e.g. [for s in var.subnets : upper(s)], which generates a list. Option E is correct because using the curly-brace form, e.g. {for k, v in var.tags : k => upper(v)}, produces a map (object) of key-value pairs. Option A is not a use of 'for' because resources are declared with a 'resource' block, not an expression.

Option C is wrong because provider configuration is handled by 'provider' blocks and required_providers, not 'for'. Option D is wrong because dynamic blocks are created with the 'dynamic' block and its 'for_each' argument, not with a 'for' expression.

Exam trap

The trap here is confusing value-producing expressions (for) with configuration blocks (resource, provider, dynamic) — remember that for expressions only generate lists or maps, never infrastructure.

60
MCQeasy

A team wants to reuse an existing, manually managed AWS provider configuration located in a separate directory as the source of truth for a new Terraform configuration, instead of declaring a fresh provider block. Which statement describes how Terraform obtains provider configurations from elsewhere?

A.Use `terraform import` with the provider address to copy the provider configuration into the new working directory.
B.Reference the other directory through a module block and inherit its provider configuration implicitly.
C.Declare a `provider` data source that reads the settings from the other directory at plan time.
D.Provider configurations cannot be imported or shared across directories; each root module must declare its own provider configuration for the AWS provider.
AnswerD

Provider configurations are not resources and cannot be imported, referenced across directories, or shared between root modules. Each root module declares the providers it needs, so the new configuration must define its own aws provider block, even if it mirrors the settings of the existing one.

Why this answer

Provider configurations live in configuration, not state, and are scoped to the root module that declares them. They cannot be imported, copied between directories, or read through a data source. The new configuration must declare its own AWS provider block, optionally using variables or environment variables to mirror the settings of the existing setup.

Exam trap

The trap here is conflating provider configurations with resources, leading to attempts to import or reference them across directories.

61
MCQeasy

Where can you define variables that apply to all workspaces within an organization in HCP Terraform?

A.In the Private Module Registry.
B.In a Variable Set.
C.In the individual workspace configuration.
D.In the organization settings directly.
AnswerB

Variable Sets apply values across every workspace in an organisation, satisfying the requirement for organisation-wide variables. They are scoped at the organisation level rather than per-workspace, unlike workspace variables or Terraform input variables defined in configuration.

Why this answer

In HCP Terraform (formerly Terraform Cloud), a Variable Set is a named collection of variables that can be applied to multiple workspaces across an organization. Variable Sets are designed specifically to share variables globally or across selected workspaces, making them the correct mechanism for organization-wide variable definitions. They can contain both Terraform variables and environment variables, and can be scoped to all workspaces or a subset.

Exam trap

The trap is assuming that organization settings provide a direct variable configuration interface — candidates often overlook Variable Sets as the dedicated mechanism for cross-workspace variables and instead pick the more obvious-sounding 'organization settings' option.

How to eliminate wrong answers

Option A is wrong because the Private Module Registry stores reusable Terraform modules, not variables — it has no mechanism for injecting variables into workspaces. Option C is wrong because individual workspace configuration only applies variables to that single workspace, not to all workspaces in the organization. Option D is wrong because organization settings in HCP Terraform do not include a direct variable definition area; variables must be defined in workspaces or variable sets, not at the org level itself.

62
MCQmedium

A platform team maintains a module that provisions a VPC and subnets. They want to expose the subnet IDs to callers without allowing callers to modify them. Which Terraform construct should they use in the module?

A.A resource block with provisioner 'local-exec' that writes the IDs to a file
B.An output block in the module that references the subnet IDs
C.A locals block in the module that stores the subnet IDs
D.A variable block in the module with type = list(string)
AnswerB

Output blocks expose module results to the caller as read-only values. The caller references them via module.<name>.<output>, and cannot assign to them. This cleanly publishes the computed subnet IDs while keeping them immutable from the caller's perspective.

Why this answer

Output blocks are the supported mechanism for a module to return values to its caller. Because outputs are read-only from the caller's perspective, they naturally expose computed attributes such as subnet IDs without giving callers a way to overwrite them. Variables, locals, and provisioners do not provide that read-only outward-facing contract.

Exam trap

The trap here is confusing module inputs (variables) with module outputs, when only outputs return computed values to the caller.

63
MCQeasy

You are writing a Terraform configuration that uses a conditional expression to set the instance type for an AWS EC2 instance. The condition checks if the environment is production. The true branch returns a string, but the false branch returns a number. What will happen when you run terraform plan?

A.Terraform will raise an error because the true and false expressions must have the same type.
B.Terraform will convert both to a common type, such as string, and then proceed.
C.Terraform will automatically convert the number to a string and proceed without error.
D.Terraform will use the type of the true expression and ignore the false expression's type.
AnswerA

Conditional expressions in Terraform require both the true and false results to be of the same type. If they are not, Terraform will produce an error during plan, indicating that the types do not match. This ensures that the resulting value has a consistent type regardless of the condition.

Why this answer

Terraform's conditional expression requires that the true and false results have the same type. If they differ, Terraform cannot determine a consistent type for the expression and will raise an error during plan. This is a common pitfall when mixing types in conditionals.

Exam trap

The trap here is assuming Terraform will automatically convert types, when it actually requires both branches to be the same type.

64
MCQmedium

Your organization uses HCP Terraform with remote runs. A workspace named 'prod-network' has its execution mode set to Remote. A platform engineer runs `terraform apply` locally after running `terraform plan` on their laptop, but the apply fails with an error because the workspace's state is locked by an active remote run. What is the most likely explanation for this error?

A.The workspace's state is stored locally because the backend configuration is missing, causing a lock conflict with the remote run.
B.The local CLI is not authenticated to HCP Terraform, so it cannot acquire the state lock.
C.A remote run is currently in progress in the workspace, holding the state lock, so a local apply cannot proceed until it finishes or is canceled.
D.The workspace's execution mode is set to Local, so HCP Terraform cannot accept remote applies.
AnswerC

When execution mode is Remote, HCP Terraform runs plan and apply remotely. If a remote run is active, it holds the state lock. A local apply attempted against the same workspace will fail because the state is locked. The engineer must wait for the remote run to complete or cancel it before applying locally, though best practice is to avoid local applies in remote-mode workspaces.

Why this answer

With remote execution mode, all runs occur in HCP Terraform and the workspace state is locked during an active run. A local apply cannot acquire the lock while a remote run is in progress. The engineer must coordinate with the remote run, typically by waiting or canceling, rather than attempting a local apply.

Exam trap

The trap here is assuming that local CLI operations can bypass remote run locks, when in fact the remote workspace state lock applies to all operations against that workspace.

65
MCQeasy

Which directory structure is considered standard for a Terraform module?

A.A directory containing main.tf, variables.tf, and outputs.tf.
B.One single file named 'all.tf'.
C.A binary executable file that compiles the infrastructure.
D.A separate folder for every single resource.
AnswerA

Splitting inputs, outputs, and resource declarations into variables.tf, outputs.tf, and main.tf is the documented convention, giving consumers a predictable interface. This satisfies the standard structure expected when a directory is consumed as a reusable module.

Why this answer

The standard Terraform module structure is a directory containing 'main.tf' (primary resource definitions), 'variables.tf' (input variable declarations), and 'outputs.tf' (output value declarations). This convention is documented by HashiCorp and used by the Terraform Registry, making modules predictable and easy to consume. Additional files like 'versions.tf' and 'README.md' are common but the three core files define the canonical layout.

Exam trap

The trap is overthinking the structure — candidates may pick 'separate folder per resource' thinking it is more organized, but Terraform's convention is file-based separation by concern, not folder-per-resource.

How to eliminate wrong answers

Option B is wrong because a single 'all.tf' file is an anti-pattern — it hurts readability, makes code review harder, and does not follow the registry's conventions. Option C is wrong because Terraform modules are collections of HCL configuration files, not compiled binaries; Terraform interprets HCL at plan/apply time and there is no compilation step. Option D is wrong because creating a separate folder for every resource is unnecessarily granular and breaks the module's cohesion — resources are typically grouped by logical function within the standard files.

66
MCQhard

An operations engineer runs `terraform init` in a directory whose configuration uses the AWS provider. After init, the engineer inspects `.terraform.lock.hcl` and sees multiple `zh:` hash entries alongside `h1:` entries for the hashicorp/aws provider. A colleague on a different platform then runs `terraform init` and Terraform reports that the provider package does not match any of the checksums recorded in the lock file. Which action most directly resolves the mismatch while preserving reproducibility?

A.Set the environment variable TF_SKIP_PROVIDER_VERIFY=true for the colleague's init run.
B.Add `-upgrade` to the colleague's terraform init command to force Terraform to re-resolve provider versions.
C.Delete .terraform.lock.hcl and rerun terraform init so Terraform regenerates hashes for the current platform.
D.Run `terraform providers lock -platform=<colleague's platform>` and commit the updated lock file.
AnswerD

The zh: entries are platform-specific package hashes, and the colleague's platform is missing from the lock file, so Terraform cannot verify the downloaded package. terraform providers lock with the additional -platform flag records hashes for that platform, and committing the file lets both engineers verify the same provider version reproducibly. This preserves pinning while extending platform coverage.

Why this answer

The lock file stores per-platform package hashes in zh: entries plus a package-level h1: hash. When a platform is absent, verification fails. Running terraform providers lock with the -platform flag for the missing platform adds those hashes, and committing the result keeps the pinned version while allowing every supported platform to verify the same package.

Exam trap

The trap here is reaching for a flag or environment variable that disables verification instead of extending the lock file with the missing platform's hashes.

67
Multi-Selectmedium

Which THREE of the following are valid ways to transform data for Terraform configuration?

Select 3 answers
A.flatten()
B.merge()
C.split_map()
D.loop()
E.for expressions
AnswersA, B, E

`flatten()` collapses nested lists into a single flat list, which satisfies the stem's requirement for a valid data transformation function. Terraform's built-in collection functions, including `flatten()`, restructure values during evaluation, so nested structures from variables or outputs become directly usable in resource arguments.

Why this answer

Option A, flatten(), is correct because it is a built-in Terraform function that takes a list of lists and transforms it into a single flat list, which is a valid data transformation for configuration. Option B, merge(), is correct because it is a built-in Terraform function that combines multiple maps or objects into one map, a common way to transform and consolidate data in Terraform. Option E, for expressions, is correct because Terraform's for expressions iterate over lists, sets, maps, or objects to produce a new transformed list or map, making them a core transformation mechanism.

Option C, split_map(), is not a valid Terraform function, so it cannot transform data. Option D, loop(), is not a Terraform construct; iteration is handled by for expressions, count, or for_each, not a loop() function.

Exam trap

The trap here is confusing Terraform's built-in functions with non-existent ones like split_map() or loop(), which sound plausible but are not part of the Terraform language.

68
Multi-Selectmedium

What are the ways to configure provider credentials? (Select THREE)

Select 3 answers
A.Shared credentials file (~/.aws/credentials).
B.Directly in the provider block.
C.Environment variables (e.g., AWS_ACCESS_KEY_ID).
D.In the .terraform.lock.hcl file.
E.Via the terraform output command.
AnswersA, B, C

Storing long-lived access keys in ~/.aws/credentials lets the AWS CLI and SDKs resolve credentials automatically via the default profile chain, satisfying the requirement for a file-based configuration method without embedding secrets in code or environment variables.

Why this answer

Option A is correct because the AWS provider (and Terraform's provider credential chain) reads static access keys from the shared credentials file at ~/.aws/credentials, typically under a named profile such as [default]. Option B is correct because credentials can be supplied inline within the provider block using arguments like access_key and secret_key, which is valid though less secure than external sources. Option C is correct because the provider credential chain also resolves credentials from environment variables such as AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, and AWS_SESSION_TOKEN.

Option D is not correct because .terraform.lock.hcl only records provider version selections and cryptographic hashes for dependency locking, not credentials. Option E is not correct because terraform output only displays values from state (such as outputs) and has no role in configuring provider authentication.

69
MCQmedium

You are refactoring a module that previously used `count` to create multiple AWS IAM users. The module now uses `for_each` with a map of usernames to user details. After the refactor, you run `terraform plan` and see that Terraform wants to destroy and recreate all existing IAM users. What is the most likely cause, and how can you avoid this disruption?

A.The resource address changed from `aws_iam_user.users[0]` to `aws_iam_user.users["alice"]`; use `terraform state mv` to move each user to the new address.
B.The IAM user resource does not support `for_each`; you must revert to `count` to avoid recreation.
C.The `for_each` map keys must be numeric to match the previous count indices; change the map keys to numbers.
D.You need to add `lifecycle { create_before_destroy = true }` to the resource to prevent downtime during recreation.
AnswerA

Switching from count to for_each changes the resource instance keys from numeric indices to string keys. Terraform sees these as different resources and plans to destroy the old and create new ones. Using `terraform state mv` to remap each existing user to the new address preserves the resources and avoids recreation. This is the standard refactoring procedure.

Why this answer

Changing from count to for_each alters the resource instance keys, causing Terraform to treat existing instances as removed and new ones as added. To avoid this, you must move the existing state entries to the new addresses using `terraform state mv`. This preserves the actual cloud resources and prevents unnecessary destruction.

Exam trap

The trap here is assuming that for_each and count are interchangeable without state migration, when in fact their instance key formats are incompatible.

70
MCQmedium

When refactoring a large infrastructure configuration, you move a resource into a child module. How do you handle the existing state to prevent Terraform from destroying and recreating the resource?

A.Run 'terraform refresh' to automatically detect the move.
B.Use the 'terraform state mv' command to move the resource address.
C.Rename the resource in the configuration to match the old state.
D.Delete the state file and run 'terraform apply'.
AnswerB

Using `terraform state mv` rewrites the resource's address in the state file from its root-level path to the new child-module path, so Terraform maps the existing remote object to the relocated configuration block. This satisfies the stem's constraint of preventing destroy-and-recreate, since no infrastructure changes are applied.

Why this answer

When a resource is moved into a child module, its address in state changes from something like 'aws_instance.web' to 'module.child.aws_instance.web'. Terraform sees these as different resources and would plan a destroy/create. The 'terraform state mv' command updates the state address in place, preserving the existing resource without any API calls.

Exam trap

The trap here is assuming Terraform can infer resource moves from configuration changes; in reality, address changes require explicit state manipulation via 'state mv' or 'moved' blocks.

How to eliminate wrong answers

Option A is wrong because 'terraform refresh' only reconciles state with real infrastructure; it does not change resource addresses and will not detect a module refactor. Option C is wrong because renaming the resource in configuration does not change the state address; Terraform still sees a mismatch and plans replacement. Option D is wrong because deleting the state file causes Terraform to lose track of all existing resources, leading to duplicate creation and orphaned infrastructure.

71
MCQeasy

What is the primary benefit of using a module registry compared to a local file path for module distribution?

A.It allows you to run Terraform commands faster.
B.It removes the need for input variables.
C.It automatically converts your code to a higher-level language.
D.It enables version control and easier sharing across the organization.
AnswerD

A registry provides published, versioned modules that teams can pin and reuse, unlike a local file path which offers no versioning or central distribution. This satisfies the cross-organisation sharing and version-control requirement in the stem.

Why this answer

A module registry (such as the public Terraform Registry or a private registry like Terraform Cloud's) provides a centralized, versioned catalog of modules. When you reference a module via a registry source, you can pin an exact version (e.g., `version = "1.2.0"`), which enables reproducible deployments and safe upgrades. It also makes modules discoverable and shareable across teams and organizations without manually copying files or managing relative paths.

Local file paths offer none of these versioning or sharing capabilities.

Exam trap

The trap here is confusing module distribution with module functionality—candidates might think a registry speeds up execution or removes the need for variables, but the core benefit is versioning and sharing.

How to eliminate wrong answers

Option A is wrong because using a registry does not inherently speed up Terraform commands; in fact, it may introduce network latency when downloading modules, and execution speed depends on provider APIs and resource graph complexity. Option B is wrong because input variables are still required to parameterize modules regardless of source; the registry does not eliminate the need for variables—it only changes how the module code is fetched. Option C is wrong because Terraform modules are written in HCL (or JSON) and are not automatically converted to a higher-level language by a registry; the registry simply stores and distributes the same configuration code.

72
MCQmedium

You have a Terraform variable defined as a list of objects, each with a name and a list of ports. You need to create AWS security group rules for each port across all objects. Which expression correctly generates a flattened list of objects containing the name and port for each combination?

A.flatten([for obj in var.services : [for p in obj.ports : { name = obj.name, port = p }]])
B.concat([for obj in var.services : { name = obj.name, port = obj.ports }])
C.merge([for obj in var.services : { (obj.name) = obj.ports }])
D.[for obj in var.services : { name = obj.name, port = obj.ports }]
AnswerA

This uses a nested for expression to create a list of lists, then flatten combines them into a single list. Each inner list contains one object per port for that service, and the outer flatten merges all services into a single list. This correctly produces one object per name-port combination.

Why this answer

The nested for expression creates an inner list for each service, where each element is an object with the service name and a single port. The flatten function then merges all these inner lists into one flat list. This is the standard pattern for transforming a list of objects with nested lists into a flat list for use with for_each or other iteration.

Exam trap

The trap here is using concat or merge instead of flatten, which do not recursively flatten nested lists of objects.

73
Multi-Selecthard

Which TWO of the following accurately describe the behavior of 'terraform state rm'?

Select 2 answers
A.It stops Terraform from tracking the resource.
B.It leaves the real-world resource running.
C.It requires the 'force' flag for all resources.
D.It is a permanent action that cannot be undone.
E.It destroys the infrastructure in the cloud.
AnswersA, B

Removing a resource from state halts tracking without destroying the real infrastructure, satisfying the requirement that the resource be forgotten rather than deleted. Terraform no longer manages or plans changes for it, though the underlying cloud object persists untouched until re-imported or removed manually.

Why this answer

Option A is correct because 'terraform state rm' removes the specified resource from the Terraform state file, so Terraform no longer tracks or manages that resource in future plans and applies. Option B is correct because the command only edits state metadata; it does not call the provider's delete API, so the actual real-world resource (e.g., an EC2 instance or S3 bucket) continues running untouched. Option C is wrong because no 'force' flag is required for all resources; the command simply removes the address from state.

Option D is wrong because the action is not strictly irreversible — you can re-import the resource with 'terraform import' or restore a state backup. Option E is wrong because 'terraform state rm' never destroys cloud infrastructure; only 'terraform destroy' or 'terraform apply' with removal does that.

Exam trap

The trap is conflating state operations with infrastructure operations — candidates assume removing a resource from state also deletes it in the cloud, when in fact state rm only stops Terraform from tracking it.

74
MCQmedium

You are updating a shared Terraform module that provisions an Amazon RDS instance. The module currently defines an input variable `engine_version` with `default = "14.7"`. Your team wants to ensure that any consumer who does not explicitly set `engine_version` still gets a valid value, but you also want to prevent consumers from accidentally passing a null value that would cause an API error. Which change should you make to the variable definition?

A.Add a validation block that checks `var.engine_version != null` and returns an error message if the value is null.
B.Add `nullable = false` to the variable block so Terraform rejects null values and uses the default instead.
C.Use a `sensitive = true` attribute on the variable to mask null values and fall back to the default.
D.Remove the default and mark the variable as required so callers must always provide a value.
AnswerB

Setting `nullable = false` ensures that if a caller passes `null` for `engine_version`, Terraform uses the default value rather than overriding it with null. This prevents the AWS provider from receiving a null argument, which would cause a validation error. The default remains available for callers who omit the variable entirely, satisfying both requirements.

Why this answer

The `nullable` argument, introduced in Terraform 1.1, controls whether a variable can be set to null. When `nullable = false`, a null value passed by a caller is treated as if the variable were omitted, so the default is used. This is the precise mechanism for ensuring a fallback to the default while still allowing callers to omit the variable.

Exam trap

The trap here is assuming that a validation block can replace a null value with the default, when validation only rejects values and cannot perform fallback substitution.

75
MCQhard

You are writing a Terraform configuration that creates multiple AWS S3 buckets. The bucket names are derived from a list of project names, but you need to ensure that the names are unique and that the configuration can be safely modified without affecting existing buckets. Which approach should you use?

A.Use for_each with a map where the keys are the project names and the values are the desired bucket configurations.
B.Use a for expression to create a list of bucket names and then pass that list to the bucket resource's name argument.
C.Use count with the length of the project list and reference each bucket by index.
D.Use a dynamic block to generate multiple bucket resources within a single resource block.
AnswerA

Using for_each with a map creates one resource instance per map key, and the key becomes part of the resource address. This provides stable identity: adding or removing a key only affects that instance, and existing buckets remain untouched. It is the recommended way to manage multiple similar resources with unique names.

Why this answer

Using for_each with a map ensures that each resource instance is uniquely identified by its map key, so changes to the map only affect the corresponding instances. This provides stable resource addresses and avoids the pitfalls of count, where reordering or removing elements can cause unintended destruction and recreation of resources.

Exam trap

The trap here is thinking that count or dynamic blocks can provide stable identity, when only for_each with a map does so.

Page 1 of 4

Page 2

All pages