---
title: "Terraform Generator"
description: "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."
type: skill
canonical_url: https://claudary.paisolsolutions.com/skills/skill-108
source: "Claudary"
difficulty: intermediate
author: "Claude Code Knowledge Pack"
date: 2026-07-10T11:43:41.027Z
license: CC-BY-4.0
attribution: "Terraform Generator — Claudary (https://claudary.paisolsolutions.com/skills/skill-108)"
---

# Terraform Generator
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.

## Overview

---
name: terraform-generator
description: Create, generate, write, or scaffold Terraform .tf HCL — resources, modules, providers, variables, outputs.
---

# 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
   terraform init
   ```
3. Review the execution plan:
   ```bash
   terraform plan
   ```
4. Apply the configuration:
   ```bash
   terraform apply
   ```

## Customization Notes

- [ ] Update `variable_name` in terraform.tfvars
- [ ] Configure backend in backend.tf for remote state
- [ ] Adjust resource names/tags as needed

## Security Reminders

⚠️ Before applying:
- Review IAM policies and permissions
- Ensure sensitive values are NOT committed to version control
- Configure state backend with encryption enabled
- Set up state locking for team collaboration
```

> **IMPORTANT:** Do NOT skip Step 5. The user needs actionable guidance on how to use the generated configuration.

## Common Generation Patterns

### Pattern 1: Simple Resource Creation

User request: "Create an AWS S3 bucket with versioning"

Generated files:
- `main.tf` - S3 bucket resource with versioning enabled
- `variables.tf` - Bucket name, tags variables
- `outputs.tf` - Bucket ARN and name outputs
- `versions.tf` - AWS provider version constraints

### Pattern 2: Module-Based Infrastructure

User request: "Set up a VPC u

---

Source: [Claudary](https://claudary.paisolsolutions.com/skills/skill-108) · https://claudary.paisolsolutions.com
