Skip to content

004 · Domain 4: Terraform configuration · 13% of the exam

Task 4.7: Validate configuration using custom conditions

Variable validation blocks, preconditions and postconditions on resources, data sources and outputs, and check blocks with assertions that warn instead of blocking.

Study it

  • Custom conditions: validation, preconditions, postconditions and checks

    Lesson coming

Sample questions

Try each one before opening the answer. Every option is explained, with the HashiCorp documentation page that proves it.

Question 1 · choose 1

A module has an input variable named env that must be one of dev, stage or prod. A wrong value should stop the run with the author's own error message, checked where the value enters the module. What should the module author add?

  1. AA type constraint of string on env, with default = "dev"
  2. BA validation block on env with a condition and an error_message
  3. CA local map keyed by dev, stage and prod, indexed with var.env
  4. DA terraform.tfvars file in the module that lists the allowed values
Show the answer and why
  • AA type constraint of string on env, with default = "dev"

    Incorrect

    A type constraint checks the kind of value, and a default only applies when no value is given; any other string still passes.

  • BA validation block on env with a condition and an error_message

    Correct

    A validation block checks the value a caller supplies against a condition and stops the operation with the error_message when the condition is false.

  • CA local map keyed by dev, stage and prod, indexed with var.env

    Incorrect

    An unknown key does fail, but with a generic invalid index error at the place where the map is used, not with the author's message.

  • DA terraform.tfvars file in the module that lists the allowed values

    Incorrect

    A .tfvars file assigns values to root module variables; it cannot restrict which values a variable accepts.

Validate inputs where they enter: a validation block on the variable, with a condition such as contains(["dev", "stage", "prod"], var.env) and a clear error_message.

Question 2 · choose 1

A module output exposes a security group ID. The module author wants to make sure an invalid value is never stored in state as that output. Where can the condition go?

  1. AIn a validation block inside the output block
  2. BIn a precondition block in the output
  3. CIn a lifecycle block inside the output block
  4. DIn a postcondition inside the output block
Show the answer and why
  • AIn a validation block inside the output block

    Incorrect

    Output blocks have no validation argument.

  • BIn a precondition block in the output

    Correct

    An output block can contain precondition blocks; if one fails, Terraform stops the operation with its error message instead of recording the output value.

  • CIn a lifecycle block inside the output block

    Incorrect

    Output blocks have no lifecycle block; a precondition sits directly in the output.

  • DIn a postcondition inside the output block

    Incorrect

    Outputs support preconditions, not postconditions.

Outputs can guard their own values with preconditions, so a module never hands its callers a value that breaks its promises.

Question 3 · choose 1

A custom condition must be false, rather than stop with a function error, whenever var.name does not match the pattern ^[a-z0-9-]+$. Which condition expression does this?

  1. Aregex("^[a-z0-9-]+$", var.name)
  2. Btry(var.name, "^[a-z0-9-]+$")
  3. Ccontains("^[a-z0-9-]+$", var.name)
  4. Dcan(regex("^[a-z0-9-]+$", var.name))
Show the answer and why
  • Aregex("^[a-z0-9-]+$", var.name)

    Incorrect

    regex returns the matched text or raises an error when nothing matches; it never returns false.

  • Btry(var.name, "^[a-z0-9-]+$")

    Incorrect

    try hands back one of its argument values, here the name itself, so the condition gets a string, not a true or false result.

  • Ccontains("^[a-z0-9-]+$", var.name)

    Incorrect

    contains checks whether a list or set holds a value; it does not match patterns.

  • Dcan(regex("^[a-z0-9-]+$", var.name))

    Correct

    can evaluates its argument and returns true if it succeeds and false if it raises an error, which turns a failed match into false.

A condition needs a true or false value. can() wraps an expression that might fail and reports success as a boolean, which suits regex and similar functions.

Question 4 · choose 1

A module contains this block: check "api_dns" { data "dns_a_record_set" "api" { host = "api.example.com" } assert { condition = length(data.dns_a_record_set.api.addrs) > 0 error_message = "api.example.com has no A records." } } An engineer adds an output elsewhere in the module with value = data.dns_a_record_set.api.addrs, and Terraform reports an error. Why?

  1. AA nested data source must be referenced with a check prefix, as check.api_dns.data.dns_a_record_set.api
  2. BThe output needs depends_on = [check.api_dns] before it can read the record set
  3. CA data source nested in a check block can be referenced only inside that check block
  4. DAn output must read a data source through a local value, not directly
Show the answer and why
  • AA nested data source must be referenced with a check prefix, as check.api_dns.data.dns_a_record_set.api

    Incorrect

    There is no such address form; a nested data source is not reachable from outside its check block under any name.

  • BThe output needs depends_on = [check.api_dns] before it can read the record set

    Incorrect

    depends_on does not change where a nested data source can be used.

  • CA data source nested in a check block can be referenced only inside that check block

    Correct

    The check block reference limits a nested data source to its parent check block, where the assert conditions use it.

  • DAn output must read a data source through a local value, not directly

    Incorrect

    Outputs can reference ordinary data blocks directly; the restriction comes from the nesting inside the check block.

To use the record set elsewhere, declare an ordinary data block at the module level; the scoped copy stays private to its check.

Question 5 · choose 2

A module author is writing the error_message arguments of the module's custom conditions and wants them to explain each failure clearly. Which two statements about error_message are true? (Choose TWO.)

  1. AIt takes a literal string, so it cannot include the value that failed
  2. BIt is written to the state file rather than shown in the terminal
  3. CIt must fit on one line, because Terraform rejects line breaks in it
  4. DIt can span several lines, for example as a heredoc string
  5. EIt can be any expression that evaluates to a string, such as a template
Show the answer and why
  • AIt takes a literal string, so it cannot include the value that failed

    Incorrect

    error_message accepts expressions, so a message can include values, for example through format().

  • BIt is written to the state file rather than shown in the terminal

    Incorrect

    The message is shown to the person running Terraform, alongside the name of the resource that detected the problem.

  • CIt must fit on one line, because Terraform rejects line breaks in it

    Incorrect

    Multi-line error messages are supported.

  • DIt can span several lines, for example as a heredoc string

    Correct

    Multi-line error messages are supported, and Terraform does not wrap lines that start with whitespace.

  • EIt can be any expression that evaluates to a string, such as a template

    Correct

    error_message supports any expression that evaluates to a string; format() helps turn null, list or map values into text.

Treat error messages as part of the module's interface: full sentences, in Terraform's own style, that say what failed and, where it helps, which value.

Practise domain 4 →Practise all domains →