- name
- terraform-generator
- description
- Create, generate, write, or scaffold Terraform .tf HCL — resources, modules, providers, variables, outputs. Use when this capability is needed.
- metadata
- {"author":"akin-ozer"}
# Terraform Generator
## Overview
This skill enables the generation of production-ready Terraform configurations following best practices and current standards. Automatically integrates validation and documentation lookup for custom providers and modules.
## Critical Requirements Checklist
**STOP: You MUST complete ALL steps in order. Do NOT skip any REQUIRED step.**
| Step | Action | Required |
|------|--------|----------|
| 1 | Understand requirements (providers, resources, modules) | ✅ REQUIRED |
| 2 | Check for custom providers/modules and lookup documentation | ✅ REQUIRED |
| 3 | Consult reference files before generation | ✅ REQUIRED |
| 4 | Generate Terraform files with ALL best practices | ✅ REQUIRED |
| 5 | Include data sources for dynamic values (region, account, AMIs) | ✅ REQUIRED |
| 6 | Add lifecycle rules on critical resources (KMS, databases) | ✅ REQUIRED |
| 7 | Invoke `Skill(devops-skills:terraform-validator)` | ✅ REQUIRED |
| 8 | **FIX all validation/security failures and RE-VALIDATE** | ✅ REQUIRED |
| 9 | Provide usage instructions (files, next steps, security) | ✅ REQUIRED |
> **IMPORTANT:** If validation fails (terraform validate OR security scan), you MUST fix the issues and re-run validation until ALL checks pass. Do NOT proceed to Step 9 with failing checks.
## Core Workflow
When generating Terraform configurations, follow this workflow:
### Step 1: Understand Requirements
Analyze the user's request to determine:
- What infrastructure resources need to be created
- Which Terraform providers are required (AWS, Azure, GCP, custom, etc.)
- Whether any modules are being used (official, community, or custom)
- Version constraints for providers and modules
- Variable inputs and outputs needed
- State backend configuration (local, S3, remote, etc.)
### Step 2: Check for Custom Providers/Modules
Before generating configurations, identify if custom or third-party providers/modules are involved:
**Standard providers** (no lookup needed):
- hashicorp/aws
- hashicorp/azurerm
- hashicorp/google
- hashicorp/kubernetes
- Other official HashiCorp providers
**Custom/third-party providers/modules** (require documentation lookup):
- Third-party providers (e.g., datadog/datadog, mongodb/mongodbatlas)
- Custom modules from Terraform Registry
- Private or company-specific modules
- Community modules
**When custom providers/modules are detected:**
1. Use WebSearch to find version-specific documentation:
```
Search query format: "[provider/module name] terraform [version] documentation [specific resource]"
Example: "datadog terraform provider v3.30 monitor resource documentation"
Example: "terraform-aws-modules vpc version 5.0 documentation"
```
2. Focus searches on:
- Official documentation (registry.terraform.io, provider websites)
- Required and optional arguments
- Attribute references
- Example usage
- Version compatibility notes
3. If Context7 MCP is available and the provider/module is supported, use it as an alternative:
```
mcp__context7__resolve-library-id → mcp__context7__query-docs
```
### Step 2.5: Consult Reference Files (REQUIRED)
Before generating configuration, you MUST consult reference files using this matrix:
| Reference | Requirement | Read When |
|-----------|-------------|-----------|
| `terraform_best_practices.md` | REQUIRED | Always - contains baseline required patterns |
| `provider_examples.md` | REQUIRED | Any AWS, Azure, GCP, or Kubernetes resource generation |
| `common_patterns.md` | OPTIONAL by default, REQUIRED for complex requests | Multi-environment, workspace, composition, DR, or conditional patterns |
Open references by path:
```
devops-skills-plugin/skills/terraform-generator/references/terraform_best_practices.md
devops-skills-plugin/skills/terraform-generator/references/provider_examples.md
devops-skills-plugin/skills/terraform-generator/references/common_patterns.md
```
### Step 3: Generate Terraform Configuration
Generate HCL files following best practices:
**File Organization:**
```
terraform-project/
├── main.tf # Primary resource definitions
├── variables.tf # Input variable declarations
├── outputs.tf # Output value declarations
├── versions.tf # Provider version constraints
├── terraform.tfvars # Variable values (optional, for examples)
└── backend.tf # Backend configuration (optional)
```
**Best Practices to Follow:**
1. **Provider Configuration:**
```hcl
terraform {
required_version = ">= 1.10, < 2.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 6.0" # Major pin; verify exact current version when needed
}
}
}
provider "aws" {
region = var.aws_region
}
```
2. **Resource Naming:**
- Use descriptive resource names
- Follow snake_case convention
- Include resource type in name when helpful
```hcl
resource "aws_instance" "web_server" {
# ...
}
```
3. **Variable Declarations:**
```hcl
variable "instance_type" {
description = "EC2 instance type for web servers"
type = string
default = "t3.micro"
validation {
condition = contains(["t3.micro", "t3.small", "t3.medium"], var.instance_type)
error_message = "Instance type must be t3.micro, t3.small, or t3.medium."
}
}
```
4. **Output Values:**
```hcl
output "instance_public_ip" {
description = "Public IP address of the web server"
value = aws_instance.web_server.public_ip
}
```
5. **Use Data Sources for References:**
```hcl
data "aws_ami" "ubuntu" {
most_recent = true
owners = ["099720109477"] # Canonical
filter {
name = "name"
values = ["ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*"]
}
}
```
6. **Module Usage:**
```hcl
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "5.0.0"
name = "my-vpc"
cidr = "10.0.0.0/16"
azs = ["us-east-1a", "us-east-1b"]
private_subnets = ["10.0.1.0/24", "10.0.2.0/24"]
public_subnets = ["10.0.101.0/24", "10.0.102.0/24"]
}
```
7. **Use locals for Computed Values:**
```hcl
locals {
common_tags = {
Environment = var.environment
ManagedBy = "Terraform"
Project = var.project_name
}
}
```
8. **Lifecycle Rules When Appropriate:**
```hcl
resource "aws_instance" "example" {
# ...
lifecycle {
create_before_destroy = true
prevent_destroy = true
ignore_changes = [tags]
}
}
```
9. **Dynamic Blocks for Repeated Configuration:**
```hcl
resource "aws_security_group" "example" {
# ...
dynamic "ingress" {
for_each = var.ingress_rules
content {
from_port = ingress.value.from_port
to_port = ingress.value.to_port
protocol = ingress.value.protocol
cidr_blocks = ingress.value.cidr_blocks
}
}
}
```
10. **Comments and Documentation:**
- Add comments explaining complex logic
- Document why certain values are used
- Include examples in variable descriptions
**Security Best Practices:**
- Never hardcode sensitive values (use variables)
- Use data sources for AMIs and other dynamic values
- Implement least-privilege IAM policies
- Enable encryption by default
- Use secure backend configurations
### Required: Data Sources for Dynamic Values (Provider-Aware)
You MUST include provider-appropriate data lookups for dynamic infrastructure values. Do NOT hardcode cloud/account/region/image IDs.
| Provider | Required Dynamic Context | Typical Data Sources |
|----------|--------------------------|----------------------|
| AWS | Region/account/AZ/image IDs | `aws_region`, `aws_caller_identity`, `aws_availability_zones`, `aws_ami` |
| Azure | Tenant/subscription/client context | `azurerm_client_config`, `azurerm_subscription` |
| GCP | Project/client context/zone discovery | `google_client_config`, `google_compute_zones`, `google_compute_image` |
| Kubernetes | Cluster endpoint/auth from trusted source | Use module outputs or cloud data sources; avoid hardcoded tokens/endpoints |
```hcl
# AWS dynamic context
data "aws_region" "current" {}
data "aws_caller_identity" "current" {}
# Azure dynamic context
data "azurerm_client_config" "current" {}
data "azurerm_subscription" "current" {}
# GCP dynamic context
data "google_client_config" "current" {}
```
### Required: Lifecycle and Deletion Safeguards (Provider-Aware)
You MUST protect stateful and critical resources from accidental destruction/deletion using both Terraform lifecycle and provider-native safeguards.
| Provider | Critical Resource Classes | Required Protection Mechanism |
|----------|---------------------------|-------------------------------|
| AWS | KMS, RDS, S3 data buckets, DynamoDB, ElastiCache, secrets | `lifecycle { prevent_destroy = true }` and service-specific deletion protection where supported |
| Azure | Key Vaults, SQL, Storage, stateful compute | `prevent_destroy` where appropriate plus provider feature flags/resource deletion protection |
| GCP | Cloud SQL, GKE, storage, stateful compute | `prevent_destroy` and resource-level `deletion_protection = true` where supported |
| Kubernetes | Stateful workloads and persistent data | Avoid destructive replacement patterns and protect backing cloud resources |
```hcl
resource "aws_db_instance" "main" {
# ...
deletion_protection = true
lifecycle {
prevent_destroy = true
}
}
resource "google_sql_database_instance" "main" {
# ...
deletion_protection = true
}
```
### Required: Object Storage Lifecycle Safeguards
When using AWS S3 lifecycle configuration, ALWAYS include a rule to abort incomplete multipart uploads:
```hcl
resource "aws_s3_bucket_lifecycle_configuration" "main" {
bucket = aws_s3_bucket.main.id
# REQUIRED: Abort incomplete multipart uploads to prevent storage costs
rule {
id = "abort-incomplete-uploads"
status = "Enabled"
# Filter applies to all objects (empty filter = all objects)
filter {}
abort_incomplete_multipart_upload {
days_after_initiation = 7
}
}
# Other lifecycle rules (e.g., transition to IA)
rule {
id = "transition-to-ia"
status = "Enabled"
filter {
prefix = "" # Apply to all objects
}
transition {
days = 90
storage_class = "STANDARD_IA"
}
noncurrent_version_transition {
noncurrent_days = 30
storage_class = "STANDARD_IA"
}
noncurrent_version_expiration {
noncurrent_days = 365
}
}
}
```
> **Why?** Incomplete multipart uploads consume storage and incur costs. Checkov check `CKV_AWS_300` enforces this for AWS.
>
> For Azure/GCP object storage, add equivalent lifecycle/retention rules for stale objects and old versions.
### Step 4: Validate Generated Configuration (REQUIRED)
After generating Terraform files, ALWAYS validate them using the devops-skills:terraform-validator skill:
```
Invoke: Skill(devops-skills:terraform-validator)
```
The devops-skills:terraform-validator skill will:
1. Check HCL syntax with `terraform fmt -check`
2. Initialize the configuration with `terraform init`
3. Validate the configuration with `terraform validate`
4. Run security scan with Checkov
5. Perform dry-run testing (if requested) with `terraform plan`
**CRITICAL: Fix-and-Revalidate Loop**
If ANY validation or security check fails, you MUST:
1. **Review the error** - Understand what failed and why
2. **Fix the issue** - Edit the generated file to resolve the problem
3. **Re-run validation** - Invoke `Skill(devops-skills:terraform-validator)` again
4. **Repeat until ALL checks pass** - Do NOT proceed with failing checks
```
┌─────────────────────────────────────────────────────────┐
│ VALIDATION FAILED? │
│ │
│ ┌─────────┐ ┌─────────┐ ┌─────────────────────┐ │
│ │ Fix │───▶│ Re-run │───▶│ All checks pass? │ │
│ │ Issue │ │ Skill │ │ YES → Step 5 │ │
│ └─────────┘ └─────────┘ │ NO → Loop back │ │
│ ▲ └─────────────────────┘ │
│ │ │ │
│ └────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
```
**Common validation failures to fix:**
| Check | Issue | Fix |
|-------|-------|-----|
| `CKV_AWS_300` | Missing abort multipart upload | Add `abort_incomplete_multipart_upload` rule |
| `CKV_AWS_24` | SSH open to 0.0.0.0/0 | Restrict to specific CIDR |
| `CKV_AWS_16` | RDS encryption disabled | Add `storage_encrypted = true` |
| `terraform validate` | Invalid resource argument | Check provider documentation |
**If custom providers are detected during validation:**
- The devops-skills:terraform-validator skill will automatically fetch documentation
- Use the fetched documentation to fix any issues
### Step 5: Provide Usage Instructions (REQUIRED)
After successful generation and validation with ALL checks passing, you MUST provide the user with:
**Required Output Format:**
```markdown
## Generated Files
| File | Description |
|------|-------------|
| `<actual-file-path>` | What was generated in that file |
Only list files that were actually generated for this request. Do not include placeholder paths or files that do not exist.
## Next Steps
1. Review and customize `terraform.tfvars` with your values
2. Initialize Terraform:
```bash
View on GitHub