Skip to content

002 · Domain 1: Scalable Terraform Configuration Design · 20% of the exam

Task 1.2: Predictable and secure Terraform configuration

Configuration that behaves the same on every run: stable instance keys, the style guide's file layout, outputs as the only interface, providers passed into modules instead of configured there, and moved blocks so a refactor never destroys anything.

Study it

  • Predictable configuration: stable keys, file layout, providers outside modules, moved blocks

    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 shared logging module names its bucket "${terraform.workspace}-logs". A root configuration now needs two instances of the module, one for application logs and one for audit logs, in every workspace. Bucket names must stay readable and must be decided by configuration, not chosen at random. What should the module author change?

  1. AAppend count.index to the name and set count = 1 on each module call
  2. BReplace terraform.workspace with uuid() to make every name unique
  3. CReplace terraform.workspace with path.module to give each module call its own name
  4. DAdd a name_prefix input that callers set, such as "audit-${terraform.workspace}"
Show the answer and why
  • AAppend count.index to the name and set count = 1 on each module call

    Incorrect

    Each call has its own instance 0, so both calls still build the same name and collide.

  • BReplace terraform.workspace with uuid() to make every name unique

    Incorrect

    uuid() returns a new value each time it is called, so the names are neither readable nor stable and every plan shows a spurious diff.

  • CReplace terraform.workspace with path.module to give each module call its own name

    Incorrect

    path.module is a filesystem path, not a readable name, and it does not tell two calls of the same local module apart.

  • DAdd a name_prefix input that callers set, such as "audit-${terraform.workspace}"

    Correct

    The caller supplies the prefix, so it can call the module more than once and still use the workspace name where it wants it.

Apart from path.module, HashiCorp recommends using the filesystem and workspace values only in the root module. A shared module that needs a unique prefix should take it as an input variable, so the caller decides how names differ between calls.

Question 2 · choose 1

A module sets the tag created_at = timestamp() on every bucket. Since then, every plan proposes updating all buckets even when nothing else changed. What explains this?

  1. Atimestamp() returns a new value on every run, and the tag never matches the value in state
  2. BThe provider stores tags in another timezone, and each refresh reports a new value
  3. CTags set by any function are unknown until apply, which forces an update on every plan
  4. DTerraform swaps timestamp() for plantimestamp() during plans, and the two never agree
Show the answer and why
  • Atimestamp() returns a new value on every run, and the tag never matches the value in state

    Correct

    The value changes every second and is taken at apply, so using it in a resource argument causes a diff on every run.

  • BThe provider stores tags in another timezone, and each refresh reports a new value

    Incorrect

    The diff comes from the function's changing value, not from how the provider stores the tag.

  • CTags set by any function are unknown until apply, which forces an update on every plan

    Incorrect

    Most functions return known values during planning; timestamp() is special because its value is always new.

  • DTerraform swaps timestamp() for plantimestamp() during plans, and the two never agree

    Incorrect

    Terraform does not substitute one function for the other; they are separate functions.

HashiCorp advises against timestamp() in resource arguments. Use it with ignore_changes to keep the creation time, or use the Time provider for a stable timestamp.

Question 3 · choose 1

Following the HashiCorp style guide's file naming conventions, which file holds the terraform block that sets required_version and required_providers?

  1. Aproviders.tf, with the provider blocks
  2. Bmain.tf, with the resources and data sources
  3. Cterraform.tf
  4. Dbackend.tf, with the backend settings
Show the answer and why
  • Aproviders.tf, with the provider blocks

    Incorrect

    providers.tf holds the provider blocks and their configuration.

  • Bmain.tf, with the resources and data sources

    Incorrect

    main.tf holds the resource and data source blocks.

  • Cterraform.tf

    Correct

    The style guide puts a single terraform block with required_version and required_providers in terraform.tf.

  • Dbackend.tf, with the backend settings

    Incorrect

    backend.tf holds the backend configuration, which can be a separate terraform block.

A predictable layout lets every maintainer find versions, providers, variables and outputs in the same place in every repository.

Question 4 · choose 1

A configuration needs AWS in us-east-1 and in us-west-2. Which layout of the provider blocks follows the HashiCorp style guide?

  1. ATwo aliased blocks, east and west, and no unaliased default configuration at all
  2. BThe default block first, then a block whose first argument is alias = "west"
  3. CThe aliased block first, with alias as its last argument
  4. DEach provider block in its own file, named after the region
Show the answer and why
  • ATwo aliased blocks, east and west, and no unaliased default configuration at all

    Incorrect

    The style guide says to always include a default provider configuration.

  • BThe default block first, then a block whose first argument is alias = "west"

    Correct

    Define the default first, and in non-default blocks put alias as the first parameter, with all providers in the same file.

  • CThe aliased block first, with alias as its last argument

    Incorrect

    The guide puts the default first and alias first inside the aliased block.

  • DEach provider block in its own file, named after the region

    Incorrect

    The guide recommends defining all of your providers in the same file.

Consistent provider layout makes it obvious which configuration is the default and which resources need a provider meta-argument.

Question 5 · choose 1

A team writes the .gitignore for a new Terraform repository. Which of these belongs in it according to the HashiCorp style guide?

  1. AThe .terraform.lock.hcl dependency lock file
  2. BThe README.md that documents the inputs and outputs of the root module
  3. CThe *.tf configuration files
  4. DSaved plan files created with terraform plan -out
Show the answer and why
  • AThe .terraform.lock.hcl dependency lock file

    Incorrect

    The style guide says to always commit the dependency lock file.

  • BThe README.md that documents the inputs and outputs of the root module

    Incorrect

    The guide recommends committing a README.md that describes the code.

  • CThe *.tf configuration files

    Incorrect

    All Terraform code files belong in version control.

  • DSaved plan files created with terraform plan -out

    Correct

    The style guide lists saved plan files among the files you should not commit.

Do not commit state files and their backups, the .terraform directory, state lock info, saved plans or .tfvars files with secrets; do commit code, the lock file and the README.

Practice domain 1 →Practice all domains →