Module 8, Modules
What is a Module
A module is a directory of Terraform files used together. Every Terraform configuration IS a module (the root module). When you call another module, it becomes a child module.
finpay-infrastructure/
├── main.tf ← root module
├── variables.tf
├── outputs.tf
└── modules/
├── networking/ ← child module
│ ├── main.tf
│ ├── variables.tf
│ └── outputs.tf
└── database/ ← child module
├── main.tf
├── variables.tf
└── outputs.tf
Creating a Module
# modules/s3-bucket/main.tf
resource "aws_s3_bucket" "this" {
bucket = var.bucket_name
tags = var.tags
}
resource "aws_s3_bucket_versioning" "this" {
bucket = aws_s3_bucket.this.id
versioning_configuration {
status = var.versioning_enabled ? "Enabled" : "Disabled"
}
}
# modules/s3-bucket/variables.tf
variable "bucket_name" { type = string }
variable "versioning_enabled" { type = bool; default = true }
variable "tags" { type = map(string); default = {} }
# modules/s3-bucket/outputs.tf
output "bucket_arn" { value = aws_s3_bucket.this.arn }
output "bucket_name" { value = aws_s3_bucket.this.id }
Calling a Module
# root main.tf
module "artifacts_bucket" {
source = "./modules/s3-bucket"
bucket_name = "finpay-artifacts-${var.environment}"
versioning_enabled = true
tags = {
Environment = var.environment
Purpose = "pipeline-artifacts"
}
}
module "logs_bucket" {
source = "./modules/s3-bucket"
bucket_name = "finpay-logs-${var.environment}"
versioning_enabled = false
tags = { Environment = var.environment }
}
# Access module outputs
output "artifacts_arn" {
value = module.artifacts_bucket.bucket_arn
}
tip
Run terraform init after adding any new module source, Terraform needs to download or resolve it.
Public Registry Modules
# Use a community-maintained VPC module from the Terraform Registry
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "~> 5.0"
name = "finpay-vpc"
cidr = "10.0.0.0/16"
azs = ["us-east-1a", "us-east-1b", "us-east-1c"]
private_subnets = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"]
public_subnets = ["10.0.101.0/24", "10.0.102.0/24", "10.0.103.0/24"]
enable_nat_gateway = true
}
Knowledge Check
- What command must be run after adding a new module source?
- How do you reference an output from a child module in the root config?
- What is the difference between
source = "./modules/networking"andsource = "terraform-aws-modules/vpc/aws"? - True or False: A module can contain other modules.
- What is the purpose of module outputs?
- Why would you wrap resources in a module even for a solo project?
Exam Mapping
- HashiCorp Associate Obj 4: Use Terraform outside of core workflow
- HashiCorp Associate Obj 5: Interact with Terraform modules (10-15% of exam)