Add Terraform Module
Scaffold a new Terraform module following project conventions.
Arguments
{module-name}— Name of the module (required, e.g.,redis,service-bus,postgresql){description}— What this module provisions (optional)
Configuration
Read cloudstack.json from the project root at the start of execution. Extract:
TF_PATH=infrastructure.terraformPath(default:infra/terraform/modules)TG_PATH=infrastructure.terragruntPath(default:infra/terragrunt)IAC_WRAPPER=infrastructure.iacWrapper(default:none)CLOUD=infrastructure.cloud(default:azure)
If cloudstack.json does not exist, auto-detect by scanning the project structure.
Process
Read existing modules in
{TF_PATH}/to follow established patterns.Create the module directory:
{TF_PATH}/{module-name}/
├── variables.tf
├── main.tf
├── outputs.tf
- variables.tf — Always include these standard variables:
variable "environment" {
description = "Environment name (e.g. dev, staging, prod)"
type = string
}
variable "location" {
description = "Cloud region (e.g. westeurope, us-east-1)"
type = string
}
variable "project" {
description = "Project prefix for resource naming"
type = string
}
variable "tags" {
description = "Common tags applied to all resources"
type = map(string)
default = {}
}
Add module-specific variables after the standard ones.
- main.tf — Follow the naming convention from existing modules. Derive a location short code from the region (e.g.,
westeurope->weu,us-east-1->use1):
locals {
location_short = # derive from var.location or use a lookup map
name = "${var.project}-{resource-abbrev}-${var.environment}-${local.location_short}"
}
Scan existing modules to discover the project's established naming convention and location short mapping. Use that pattern.
outputs.tf — Export
name,id, and any connection strings or keys needed by downstream modules.IaC Wrapper Wiring (conditional on
IAC_WRAPPER):If
IAC_WRAPPER=terragrunt: Create Terragrunt wiring for the dev environment:{TG_PATH}/dev/{module-name}/ └── terragrunt.hclWith content:
include "root" { path = find_in_parent_folders() } terraform { source = "../../../terraform/modules/{module-name}" } dependency "resource_group" { config_path = "../resource-group" } inputs = { resource_group_name = dependency.resource_group.outputs.name }Adjust the
sourcepath to be the correct relative path from{TG_PATH}/dev/{module-name}/to{TF_PATH}/{module-name}. Add additional dependencies based on what the module needs.If
IAC_WRAPPER=none: Skip wrapper wiring. Note that the user can runterraform plandirectly from the module directory.
Output
After scaffolding, report:
## Scaffolded: {module-name} Terraform module
Files created:
- `{TF_PATH}/{module-name}/variables.tf`
- `{TF_PATH}/{module-name}/main.tf`
- `{TF_PATH}/{module-name}/outputs.tf`
- `{TG_PATH}/dev/{module-name}/terragrunt.hcl` (if IAC_WRAPPER = terragrunt)
Next: Add resource definitions in `main.tf`, then run `/infra-lint` to validate.
Error Handling
- Module directory already exists: Warn the user and ask whether to overwrite or extend.
- Terraform not installed: Suggest installing with
brew install terraform. - IaC wrapper root config not found: If using Terragrunt, check that
{TG_PATH}/terragrunt.hclexists as the root config.
After Scaffolding
Remind to:
- Add module-specific resource definitions in
main.tf - Add any needed dependencies in the wrapper config (if applicable)
- Run
/infra-lintto validate