$npx -y skills add wshobson/agents --skill terraform-module-libraryBuild reusable Terraform modules for AWS, Azure, GCP, and OCI infrastructure following infrastructure-as-code best practices. Use when creating infrastructure modules, standardizing cloud provisioning, or implementing reusable IaC components.
| 1 | # Terraform Module Library |
| 2 | |
| 3 | Production-ready Terraform module patterns for AWS, Azure, GCP, and OCI infrastructure. |
| 4 | |
| 5 | ## Purpose |
| 6 | |
| 7 | Create reusable, well-tested Terraform modules for common cloud infrastructure patterns across multiple cloud providers. |
| 8 | |
| 9 | ## When to Use |
| 10 | |
| 11 | - Build reusable infrastructure components |
| 12 | - Standardize cloud resource provisioning |
| 13 | - Implement infrastructure as code best practices |
| 14 | - Create multi-cloud compatible modules |
| 15 | - Establish organizational Terraform standards |
| 16 | |
| 17 | ## Module Structure |
| 18 | |
| 19 | ``` |
| 20 | terraform-modules/ |
| 21 | ├── aws/ |
| 22 | │ ├── vpc/ |
| 23 | │ ├── eks/ |
| 24 | │ ├── rds/ |
| 25 | │ └── s3/ |
| 26 | ├── azure/ |
| 27 | │ ├── vnet/ |
| 28 | │ ├── aks/ |
| 29 | │ └── storage/ |
| 30 | ├── gcp/ |
| 31 | │ ├── vpc/ |
| 32 | │ ├── gke/ |
| 33 | │ └── cloud-sql/ |
| 34 | └── oci/ |
| 35 | ├── vcn/ |
| 36 | ├── oke/ |
| 37 | └── object-storage/ |
| 38 | ``` |
| 39 | |
| 40 | ## Standard Module Pattern |
| 41 | |
| 42 | ``` |
| 43 | module-name/ |
| 44 | ├── main.tf # Main resources |
| 45 | ├── variables.tf # Input variables |
| 46 | ├── outputs.tf # Output values |
| 47 | ├── versions.tf # Provider versions |
| 48 | ├── README.md # Documentation |
| 49 | ├── examples/ # Usage examples |
| 50 | │ └── complete/ |
| 51 | │ ├── main.tf |
| 52 | │ └── variables.tf |
| 53 | └── tests/ # Terratest files |
| 54 | └── module_test.go |
| 55 | ``` |
| 56 | |
| 57 | ## AWS VPC Module Example |
| 58 | |
| 59 | **main.tf:** |
| 60 | |
| 61 | ```hcl |
| 62 | resource "aws_vpc" "main" { |
| 63 | cidr_block = var.cidr_block |
| 64 | enable_dns_hostnames = var.enable_dns_hostnames |
| 65 | enable_dns_support = var.enable_dns_support |
| 66 | |
| 67 | tags = merge( |
| 68 | { |
| 69 | Name = var.name |
| 70 | }, |
| 71 | var.tags |
| 72 | ) |
| 73 | } |
| 74 | |
| 75 | resource "aws_subnet" "private" { |
| 76 | count = length(var.private_subnet_cidrs) |
| 77 | vpc_id = aws_vpc.main.id |
| 78 | cidr_block = var.private_subnet_cidrs[count.index] |
| 79 | availability_zone = var.availability_zones[count.index] |
| 80 | |
| 81 | tags = merge( |
| 82 | { |
| 83 | Name = "${var.name}-private-${count.index + 1}" |
| 84 | Tier = "private" |
| 85 | }, |
| 86 | var.tags |
| 87 | ) |
| 88 | } |
| 89 | |
| 90 | resource "aws_internet_gateway" "main" { |
| 91 | count = var.create_internet_gateway ? 1 : 0 |
| 92 | vpc_id = aws_vpc.main.id |
| 93 | |
| 94 | tags = merge( |
| 95 | { |
| 96 | Name = "${var.name}-igw" |
| 97 | }, |
| 98 | var.tags |
| 99 | ) |
| 100 | } |
| 101 | ``` |
| 102 | |
| 103 | **variables.tf:** |
| 104 | |
| 105 | ```hcl |
| 106 | variable "name" { |
| 107 | description = "Name of the VPC" |
| 108 | type = string |
| 109 | } |
| 110 | |
| 111 | variable "cidr_block" { |
| 112 | description = "CIDR block for VPC" |
| 113 | type = string |
| 114 | validation { |
| 115 | condition = can(regex("^([0-9]{1,3}\\.){3}[0-9]{1,3}/[0-9]{1,2}$", var.cidr_block)) |
| 116 | error_message = "CIDR block must be valid IPv4 CIDR notation." |
| 117 | } |
| 118 | } |
| 119 | |
| 120 | variable "availability_zones" { |
| 121 | description = "List of availability zones" |
| 122 | type = list(string) |
| 123 | } |
| 124 | |
| 125 | variable "private_subnet_cidrs" { |
| 126 | description = "CIDR blocks for private subnets" |
| 127 | type = list(string) |
| 128 | default = [] |
| 129 | } |
| 130 | |
| 131 | variable "enable_dns_hostnames" { |
| 132 | description = "Enable DNS hostnames in VPC" |
| 133 | type = bool |
| 134 | default = true |
| 135 | } |
| 136 | |
| 137 | variable "tags" { |
| 138 | description = "Additional tags" |
| 139 | type = map(string) |
| 140 | default = {} |
| 141 | } |
| 142 | ``` |
| 143 | |
| 144 | **outputs.tf:** |
| 145 | |
| 146 | ```hcl |
| 147 | output "vpc_id" { |
| 148 | description = "ID of the VPC" |
| 149 | value = aws_vpc.main.id |
| 150 | } |
| 151 | |
| 152 | output "private_subnet_ids" { |
| 153 | description = "IDs of private subnets" |
| 154 | value = aws_subnet.private[*].id |
| 155 | } |
| 156 | |
| 157 | output "vpc_cidr_block" { |
| 158 | description = "CIDR block of VPC" |
| 159 | value = aws_vpc.main.cidr_block |
| 160 | } |
| 161 | ``` |
| 162 | |
| 163 | ## Best Practices |
| 164 | |
| 165 | 1. **Use semantic versioning** for modules |
| 166 | 2. **Document all variables** with descriptions |
| 167 | 3. **Provide examples** in examples/ directory |
| 168 | 4. **Use validation blocks** for input validation |
| 169 | 5. **Output important attributes** for module composition |
| 170 | 6. **Pin provider versions** in versions.tf |
| 171 | 7. **Use locals** for computed values |
| 172 | 8. **Implement conditional resources** with count/for_each |
| 173 | 9. **Test modules** with Terratest |
| 174 | 10. **Tag all resources** consistently |
| 175 | |
| 176 | **Reference:** See `references/aws-modules.md` and `references/oci-modules.md` |
| 177 | |
| 178 | ## Module Composition |
| 179 | |
| 180 | ```hcl |
| 181 | module "vpc" { |
| 182 | source = "../../modules/aws/vpc" |
| 183 | |
| 184 | name = "production" |
| 185 | cidr_block = "10.0.0.0/16" |
| 186 | availability_zones = ["us-west-2a", "us-west-2b", "us-west-2c"] |
| 187 | |
| 188 | private_subnet_cidrs = [ |
| 189 | "10.0.1.0/24", |
| 190 | "10.0.2.0/24", |
| 191 | "10.0.3.0/24" |
| 192 | ] |
| 193 | |
| 194 | tags = { |
| 195 | Environment = "production" |
| 196 | ManagedBy = "terraform" |
| 197 | } |
| 198 | } |
| 199 | |
| 200 | module "rds" { |
| 201 | source = "../../modules/aws/rds" |
| 202 | |
| 203 | identifier = "production-db" |
| 204 | engine = "postgres" |
| 205 | engine_version = "15.3" |
| 206 | instance_class = "db.t3.large" |
| 207 | |
| 208 | vpc_id = module.vpc.vpc_id |
| 209 | subnet_ids = module.vpc.private_subnet_ids |
| 210 | |
| 211 | tags = { |
| 212 | Environment = "production" |
| 213 | } |
| 214 | } |
| 215 | ``` |
| 216 | |
| 217 | |
| 218 | ## Testing |
| 219 | |
| 220 | ```go |
| 221 | // tests/vpc_test.go |
| 222 | package test |
| 223 | |
| 224 | import ( |
| 225 | "testing" |
| 226 | "github.com/gruntwork-io/terratest/modules/terraform" |
| 227 | "github.com/stretchr/testify/assert" |
| 228 | ) |
| 229 | |
| 230 | func TestVPCModule(t *testing.T) { |
| 231 | terraformOptions := &t |