FlashGenius Logo FlashGenius
Terraform Associate 004 · Page 3 of 5

Terraform Modules

Terraform Associate 004 · Objective 5

Module Sources · Registry · Local · Variable Scope · Inputs · Outputs · Versioning · Composition

Study with Practice Tests →

Objective 5: Terraform Modules

Everything you need to know about sourcing, using, scoping, and versioning modules for the Terraform Associate 004 exam.

Exam Terraform Associate 004
Duration 1 hour
Format Multiple Choice
Cost $70.50
Terraform Version 1.12
Page 3 of 5
📦

5a — Module Sources

Registry, local path, GitHub, generic Git, HCP Terraform private registry, S3/GCS/HTTP. terraform init downloads into .terraform/modules/.

🔀

5b — Variable Scope

Root vs. child modules. Input variables, output values, and local values. Locals are module-private; outputs expose data to the caller.

⚙️

5c — Using Modules

The module block, required vs. optional arguments, accessing outputs via module.name.output, and module composition (nested modules).

🔢

5d — Module Versions

Only registry and HCP private registry support version =. Git uses ?ref=. Pin versions in production; use terraform init -upgrade.

Exam Objectives Covered


Key topics: terraform init module block registry source local path input variables output values locals scope version constraint ~> operator module composition

Core Concepts

Deep-dive reference for each exam objective. Study all four sections before attempting the quiz.

📦 Module Sources 5a

The source argument in a module block tells Terraform where to find the module's code. terraform init downloads remote sources into .terraform/modules/ (gitignore this folder).

Source Type Example version =
Terraform Registry hashicorp/consul/aws Yes
HCP Terraform Private Registry app.terraform.io/example_corp/vpc/aws Yes
Local path ./modules/networking No
GitHub github.com/hashicorp/example No (use ?ref=)
Generic Git git::https://example.com/vpc.git?ref=v1.2 No (use ?ref=)
Git over SSH git::ssh://user@example.com/storage.git?ref=v1.2.0 No (use ?ref=)
S3 / GCS / HTTP https://example.com/vpc-module.zip No
# Terraform Registry — namespace/module/provider module "consul" { source = "hashicorp/consul/aws" version = "~> 0.1" } # Local path (dot-slash required) module "networking" { source = "./modules/networking" } # Git with ref pinning module "vpc" { source = "git::https://example.com/vpc.git?ref=v1.2.0" }
  • Registry URL: registry.terraform.io — official and verified modules live here
  • Registry format: <namespace>/<module>/<provider> — three parts, always
  • Verified modules show a blue checkmark; maintained by known vendors
  • Publishable module naming convention: terraform-<provider>-<name>
  • Local path modules: must begin with ./ or ../ so Terraform distinguishes them from registry sources
  • After adding or changing module source: always re-run terraform init

🔀 Variable Scope Within Modules 5b

Terraform organises configuration into a tree of modules. Understanding scope determines what values each module can see and expose.

  • Root module: the working directory where you run terraform commands; all .tf files at that level
  • Child module: any module called via a module block from the root or another module
  • Input variables: declared with variable blocks in the child; the caller passes values as arguments in the module block
  • Output values: declared with output in the child module; the only way to expose data back to the caller
  • Local values: locals { } — computed, named values that are module-private; they never escape their module
  • A parent module cannot directly reference a child module's resources or variables — only its outputs
  • Accessing a child module's output: module.<name>.<output_name>
# child module: modules/vpc/outputs.tf output "vpc_id" { description = "The ID of the VPC" value = aws_vpc.main.id } # root module: main.tf — accessing child output resource "aws_subnet" "example" { vpc_id = module.vpc.vpc_id } # locals — private to this module only locals { name_prefix = "prod-${var.env}" }

⚙️ Using Modules in Configuration 5c

The module block is how you call a module and pass input values. Every argument in the block maps to an input variable in the child module.

module "vpc" { source = "terraform-aws-modules/vpc/aws" version = "~> 5.0" # These are input variable values for the child module name = "my-vpc" cidr = "10.0.0.0/16" azs = ["us-east-1a", "us-east-1b"] private_subnets = ["10.0.1.0/24", "10.0.2.0/24"] public_subnets = ["10.0.101.0/24", "10.0.102.0/24"] } # Accessing outputs from the module output "vpc_id" { value = module.vpc.vpc_id } output "private_subnets" { value = module.vpc.private_subnets }
  • Required arguments: any input variable in the child that has no default value must be provided by the caller
  • Optional arguments: variables with defaults can be omitted; child uses its default
  • After adding or changing a source: must re-run terraform init to download the module
  • Module composition: modules can call other modules — this creates a tree (nested/child-of-child); root is always at the top
  • Standard module file structure: main.tf, variables.tf, outputs.tf, versions.tf, README.md
  • Any directory containing .tf files is technically a module
# Standard module directory layout modules/ networking/ main.tf # resource definitions variables.tf # input variable declarations outputs.tf # output value declarations versions.tf # required_providers block README.md # documentation (required for published modules)

🔢 Module Versions 5d

The version argument is only supported for Terraform Registry and HCP Terraform Private Registry sources. All other sources use different pinning mechanisms.

