R

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.

SkillCommunitydevopsv1.0.0MIT
0 views0 copies

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

PrincipleDescriptionImplementation
Single ResponsibilityModule manages one logical resource groupECS service + ALB, not entire infrastructure
Opinionated DefaultsSecure, production-ready defaultsEncryption on, public access off
Configurable Escape HatchesAllow overriding defaults when neededVariables with sensible defaults
ComposabilityModules work together via outputs/inputsOutput IDs for cross-module references
VersioningSemantic versioning for breaking changesGit tags + changelog

Module Testing

Test LevelToolPurpose
Validationterraform validateSyntax and type checking
Planterraform planResource creation verification
IntegrationTerratest (Go)Deploy, verify, destroy
Compliancetflint, checkovSecurity and best practice rules
Documentationterraform-docsAuto-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

ParameterDescriptionDefault
module_sourceModule source: local, git, registrylocal
versioningSemantic versioning strategysemver
testingTesting framework: terratest, tftestterratest
docs_generatorDocumentation: terraform-docs, manualterraform-docs
compliance_scannerSecurity scanning: checkov, tflint, tfseccheckov
registryPublishing target: hashicorp, private, nonenone

Best Practices

  1. Design the module interface (variables + outputs) before implementing resources — Write the variables.tf and outputs.tf first to design the consumer experience. This ensures the module API is intuitive and complete before you get lost in resource implementation details.

  2. 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.

  3. 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.

  4. 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".

  5. Generate documentation automatically with terraform-docs — Run terraform-docs markdown . > README.md to 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.

Community

Reviews

Write a review

No reviews yet. Be the first to review this template!

Similar Templates