📖 Scenario: You are building a simple cloud infrastructure using Terraform. You want to organize your code by creating reusable modules. This project will guide you through composing modules to build a virtual private cloud (VPC) with subnets.
🎯 Goal: Build a Terraform configuration that uses module composition patterns to create a VPC and two subnets inside it. You will create the initial variables, configure module inputs, apply the main module calls, and complete the configuration with outputs.
📋 What You'll Learn
Create a variables file with exact variable names and values
Configure module input variables with correct values
Call modules with proper source and input arguments
Add outputs to expose the created resources
💡 Why This Matters
🌍 Real World
Organizing Terraform code into modules helps manage complex cloud infrastructure by reusing and composing components.
💼 Career
Understanding module composition is essential for cloud engineers and DevOps professionals to build scalable and maintainable infrastructure as code.
Progress0 / 4 steps
1
Create variables for VPC and subnet CIDR blocks
Create a Terraform variables file named variables.tf with two variables: vpc_cidr set to "10.0.0.0/16" and subnet_cidrs set to a list containing "10.0.1.0/24" and "10.0.2.0/24".
Terraform
Hint
Define variables using the variable block with default values.
2
Configure module input variables for VPC and subnet modules
In a new file named modules.tf, declare two module blocks: vpc with source ./modules/vpc and input variable cidr_block set to var.vpc_cidr, and subnets with source ./modules/subnet and input variable cidr_blocks set to var.subnet_cidrs.
Terraform
Hint
Use module blocks with source and input variables referencing var. variables.
3
Use for_each to create multiple subnets from the subnet module
Modify the subnets module block to use for_each over var.subnet_cidrs. Pass each subnet CIDR block to the module input variable cidr_block using each.value. Rename the module block to subnet (singular).
Terraform
Hint
Use for_each = toset(var.subnet_cidrs) and pass cidr_block = each.value inside the module block.
4
Add outputs to expose VPC ID and subnet IDs
Create an outputs.tf file that defines two outputs: vpc_id which gets the id attribute from module.vpc, and subnet_ids which collects the id attributes from all module.subnet instances using values(module.subnet)[*].id.
Terraform
Hint
Define outputs using output blocks and use a for expression to collect subnet IDs.
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
Step 1: Understand module composition
Module composition means connecting modules by using outputs from one as inputs to another.
Step 2: Recognize benefits
This approach keeps infrastructure code organized, reusable, and easier to manage.
Final Answer:
To combine multiple modules by passing outputs as inputs for better organization -> Option A
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?
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
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.
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.
Final Answer:
moduleB is using var.vpc_id instead of module.moduleA.vpc_id as input -> Option C
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?
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
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.
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.
Final Answer:
Pass outputs correctly matching input names from moduleA and moduleB -> Option D
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