  • Registry only: use version = "~> 5.0" in the module block
  • Git sources: pin with ?ref=v1.2.0 appended to the URL — no version argument
  • Local paths: no versioning — they always read the current directory contents
  • Version constraint syntax is identical to provider version constraints
  • ~> 5.0 allows 5.x but not 6.0 (pessimistic constraint operator)
  • >= 4.0, < 6.0 — range constraint
  • "= 5.1.2" or just "5.1.2" — exact pin, best for production
  • After changing a module version: run terraform init -upgrade to download the new version
  • Best practice: always pin exact versions in production; use ~> for minor version flexibility in development
# Exact pin — most stable for production module "vpc" { source = "terraform-aws-modules/vpc/aws" version = "5.1.2" } # Pessimistic constraint — allows 5.x, blocks 6.0 module "vpc" { source = "terraform-aws-modules/vpc/aws" version = "~> 5.0" } # Range constraint module "vpc" { source = "terraform-aws-modules/vpc/aws" version = ">= 4.0, < 6.0" }

Memory Hooks

Six high-retention mnemonics for the most exam-tested module concepts.

1
Registry Format: Three Parts
The Terraform Registry source is always namespace / module / provider — think of it as "who / what / where".
hashicorp/consul/aws
2
version = is Registry-Only
Only registry and HCP private registry sources accept the version argument. Git sources pin with ?ref= in the URL instead.
git::…/vpc.git?ref=v1.2.0
3
Locals Never Escape
locals { } values are completely private to the module where they are defined. They cannot be referenced from a parent or sibling module — ever.
locals { } → module-private only
4
Outputs Are the Only Exit
To get data from a child module, the child must declare an output. The caller accesses it as module.name.output_name — no shortcut exists.
module.vpc.vpc_id
5
The Standard Three Files
A well-structured module has three core files: main.tf for resources, variables.tf for inputs, and outputs.tf for what the module exposes.
main.tf + variables.tf + outputs.tf
6
Init Downloads Modules
terraform init fetches remote modules into .terraform/modules/. This folder is auto-generated — always add it to .gitignore.
.terraform/modules/ → gitignore

Practice Quiz

10 questions covering all module objectives. Select an answer to see instant feedback.

Question 1 of 10
Which source string correctly references a module on the public Terraform Registry for the vpc module in the aws provider namespace by terraform-aws-modules?
Question 2 of 10
You add a new module block that sources from GitHub. What must you do before running terraform plan?
Question 3 of 10
You want to pin a Git-sourced module to the tag v2.1.0. Which syntax is correct?
Question 4 of 10
A child module defines locals { region = "us-east-1" }. How can the parent module access this value?
Question 5 of 10
A child module called network has an output named subnet_ids. How does the root module reference it?
Question 6 of 10
Which version constraint allows 5.1, 5.9, and 5.99 but NOT 6.0?
Question 7 of 10
You update a registry module's version constraint from ~> 4.0 to ~> 5.0. What command downloads the new version?
Question 8 of 10
Which of the following is the correct definition of the root module?
Question 9 of 10
A team member claims you can add version = "3.0.0" to a module block that uses a local path source (./modules/vpc). What happens?
Question 10 of 10
Module A calls Module B, and Module B calls Module C. What term describes this arrangement?

Score: 0 / 10

Flashcards

Click any card to reveal the answer. Work through all 8 for full objective coverage.

0 / 8 reviewed
Module Sources
What are the six main module source types in Terraform?
Terraform Registry, HCP Terraform Private Registry, Local path, GitHub, Generic Git (git::), and S3/GCS/HTTP URLs.
registry · private · ./local · github · git:: · https://
Versioning
Which module source types support the version = argument?
Only the Terraform Registry and HCP Terraform Private Registry. Local paths and Git sources do not support the version argument (Git uses ?ref= instead).
version = → registry only
Inputs & Outputs
How does a root module access an output named vpc_id from a child module called network?
Using the expression module.network.vpc_id. The child must declare the output with an output block; there is no other way to expose data.
module.<name>.<output_name>
Module Structure
What is the difference between the root module and a child module?
The root module is the working directory where you run terraform commands. A child module is any module invoked via a module block from the root or from another module.
root = working dir · child = called via module {}
Variable Scope
Can a parent module read a locals value defined in a child module? Why or why not?
No. Local values (locals { }) are scoped exclusively to the module where they are defined. They are completely private and never exposed outside that module.
locals = module-private, never escapable
Module Workflow
What must you do after changing a module's source or adding a new module block?
Run terraform init again. Terraform downloads the new module source into .terraform/modules/. For a version upgrade specifically, use terraform init -upgrade.
new/changed source → terraform init
Versioning
What does the ~> pessimistic constraint operator do when applied to a module version like ~> 5.0?
It allows any version >= 5.0 and < 6.0 (increments only the rightmost component). It permits patch and minor updates within the 5.x line but blocks the next major version.
~> 5.0 = 5.x only, never 6.0
Module Structure
Name the five standard files in a well-structured publishable Terraform module directory.
main.tf (resources), variables.tf (input declarations), outputs.tf (output declarations), versions.tf (required_providers), and README.md (required for published modules).
main · variables · outputs · versions · README

Tap a card to flip it · Tap again to return

Study Advisor

Select a category to get targeted study tips and common exam traps.

📦 Module Sources — Study Tips

