Code Phase
The Code phase is where you write the actual infrastructure code: modules, solutions, and deployments.
Core Concepts
Modules
The smallest reusable unit that defines a cloud resource. Modules enforce strong, opinionated defaults for security and compliance.
# modules/s3/bucket/main.tf
resource "aws_s3_bucket" "this" {
bucket = var.bucket_name
}
resource "aws_s3_bucket_public_access_block" "this" {
bucket = aws_s3_bucket.this.id
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
resource "aws_s3_bucket_versioning" "this" {
bucket = aws_s3_bucket.this.id
versioning_configuration {
status = var.bucket_versioning_status
}
}
Solutions
Opinionated compositions of modules that represent a complete service. Solutions enforce required versions and policies — they should not be entirely configurable.
# solutions/my-app/main.tf
module "app_bucket" {
source = "terrareg.example.com/modules/s3-bucket/aws"
version = "1.1.0"
bucket_name = "${var.environment}-${var.app_name}-data"
bucket_tags = local.tags
}
module "app_database" {
source = "terrareg.example.com/modules/rds-postgres-database/aws"
version = "1.3.0"
instance_identifier = "${var.app_name}-${var.environment}"
engine_version = "16.6" # Enforced by solution
instance_class = var.instance_class
allocated_storage = var.allocated_storage
subnet_group_name = var.subnet_group_name
}
Deployments
Environment-specific definitions that instantiate solutions. A deployment always references a solution and never directly interacts with a module.
# deployments/region-1/production/my-app/terragrunt.hcl
include "root" {
path = find_in_parent_folders("root.hcl")
expose = true
}
terraform {
source = "tfr://terrareg.example.com/solutions/my-app/aws?version=2.1.0"
}
inputs = {
app_name = "my-app"
environment = "production"
business_region = "region-1"
instance_class = "db.r6g.large"
allocated_storage = 500
subnet_group_name = "region-1-production-db-subnet-group"
}
Repository Layout
your-idlc-repo/
├── modules/
│ ├── s3/
│ │ └── bucket/
│ ├── rds/
│ │ ├── postgres-database/
│ │ ├── parameter-group/
│ │ └── alarms/
│ └── eks/
│ ├── cluster/
│ └── karpenter/
├── solutions/
│ ├── my-app/
│ └── my-database/
└── deployments/
├── region-1/
│ ├── stage/
│ ├── production/
└── region-2/
└── production/
Best Practices
- Modules: Small surface area, strong defaults (security, encryption, logging). Inputs are validated; outputs are minimal and purposeful.
- Solutions: Encapsulate service composition. Enforce required versions and policies. Only expose variables that truly vary across services.
- Deployments: One folder per team and environment. Keep them declarative (no business logic). Pin solution/module versions.