Bird
Raised Fist0
Terraformcloud~5 mins

Module composition patterns in Terraform - Commands & Configuration

Choose your learning style10 modes available
Introduction
When building infrastructure with Terraform, you often need to reuse and organize code. Module composition patterns help you combine smaller modules into bigger ones, making your infrastructure easier to manage and scale.
When you want to reuse a set of resources like networking or compute across multiple projects.
When you need to organize complex infrastructure into smaller, understandable parts.
When you want to share common infrastructure code with your team or across environments.
When you want to avoid repeating the same resource definitions in multiple places.
When you want to build layered infrastructure where one module uses other modules.
Config File - main.tf
main.tf
terraform {
  required_version = ">= 1.3.0"
}

provider "aws" {
  region = "us-east-1"
}

module "network" {
  source = "./modules/network"
  vpc_cidr = "10.0.0.0/16"
}

module "compute" {
  source = "./modules/compute"
  subnet_id = module.network.public_subnet_id
  instance_type = "t3.micro"
}

This file shows how to compose two modules: network and compute.

The network module creates a VPC and subnet. The compute module creates an EC2 instance inside the subnet created by the network module.

This pattern helps organize infrastructure by responsibility and reuse modules easily.

Commands
This command initializes the Terraform working directory. It downloads the modules and providers needed for the configuration.
Terminal
terraform init
Expected OutputExpected
Initializing the backend... Initializing provider plugins... - Finding latest version of hashicorp/aws... - Installing hashicorp/aws v4.60.0... - Installed hashicorp/aws v4.60.0 (signed by HashiCorp) Terraform has been successfully initialized! You may now begin working with Terraform. Try running "terraform plan" to see any changes that are required for your infrastructure.
This command shows what Terraform will create or change based on the composed modules before applying any changes.
Terminal
terraform plan
Expected OutputExpected
Refreshing Terraform state in-memory prior to plan... An execution plan has been generated and is shown below. Resource actions are indicated with the following symbols: + create Terraform will perform the following actions: # aws_vpc.main will be created + resource "aws_vpc" "main" { + cidr_block = "10.0.0.0/16" + id = (known after apply) } # aws_subnet.public will be created + resource "aws_subnet" "public" { + vpc_id = (known after apply) + cidr_block = "10.0.1.0/24" + id = (known after apply) } # aws_instance.web will be created + resource "aws_instance" "web" { + instance_type = "t3.micro" + subnet_id = (known after apply) + id = (known after apply) } Plan: 3 to add, 0 to change, 0 to destroy.
This command applies the planned changes and creates the infrastructure defined by the composed modules.
Terminal
terraform apply -auto-approve
Expected OutputExpected
aws_vpc.main: Creating... aws_vpc.main: Creation complete after 3s [id=vpc-0abcd1234efgh5678] aws_subnet.public: Creating... aws_subnet.public: Creation complete after 2s [id=subnet-0abcd1234efgh5678] aws_instance.web: Creating... aws_instance.web: Still creating... [10s elapsed] aws_instance.web: Creation complete after 15s [id=i-0abcd1234efgh5678] Apply complete! Resources: 3 added, 0 changed, 0 destroyed.
→
-auto-approve - Automatically approve the apply without prompting
This command shows the outputs defined by the modules, such as subnet IDs or instance IPs, to verify the composed infrastructure.
Terminal
terraform output
Expected OutputExpected
public_subnet_id = "subnet-0abcd1234efgh5678" instance_id = "i-0abcd1234efgh5678"
Key Concept

If you remember nothing else from this pattern, remember: compose small reusable modules by passing outputs from one as inputs to another to build organized and scalable infrastructure.

Common Mistakes
Not passing outputs from one module as inputs to another module.
Modules won't connect properly, causing errors or isolated resources that don't work together.
Always use module outputs as inputs when composing modules to link resources correctly.
Using relative paths incorrectly in the module source attribute.
Terraform cannot find the module code, causing initialization errors.
Use correct relative paths like "./modules/network" relative to the root module.
Not running terraform init after adding or changing modules.
Terraform won't download or update modules, causing plan or apply failures.
Always run terraform init after modifying module sources.
Summary
Use modules to organize infrastructure into reusable parts.
Pass outputs from one module as inputs to another to compose infrastructure.
Run terraform init, plan, and apply to deploy composed modules.

Practice

(1/5)
1. What is the main purpose of using module composition patterns in Terraform?
easy
A. To combine multiple modules by passing outputs as inputs for better organization
B. To write all resources in a single large file
C. To avoid using variables in Terraform configurations
D. To deploy resources without any dependencies

Solution

  1. Step 1: Understand module composition

    Module composition means connecting modules by using outputs from one as inputs to another.
  2. Step 2: Recognize benefits

    This approach keeps infrastructure code organized, reusable, and easier to manage.
  3. Final Answer:

    To combine multiple modules by passing outputs as inputs for better organization -> Option A
  4. Quick Check:

    Module composition = combining modules with outputs as inputs [OK]
Hint: Think of modules as building blocks connected by outputs [OK]
Common Mistakes:
  • Thinking modules should be combined by copying code
  • Believing variables are avoided in module composition
  • Assuming modules work independently without connections
