Implementing Terraform Modules
Plugin: TSH Platform Engineering
Invoke: /tsh-platform-engineering:implementing-terraform-modules, or loaded automatically when a request matches its description
Used by: devops-engineer, infrastructure-auditor. Also named by the cloud plugin skills implementing-aws-terraform, implementing-gcp-terraform and implementing-azure-terraform as the home of generic Terraform mechanics.
Treats a module as an interface before it is a set of resources: the variables, outputs and version constraints are what every consumer inherits. This is the module-structure layer, loaded alongside the cloud provider's own resource patterns and not instead of them.
Key Areas
| Area | Coverage |
|---|---|
| Precedence | Reads the shared context file (sections 2 and 3: dialect and pinned versions). A *.plan.md Technical Context is the primary source when one exists. The project's existing module conventions outrank everything in the skill; a second convention introduced alongside the first is a finding. |
| Module interface | Semantic versioning on published modules. Every variable typed and described, with a validation block where a bad value is expensive. Every attribute a consumer could need exported as an output. locals for computed values, count or for_each for conditional and repeated resources, and an examples/complete/ that actually runs. |
| Module layout | main.tf, variables.tf, outputs.tf, versions.tf, README.md, examples/complete/ and tests/module_test.go. A shared module library is grouped by provider, then by component. |
| State and providers | Remote state with locking before anything is applied. Provider versions pinned in versions.tf with the lock file committed. Starting-point constraints are aws ~> 6.0, azurerm ~> 4.0 and google ~> 5.0, to be verified against the project's pins with context7. |
| Terraform or Terragrunt | Plain Terraform for a single environment or region, two or three environments in one region, or any existing project not already on Terragrunt. Terragrunt for four or more environments, multi-region, a monorepo of independent stacks, strict environment parity, multi-account AWS, or greenfield with known growth. Never migrate mid-project as a side effect of another change. |
| Testing | Terratest with examples/complete/ as the fixture and tests/module_test.go running InitAndApply with a deferred Destroy. Always t.Parallel(), terraform.WithDefaultRetryableErrors, a fixture path from runtime.Caller(0), cost-reducing flags, a plan-only variant for pull requests, a dedicated test account and -timeout 30m in CI. Assertions target the module's interface, not generated resource names. |
| Cost and tags | A cost estimate for new resources, opening with ⚠️ FINOPS ALERT: High Cost Impact if projected spend rises more than 10%. The project's mandatory tags on every taggable resource, merged so consumers can add their own. |
| Safety | Never apply, destroy or -auto-approve without explicit authorization for that specific action; apply instructions are delivered instead. No secrets in variable defaults or committed .tfvars. No manual console changes. |
How it works
- Discover the dialect, provider versions, state backend and environment layout from the shared context file and the plan's Technical Context.
- Confirm state. A remote backend with locking comes first; if it is missing, that is the first change.
- Choose Terraform or Terragrunt using the decision criteria above.
- Look up current syntax with
context7for the pinned provider version. - Write the module to the standard layout, loading the cloud-specific reference for resource patterns.
- Validate with
terraform fmt -check,terraform validateandterraform plan -out=tfplan, plustflint, andtfsecorcheckovwhere the project has them. - Estimate cost for new resources.
- Deliver apply instructions without applying.
The output is a Terraform Implementation Summary: current state, proposed configuration, a variables table, state backend, cost estimate, apply instructions and files changed.
References
| Reference | Load when |
|---|---|
module-structure.md | Creating a module or reviewing its shape. Covers the standard layout and a worked AWS VPC module. |
terragrunt.md | More than three environments, multi-region, multi-account, or terragrunt.hcl present. Covers the Terragrunt layout (root terragrunt.hcl, _envcommon/, env.hcl) and its cautions: run-all apply applies everything it resolves, and dependency blocks need foundational stacks applied first. |
testing-modules.md | Adding or reviewing module tests. |
Cloud-specific patterns live elsewhere
Resource families, service defaults and anti-patterns for each provider are in the cloud plugin's own skill: implementing-aws-terraform in tsh-stack-aws, implementing-gcp-terraform in tsh-stack-gcp, and implementing-azure-terraform in tsh-stack-azure. Use them where the repository's cloud plugin is installed.
Related skills
- Implementing CI/CD Pipelines - running plan and apply safely in a pipeline.
- Managing Secrets - credentials and state hygiene.
- Optimizing Cloud Cost - sizing and pricing model.
- Designing Multi-Cloud Architecture - service selection before provisioning.