Rapid Terraform Module Creation Framework
Streamline your workflow with this skill for create and refactor infrastructure modules. Built for Claude Code with best practices and real-world patterns.
Terraform Module Creation Framework
Advanced Terraform module development toolkit for creating reusable, versioned, well-documented infrastructure modules with testing, validation, and registry publishing support.
When to Use This Skill
Choose Terraform Module Creation when:
- Building reusable infrastructure patterns for your organization
- Standardizing resource provisioning across teams
- Creating opinionated modules that enforce security and compliance
- Publishing modules to private or public registries
- Wrapping complex resource configurations into simple interfaces
Consider alternatives when:
- One-off infrastructure — use direct resource blocks
- Need Kubernetes resources — use Helm charts
- Want CDK instead — use AWS CDK constructs or CDKTF
Quick Start
# Activate module creation claude skill activate rapid-terraform-module-creation-framework # Create a module claude "Create a Terraform module for an AWS ECS Fargate service with ALB" # Test a module claude "Add Terratest tests to the ECS module"
Example: Reusable Module Structure
# modules/ecs-service/main.tf resource "aws_ecs_service" "this" { name = var.name cluster = var.cluster_id task_definition = aws_ecs_task_definition.this.arn desired_count = var.desired_count launch_type = "FARGATE" network_configuration { subnets = var.subnet_ids security_groups = [aws_security_group.service.id] assign_public_ip = false } load_balancer { target_group_arn = aws_lb_target_group.this.arn container_name = var.name container_port = var.container_port } lifecycle { ignore_changes = [desired_count] # Allow autoscaling } } # modules/ecs-service/variables.tf variable "name" { type = string description = "Name of the ECS service" validation { condition = can(regex("^[a-z][a-z0-9-]{2,28}[a-z0-9]$", var.name)) error_message = "Name must be 4-30 lowercase alphanumeric characters." } } variable "container_image" { type = string description = "Docker image URI (e.g., 123456.dkr.ecr.us-east-1.amazonaws.com/app:latest)" } variable "container_port" { type = number default = 8080 description = "Port the container listens on" } variable "desired_count" { type = number default = 2 validation { condition = var.desired_count >= 1 && var.desired_count <= 20 error_message = "Desired count must be between 1 and 20." } } # modules/ecs-service/outputs.tf output "service_name" { value = aws_ecs_service.this.name description = "The name of the ECS service" } output "alb_dns_name" { value = aws_lb.this.dns_name description = "DNS name of the Application Load Balancer" }
Core Concepts
Module Design Principles
| Principle | Description | Implementation |
|---|---|---|
| Single Responsibility | Module manages one logical resource group | ECS service + ALB, not entire infrastructure |
| Opinionated Defaults | Secure, production-ready defaults | Encryption on, public access off |
| Configurable Escape Hatches | Allow overriding defaults when needed | Variables with sensible defaults |
| Composability | Modules work together via outputs/inputs | Output IDs for cross-module references |
| Versioning | Semantic versioning for breaking changes | Git tags + changelog |
Module Testing
| Test Level | Tool | Purpose |
|---|---|---|
| Validation | terraform validate | Syntax and type checking |
| Plan | terraform plan | Resource creation verification |
| Integration | Terratest (Go) | Deploy, verify, destroy |
| Compliance | tflint, checkov | Security and best practice rules |
| Documentation | terraform-docs | Auto-generated README |
// Terratest integration test package test import ( "testing" "github.com/gruntwork-io/terratest/modules/terraform" "github.com/stretchr/testify/assert" ) func TestEcsModule(t *testing.T) { t.Parallel() opts := terraform.WithDefaultRetryableErrors(t, &terraform.Options{ TerraformDir: "../modules/ecs-service", Vars: map[string]interface{}{ "name": "test-service", "container_image": "nginx:latest", "desired_count": 1, }, }) defer terraform.Destroy(t, opts) terraform.InitAndApply(t, opts) serviceName := terraform.Output(t, opts, "service_name") assert.Equal(t, "test-service", serviceName) }
Configuration
| Parameter | Description | Default |
|---|---|---|
module_source | Module source: local, git, registry | local |
versioning | Semantic versioning strategy | semver |
testing | Testing framework: terratest, tftest | terratest |
docs_generator | Documentation: terraform-docs, manual | terraform-docs |
compliance_scanner | Security scanning: checkov, tflint, tfsec | checkov |
registry | Publishing target: hashicorp, private, none | none |
Best Practices
-
Design the module interface (variables + outputs) before implementing resources — Write the
variables.tfandoutputs.tffirst to design the consumer experience. This ensures the module API is intuitive and complete before you get lost in resource implementation details. -
Use variable validation blocks for all constrained inputs — Validate CIDR ranges, naming conventions, enum values, and size limits in variable blocks. Early validation produces clear error messages at plan time instead of cryptic API errors at apply time.
-
Provide secure defaults that can be overridden — Default to encryption enabled, public access disabled, and minimum necessary permissions. Allow overrides via variables for development environments, but make the production-safe path the easy path.
-
Version modules with semantic versioning and changelogs — Use git tags (v1.0.0, v1.1.0, v2.0.0) for module versions. Document breaking changes in CHANGELOG.md. Pin module versions in consumer code:
source = "git::...?ref=v1.2.0". -
Generate documentation automatically with terraform-docs — Run
terraform-docs markdown . > README.mdto generate accurate input/output documentation. Add a pre-commit hook to regenerate docs on change, ensuring documentation never drifts from code.
Common Issues
Module changes break consumers who pinned to a branch instead of a tag. Always use tagged releases for module references, not branch names. Branch references track the latest commit and can break unexpectedly. Tags are immutable and provide predictable behavior.
Module outputs don't expose enough information for downstream modules. Output every resource attribute that downstream modules might need. Use output "this" to export the entire resource object when the module wraps a single resource. It's easier to remove unused outputs than to add missing ones later.
Testing modules is slow because each test deploys real infrastructure. Use terraform plan tests for syntax validation (fast, free). Reserve Terratest integration tests for CI pipelines with dedicated test accounts. Implement test fixtures that share long-lived infrastructure (VPCs, clusters) across multiple module tests.
Reviews
No reviews yet. Be the first to review this template!
Similar Templates
Full-Stack Code Reviewer
Comprehensive code review skill that checks for security vulnerabilities, performance issues, accessibility, and best practices across frontend and backend code.
Test Suite Generator
Generates comprehensive test suites with unit tests, integration tests, and edge cases. Supports Jest, Vitest, Pytest, and Go testing.
Pro Architecture Workspace
Battle-tested skill for architectural, decision, making, framework. Includes structured workflows, validation checks, and reusable patterns for development.