2. Which of the following is the correct syntax to pass an output from one module as an input to another in Terraform?
easy
A. output.moduleA.output_name
B. module.moduleA.output_name
C. var.moduleA.output_name
D. resource.moduleA.output_name

Solution

  1. Step 1: Recall Terraform module output reference syntax

    Outputs from a module are accessed using module.<module_name>.<output_name>.
  2. Step 2: Compare options

    Only module.moduleA.output_name matches the correct syntax for accessing module outputs.
  3. Final Answer:

    module.moduleA.output_name -> Option B
  4. Quick Check:

    Module output reference = module.module_name.output_name [OK]
Hint: Outputs are accessed via module.<name>.<output> [OK]
Common Mistakes:
  • Using var or resource instead of module to access outputs
  • Confusing output blocks with module references
  • Using incorrect keywords like output.moduleA
3. Given the following Terraform code snippet, what will be the value of moduleB's input instance_id?
module "moduleA" {
  source = "./moduleA"
}

module "moduleB" {
  source      = "./moduleB"
  instance_id = module.moduleA.instance_id
}
medium
A. The value of the output named instance_id from moduleA
B. A syntax error because instance_id is not defined
C. The string literal 'module.moduleA.instance_id'
D. Null because moduleB does not have instance_id output

Solution

  1. Step 1: Identify module output usage

    The input instance_id for moduleB is assigned from module.moduleA.instance_id, which means it uses the output named instance_id from moduleA.
  2. Step 2: Understand value passing

    This passes the actual value of moduleA's output to moduleB's input, not a string or error.
  3. Final Answer:

    The value of the output named instance_id from moduleA -> Option A
  4. Quick Check:

    moduleB.instance_id = moduleA.instance_id output value [OK]
Hint: module.<name>.<output> passes actual output value, not string [OK]
Common Mistakes:
  • Thinking it passes a string literal instead of value
  • Assuming syntax error due to missing variable declaration
  • Confusing inputs and outputs between modules
4. You have two modules: moduleA outputs vpc_id, and moduleB requires vpc_id as input. The following code causes an error:
module "moduleA" {
  source = "./moduleA"
}

module "moduleB" {
  source = "./moduleB"
  vpc_id = var.vpc_id
}
What is the most likely cause of the error?
medium
A. moduleB source path is incorrect
B. moduleA does not have an output named vpc_id
C. moduleB is using var.vpc_id instead of module.moduleA.vpc_id as input
D. Terraform does not support passing outputs between modules

Solution

  1. Step 1: Check input assignment in moduleB

    moduleB expects vpc_id input, but it is assigned from var.vpc_id, which is a variable, not the output from moduleA.
  2. Step 2: Identify correct way to pass output

    The correct way is to assign vpc_id = module.moduleA.vpc_id to pass the output from moduleA.
  3. Final Answer:

    moduleB is using var.vpc_id instead of module.moduleA.vpc_id as input -> Option C
  4. Quick Check:

    Pass outputs via module.moduleA.output, not var [OK]
Hint: Use module.<name>.<output> to pass outputs, not var.<name> [OK]
Common Mistakes:
  • Assuming var.vpc_id automatically links to moduleA output
  • Ignoring the need to explicitly connect modules
  • Thinking Terraform cannot pass outputs between modules
5. You want to create a composed Terraform setup where moduleC depends on outputs from both moduleA and moduleB. Which pattern correctly composes these modules to pass outputs as inputs to moduleC?
// Option A
module "moduleC" {
  source = "./moduleC"
  inputA = module.moduleA.outputA
  inputB = module.moduleB.outputB
}

// Option B
module "moduleC" {
  source = "./moduleC"
  inputA = var.outputA
  inputB = var.outputB
}

// Option C
module "moduleC" {
  source = "./moduleC"
  inputA = module.moduleB.outputB
  inputB = module.moduleA.outputA
}

// Option D
module "moduleC" {
  source = "./moduleC"
  inputA = module.moduleA.outputB
  inputB = module.moduleB.outputA
}
hard
A. Mix outputs incorrectly between modules
B. Use variables instead of module outputs for inputs
C. Swap inputs but still use correct module outputs
D. Pass outputs correctly matching input names from moduleA and moduleB

Solution

  1. Step 1: Match inputs to correct module outputs

    Pass outputs correctly matching input names from moduleA and moduleB passes inputA from moduleA.outputA and inputB from moduleB.outputB, matching names correctly.
  2. Step 2: Evaluate other options

    Use variables instead of module outputs for inputs uses variables instead of outputs, which breaks composition. Swap inputs but still use correct module outputs swaps the assignments, mismatching inputA (expects moduleA.outputA) with moduleB.outputB and inputB with moduleA.outputA. Mix outputs incorrectly between modules mixes outputs incorrectly, likely causing errors.
  3. Final Answer:

    Pass outputs correctly matching input names from moduleA and moduleB -> Option D
  4. Quick Check:

    Correct output-to-input mapping = Pass outputs correctly matching input names from moduleA and moduleB [OK]
Hint: Match input names to correct module outputs carefully [OK]
Common Mistakes:
  • Swapping outputs between modules without checking input expectations
  • Using variables instead of module outputs
  • Mixing output names incorrectly causing runtime errors
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard