Terraform Associate · 12% of the exam

Terraform configuration: free practice questions

5 sample questions from our 40-question bank for this domain — answers and explanations included. These are the same scenario-based style as the real HashiCorp exam.

1. A developer writes the following Terraform configuration: ```hcl variable "enable_monitoring" { type = bool default = false } resource "aws_instance" "web" { ami = "ami-0abcdef1234567890" instance_type = var.enable_monitoring ? "t3.large" : "t3.micro" } ``` The developer runs `terraform apply` without passing any variable values. What instance type will be used?

  • A. t3.large, because bool variables default to true
  • B. t3.micro, because the default value of enable_monitoring is false✓ Correct
  • C. An error occurs because conditional expressions require explicit variable values
  • D. t3.large, because the ternary operator always evaluates the first branch first
Explanation

**t3.micro** is correct. The variable `enable_monitoring` defaults to `false`, so the conditional expression `false ? "t3.large" : "t3.micro"` evaluates to `"t3.micro"`. **t3.large** (first option) is wrong because `bool` variables do not default to `true` unless explicitly set. **An error occurs** is wrong — Terraform's ternary/conditional expression works perfectly with default variable values; no explicit value is required. **t3.large** (last option) is wrong — the ternary operator evaluates the condition, not just the first branch unconditionally.

2. A developer has this configuration to retrieve a list of availability zones and use the second one: ```hcl data "aws_availability_zones" "available" { state = "available" } resource "aws_subnet" "secondary" { vpc_id = aws_vpc.main.id cidr_block = "10.0.2.0/24" availability_zone = element(data.aws_availability_zones.available.names, 1) } ``` The `data.aws_availability_zones.available.names` returns `["us-east-1a", "us-east-1b", "us-east-1c"]`. What is the `availability_zone` assigned to the subnet?

  • A. "us-east-1a" — `element()` with index 1 returns the first element.
  • B. "us-east-1b" — `element()` uses zero-based indexing, so index 1 is the second element.✓ Correct
  • C. "us-east-1c" — `element()` with index 1 wraps around to the last element.
  • D. An error, because `element()` requires `count.index` as its second argument.
Explanation

**`"us-east-1b"`** is correct. `element()` uses zero-based indexing — index `0` is `"us-east-1a"`, index `1` is `"us-east-1b"`, and index `2` is `"us-east-1c"`. **`"us-east-1a"`** is incorrect; that would be index `0`. **`"us-east-1c"`** is incorrect; wrapping only occurs when the index exceeds the list length (e.g., index `3` would wrap to `"us-east-1a"`). **Requiring `count.index`** is incorrect; `element()` accepts any integer expression as its second argument.

3. A developer is configuring an AWS Auto Scaling group and wants to dynamically generate `tag` blocks based on a variable map, rather than hardcoding each tag block. The number of tags varies per environment. Which Terraform feature is best suited for this?

  • A. A `dynamic` block with a `for_each` argument iterating over the tags map.✓ Correct
  • B. A `count` meta-argument on the `aws_autoscaling_group` resource.
  • C. Multiple `locals` blocks, one for each potential tag.
  • D. A `for` expression inside the resource block to generate a list of tag objects.
Explanation

Option A is correct: `dynamic` blocks are specifically designed to programmatically generate repeated nested blocks (like `tag` blocks in `aws_autoscaling_group`) based on a collection. Using `for_each` within the dynamic block iterates over the map and produces one `tag` block per entry. Option B is wrong: `count` controls how many *instances* of the entire resource are created, not how many nested blocks exist within a single resource instance. Option C is wrong: multiple `locals` blocks do not generate nested blocks inside a resource. They only define reusable values within a module. Option D is wrong: a `for` expression can produce a list or map value, but the `tag` argument in `aws_autoscaling_group` requires repeated *blocks*, not a list value. You cannot substitute a `for` expression for repeated block syntax — that is exactly what `dynamic` blocks solve.

4. A security-conscious team enforces that all Terraform output values containing ARNs must be marked sensitive. A developer writes: ```hcl resource "aws_iam_role" "deployer" { name = "deployer" assume_role_policy = data.aws_iam_policy_document.assume.json } output "deployer_arn" { value = aws_iam_role.deployer.arn sensitive = true depends_on = [aws_iam_role_policy_attachment.deployer_policy] } ``` Which statement BEST describes the effect of `depends_on` in this output block?

  • A. `depends_on` in an output block has no effect; it is only valid on resource blocks.
  • B. `depends_on` ensures the output value is not computed until `aws_iam_role_policy_attachment.deployer_policy` has been applied, which is useful when the output's value doesn't directly reference the dependency.✓ Correct
  • C. `depends_on` forces the output to be re-evaluated on every `terraform apply`, bypassing the Terraform state cache.
  • D. `depends_on` in an output block causes Terraform to mark the output as tainted if the dependency changes.
Explanation

**`depends_on` in output blocks ensures ordering** — it instructs Terraform not to finalize the output until the specified dependency has been fully applied. This is particularly useful when the output's computed value doesn't directly reference the dependency resource (e.g., the ARN comes from the role, but you want to ensure the policy attachment is complete before exposing the ARN downstream). **`depends_on` having no effect on outputs** is incorrect; since Terraform 0.13+, `depends_on` is valid and functional on output blocks. **Forcing re-evaluation every apply** is incorrect; `depends_on` establishes ordering, not cache-busting behavior. **Tainting the output** is incorrect; Terraform does not have a concept of tainted outputs — tainting applies only to resource instances.

5. A team stores a list of allowed CIDR blocks in a variable and needs to pass a **set** of unique CIDRs to an AWS security group resource that expects `type = set(string)`. The variable is declared as `type = list(string)`. Which built-in function converts the list to a set, removing any duplicate entries?

  • A. toset()✓ Correct
  • B. distinct()
  • C. tolist()
  • D. compact()
Explanation

Option A is correct: `toset()` converts a list (or other collection) to a set, automatically removing duplicate values and dropping order, which matches the `set(string)` type expected by the resource. Option B is wrong: `distinct()` removes duplicate elements from a list but returns a **list**, not a set. The resource still expects a `set(string)`, so a type mismatch would occur. Option C is wrong: `tolist()` converts a set or tuple to a list — it goes in the opposite direction of what is needed here. Option D is wrong: `compact()` removes empty strings from a list of strings but does not remove non-empty duplicates, and it returns a list, not a set.

35 more questions in this domain

Practice the full bank with instant grading, flashcards, and a timed mock exam.

Start practicing free