HashiCorp Terraform Associate (004) Question 150
Single answer5c Use modules in configurationYour team maintains a reusable Terraform module named network in a private Git repository. The module creates a VPC and subnets and exposes outputs such as vpc_id. In a root configuration, you need to use version v1.4.2 of that module and create two identical networking environments, dev and prod, with different CIDR blocks. You also want the configuration to remain easy to maintain and follow Terraform module best practices. Which configuration is the best choice?
- A
Define one
module "network"block withsource = "git::https://example.com/org/network.git?ref=v1.4.2"andfor_each = { dev = "10.10.0.0/16", prod = "10.20.0.0/16" }, then passcidr_block = each.valueand usemodule.network["dev"].vpc_idwhen referencing outputs. - B
Define one
module "network"block withsource = "git::https://example.com/org/network.git"andversion = "1.4.2", then usecount = 2and hard-code the CIDR blocks inside the child module so the root module stays smaller. - C
Copy the contents of the
networkmodule directly into the root configuration twice, once fordevand once forprod, because modules cannot be instantiated multiple times from the same source in a single configuration. - D
Define two separate
moduleblocks namednetwork-devandnetwork-prod, each withsource = "./modules/network", and setversion = "v1.4.2"in both blocks to pin the local module version.
Show answer and explanation
Correct answer: A
Explanation
This question tests practical module usage in Terraform: sourcing modules, pinning versions correctly, creating multiple module instances, and passing inputs from a root module. For modules from a Git repository, Terraform expects the source address to include a VCS prefix such as git:: and a ref query parameter to select a tag, branch, or commit. The version meta-argument is reserved for registry modules, not Git or local path sources. Terraform also allows count and for_each on module blocks, and for_each is usually the better choice when instances have meaningful names like dev and prod, because references remain explicit and stable. Best practice is to keep child modules reusable by defining input variables and outputs rather than embedding environment-specific values inside the module. These behaviors are documented in Terraform's module configuration, module source, and meta-argument documentation.
- A. Correct.
Correct. Terraform supports using
for_eachwith module blocks to create multiple instances of the same module from a single definition. Using a Git source with?ref=v1.4.2is the correct way to pin a module version when the source is a VCS repository. Passing environment-specific values like CIDR blocks from the root module follows module design best practices, and outputs from module instances created withfor_eachare referenced by key, such asmodule.network["dev"].vpc_id. - B. Incorrect.
Incorrect. The
versionargument works only for modules sourced from a Terraform registry, not for Git or other generic VCS sources. For a Git source, version pinning is done with?ref=in thesourcestring. Also, hard-coding environment-specific CIDR blocks inside the child module reduces reusability and violates the purpose of parameterized modules. - C. Incorrect.
Incorrect. Terraform modules are specifically designed to be instantiated multiple times, including from the same source, using either multiple module blocks or meta-arguments like
countandfor_each. Copying module contents into the root configuration defeats reuse, increases maintenance overhead, and is not a best practice. - D. Incorrect.
Incorrect. Module block labels must be valid identifiers, so names like
network-devare not valid because hyphens are not allowed in Terraform identifiers. In addition, theversionargument does not apply to local path modules such as./modules/network; local modules are simply loaded from the specified path and cannot be version-pinned with theversionargument.