HashiCorp Terraform Associate (004) exam dumps

HashiCorp Terraform Associate (004) practice question 112 of 223

Terraform Associate 004. Associate level, HashiCorp. Free question with the correct answer and a full explanation.

HashiCorp Terraform Associate (004) Question 112

Single answer4e Write dynamic configuration using expressions and functions

A platform team uses Terraform to create security groups for multiple application components. They want each security group to include one ingress rule per allowed CIDR block, but only when a component has at least one CIDR defined. The team stores input in a variable:

variable "components" { type = map(object({ port = number allowed_cidrs = list(string) })) }

An example value is: { api = { port = 443 allowed_cidrs = ["10.0.0.0/24", "10.0.1.0/24"] } worker = { port = 8080 allowed_cidrs = [] } }

Which configuration correctly uses Terraform expressions and functions to create one aws_security_group per component and dynamically add ingress blocks only for components that have CIDR entries?

  1. A

    resource "aws_security_group" "component" { for_each = var.components

    name = each.key

    dynamic "ingress" { for_each = length(each.value.allowed_cidrs) > 0 ? each.value.allowed_cidrs : [] content { from_port = each.value.port to_port = each.value.port protocol = "tcp" cidr_blocks = [ingress.value] } } }

  2. B

    resource "aws_security_group" "component" { count = length(var.components)

    name = keys(var.components)[count.index]

    dynamic "ingress" { for_each = var.components[count.index].allowed_cidrs content { from_port = var.components[count.index].port to_port = var.components[count.index].port protocol = "tcp" cidr_blocks = [ingress.key] } } }

  3. C

    resource "aws_security_group" "component" { for_each = var.components

    name = each.key

    ingress = [for cidr in each.value.allowed_cidrs : { from_port = each.value.port to_port = each.value.port protocol = "tcp" cidr_blocks = [cidr] }] }

  4. D

    resource "aws_security_group" "component" { for_each = var.components

    name = each.key

    dynamic "ingress" { for_each = contains(each.value.allowed_cidrs, "0.0.0.0/0") ? each.value.allowed_cidrs : null content { from_port = each.value.port to_port = each.value.port protocol = "tcp" cidr_blocks = ingress.value } } }

Show answer and explanation

Correct answer: A

Explanation

The best answer is the configuration that combines resource-level for_each with a dynamic nested block. In Terraform, for_each is well suited for creating one resource instance per element in a map or set, preserving stable addressing by key. Dynamic blocks are the correct mechanism for generating repeatable nested blocks such as ingress based on input data. A common best practice is to make the dynamic block's for_each evaluate to an empty collection when no blocks should be created. That is exactly what the conditional expression in Option 1 does.

This question tests practical use of expressions and functions together: length() checks whether the list has values, the conditional expression selects either the list or an empty list, and the dynamic block uses ingress.value for the current element. Candidates should also recognize that map iteration usually favors for_each over count, and that Terraform distinguishes between arguments and nested blocks. HashiCorp documentation on dynamic blocks, for_each, conditional expressions, and built-in functions such as length supports these patterns and is the basis for this solution.

  • A. Correct.

    Correct. This configuration uses for_each at the resource level to create one security group per component in the map, which is the preferred pattern when working with keyed collections. Inside the resource, a dynamic "ingress" block iterates over each.value.allowed_cidrs. The conditional expression returns the list of CIDRs when the list is non-empty, or an empty list otherwise, so no ingress blocks are generated for components like worker that have no allowed CIDRs. Within the dynamic block, ingress.value refers to the current CIDR string, and cidr_blocks expects a list, so wrapping it as [ingress.value] is appropriate. Using each.value.port inside the content block is also valid because each refers to the current resource instance.

  • B. Incorrect.

    Incorrect. var.components is a map, so using count with numeric indexes is a poor fit and the expressions shown are invalid. In particular, var.components[count.index] is not valid because maps are accessed by key, not by numeric index. Although keys(var.components)[count.index] can derive a key string, the code would then need to use that key to index the map consistently. Also, inside the dynamic block, ingress.key is wrong for a list iteration because when iterating a list, ingress.value is the element value and ingress.key is the numeric index. Using the index as a CIDR block would fail. This option reflects a common misconception that count can be used interchangeably with for_each for maps.

  • C. Incorrect.

    Incorrect. The intent is plausible, but this syntax does not match how nested ingress blocks are defined for this resource. The aws_security_group resource expects repeated nested ingress blocks, and Terraform provides dynamic blocks specifically to generate nested blocks from expressions. Assigning ingress to a list of objects is not the standard supported syntax for this nested block in Terraform configuration. A candidate might choose this because for expressions do produce collections dynamically, but they are not a replacement for nested block generation in this case.

  • D. Incorrect.

    Incorrect. The condition is unrelated to the requirement. The team wants ingress rules whenever the component has any CIDRs, not only when the list contains 0.0.0.0/0. Also, dynamic block for_each must evaluate to a collection, not null, so returning null is invalid here; an empty list would be the correct way to generate zero nested blocks. Finally, cidr_blocks expects a list of strings, but ingress.value would already be a single string from iterating over allowed_cidrs, so assigning cidr_blocks = ingress.value is the wrong type. This option combines several realistic mistakes involving contains, null handling, and attribute types.

Timed practice exam

Take a HashiCorp Terraform Associate (004) practice test under exam conditions

70 questions in 60 minutes, drawn from this bank, with a score report and a per-question review when you finish.

Start timed exam