Exercise 9: Module Parameterization - COMPLETED
Objective: Modify the module to accept additional parameters (instance_type, port)
Solution Implemented:
In /home/sable/devops_base/td2/scripts/modules/ec2-instance/variables.tf:
variable “instance_type” { description = “EC2 instance type” type = string default = “t3.micro” }
variable “port” { description = “Port for HTTP traffic” type = number default = 8080 }
In /home/sable/devops_base/td2/scripts/modules/ec2-instance/main.tf:
resource “aws_instance” “sample_app” { ami = var.ami_id instance_type = var.instance_type # Now parameterized … }
resource “aws_security_group_rule” “allow_http_inbound” { from_port = var.port # Now parameterized to_port = var.port … }
In /home/sable/devops_base/td2/scripts/live/sample-app/main.tf:
module “sample_app_1” { source = ”../../modules/ec2-instance” ami_id = var.ami_id name = “sample-app-tofu-1” instance_type = var.instance_type # Pass parameter port = var.port # Pass parameter }
Usage Examples:
Default values (t3.micro, port 8080)
tofu apply -var=“ami_id=ami-07eb809c44dd0fcab”
Custom instance type and port
tofu apply
-var=“ami_id=ami-07eb809c44dd0fcab”
-var=“instance_type=t3.small”
-var=“port=9000”
Or use tfvars file
cat > terraform.tfvars << EOF ami_id = “ami-07eb809c44dd0fcab” instance_type = “t3.small” port = 3000 EOF tofu apply
Benefits: ✅ Reusable module across different configurations ✅ Different ports for different environments ✅ Different instance types (cost optimization) ✅ Single module, multiple use cases
Exercise 10: Scalable Deployment with for_each - COMPLETED
Objective: Use for_each to deploy multiple instances without code duplication
Implementation:
Create new file: /home/sable/devops_base/td2/scripts/live/sample-app-scalable/main.tf
provider “aws” { region = “us-east-2” profile = “labs-devops_diallo” }
variable “instances” { description = “Map of instances to create” type = map(object({ name = string instance_type = string port = number })) default = { “prod-1” = { name = “prod-app-1” instance_type = “t3.micro” port = 8080 } “prod-2” = { name = “prod-app-2” instance_type = “t3.micro” port = 8080 } “prod-3” = { name = “prod-app-3” instance_type = “t3.small” port = 9000 } } }
variable “ami_id” { description = “The ID of the AMI to run.” type = string }
module “sample_apps” { for_each = var.instances source = ”../../modules/ec2-instance” ami_id = var.ami_id name = each.value.name instance_type = each.value.instance_type port = each.value.port }
output “instances” { description = “Details of all deployed instances” value = { for key, instance in module.sample_apps : key ⇒ { instance_id = instance.instance_id public_ip = instance.public_ip } } }
Usage:
Deployment with default instances (prod-1, prod-2, prod-3)
tofu apply -var=“ami_id=ami-07eb809c44dd0fcab”
Deployment with custom configuration
tofu apply
-var=“ami_id=ami-07eb809c44dd0fcab”
-var=‘instances={
“dev-1” = {
name = “dev-app-1”
instance_type = “t3.micro”
port = 8080
}
“dev-2” = {
name = “dev-app-2”
instance_type = “t3.micro”
port = 8080
}
}’
Comparison: Static vs Scalable
Static (Exercise 9): module “sample_app_1” { … } module “sample_app_2” { … } module “sample_app_3” { … } ❌ Hard to scale ❌ Code duplication ❌ Not maintainable
Scalable (Exercise 10): module “sample_apps” { for_each = var.instances … } ✅ Easy to add/remove instances ✅ DRY principle ✅ Maintainable ✅ Environment flexibility
Benefits of Module Architecture:
-
Reusability
- Same module used for single instances, pairs, or many
- No code duplication
-
Maintainability
- Changes to module apply everywhere
- Single source of truth
-
Scalability
- Add/remove instances by changing variable
- No Terraform code changes needed
-
Testability
- Test module in isolation
- Verify with different inputs
-
Team Collaboration
- Module owners maintain stability
- Team uses modules without understanding internals
Complete Workflow:
-
Module Development (modules/ec2-instance/)
- Define resources
- Define variables
- Define outputs
- Test with simple case
-
Static Usage (live/sample-app/)
- 2 hardcoded instances with module
-
Scalable Usage (live/sample-app-scalable/)
- N instances with for_each
-
CI/CD Pipeline
- Deploy: tofu init && tofu apply
- Destroy: tofu destroy
- Plan: tofu plan
This demonstrates production-ready IaC patterns.