  • Registry format quiz trap: It is always namespace/module/provider. The exam may reverse the order or use only two parts — watch for this.
  • Local path prefix: Local paths MUST begin with ./ or ../. Without the dot-slash, Terraform treats the string as a registry address.
  • Git vs GitHub: You can use github.com/org/repo shorthand or the full git::https://... form. Both are valid on the exam.
  • Download location: All remote modules are cached in .terraform/modules/. Always add this to .gitignore.
  • Verified modules: Look for the blue checkmark on registry.terraform.io. Verified ≠ official HashiCorp — it means a vetted vendor.
  • Naming convention: Publishable modules must follow terraform-<provider>-<name> for the repository name.

🔢 Versioning — Study Tips

  • version = is registry-exclusive: The most common exam trap — version is NOT supported for local paths or any Git-based source. Only registry and HCP private registry.
  • Git pinning: For Git, version pinning is done via the source URL itself: append ?ref=v1.2.0 to the URL.
  • ~> operator: ~> 5.0 allows 5.x but not 6.0. ~> 5.1 allows 5.1.x but not 5.2. The rightmost digit is the one that can increment.
  • Init -upgrade: Changing a version constraint alone won't download the new version. You must run terraform init -upgrade.
  • Production best practice: Exact pins ("5.1.2") for production; pessimistic constraints (~> 5.0) for development flexibility.

📤 Inputs & Outputs — Study Tips

  • Locals never escape: locals { } values are strictly module-private. No reference like module.child.local.name exists — it will error.
  • Only outputs expose data: To pass data from child to parent, the child must declare an output block. There is no other mechanism.
  • Output reference syntax: module.<label>.<output_name> — note three parts: keyword, module label, output name.
  • Required vs optional inputs: Variables with no default are required; the caller must supply them. Variables with a default are optional.
  • Sensitive outputs: Mark outputs sensitive = true to suppress them in plan/apply output, but they are still accessible by reference.

🏗️ Module Structure — Study Tips

  • Any directory is a module: Technically, any directory with .tf files is a module. The formal five-file structure is a best practice, not a requirement.
  • Root module definition: The root module is the working directory from which you run Terraform — not the first module block in the code.
  • Child module isolation: A parent cannot directly reference resources or variables inside a child module — only its declared outputs.
  • versions.tf: Contains the terraform { required_providers { } } block — separating this makes the module easier to maintain.
  • README required: Published modules on the registry must include a README.md. Input/output blocks should have description fields for the registry to display documentation.

🔄 Module Workflow — Study Tips

  • Always init after source changes: Any time you add a new module block or change the source, you must run terraform init before plan or apply.
  • Init -upgrade for version changes: If you only change the version constraint, use terraform init -upgrade to fetch the updated version.
  • Module composition: Modules can call other modules, creating a tree. The root is always the top-level working directory. This is called module composition, not inheritance.
  • Gitignore .terraform/modules/: This directory is auto-generated by terraform init and should never be committed to source control.
  • Local modules and init: Local path modules do not need to be "downloaded," but you still need to run terraform init after adding them so Terraform registers the module in its internal index.

Resources

Authoritative references for deeper study and exam preparation.

Official Docs

Terraform Modules Documentation

Complete language reference for module blocks, sources, inputs, outputs, and composition.

Registry

Terraform Registry

Browse verified and community modules. See version history, changelogs, and input/output docs.

Exam Guide

Terraform Associate 004 Exam Guide

Official objectives, study guide, and sample questions from HashiCorp.

Tutorial

Create a Module Tutorial

Step-by-step tutorial for building, structuring, and publishing your own Terraform module.

Tutorial

Use Registry Modules Tutorial

Hands-on guide to sourcing, configuring, and versioning modules from the public registry.

Practice Tests

FlashGenius Practice Tests

Full-length Terraform Associate 004 practice exams with detailed answer explanations.


Page Navigation

Page 1: Core Concepts & IaC Page 2: Providers & State Page 3: Modules (this page) Page 4: Commands & Workflow Page 5: HCP Terraform & Backends

Ready to Test Your Knowledge?

Full-length Terraform Associate 004 practice exams with detailed explanations for every answer.

Start Free Practice Tests →