Skill v1.0.0
currentAutomated scan91/100version: "1.0.0" 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:
- 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" ``
- Focus searches on:
- Official documentation (registry.terraform.io, provider websites)
- Required and optional arguments
- Attribute references
- Example usage
- Version compatibility notes
- 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.mddevops-skills-plugin/skills/terraform-generator/references/provider_examples.mddevops-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:
- 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 } ```
- Resource Naming:
- Use descriptive resource names
- Follow snake_case convention
- Include resource type in name when helpful
``hcl resource "aws_instance" "web_server" { # ... } ``
- 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." } } ```
- Output Values:
``hcl output "instance_public_ip" { description = "Public IP address of the web server" value = aws_instance.web_server.public_ip } ``
- 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-*"] } } ```
- 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"] } ```
- Use locals for Computed Values:
``hcl locals { common_tags = { Environment = var.environment ManagedBy = "Terraform" Project = var.project_name } } ``
- Lifecycle Rules When Appropriate:
```hcl resource "aws_instance" "example" { # ...
lifecycle { create_before_destroy = true prevent_destroy = true ignore_changes = [tags] } } ```
- 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 } } } ```
- 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 |
# AWS dynamic contextdata "aws_region" "current" {}data "aws_caller_identity" "current" {}# Azure dynamic contextdata "azurerm_client_config" "current" {}data "azurerm_subscription" "current" {}# GCP dynamic contextdata "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 |
resource "aws_db_instance" "main" {# ...deletion_protection = truelifecycle {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:
resource "aws_s3_bucket_lifecycle_configuration" "main" {bucket = aws_s3_bucket.main.id# REQUIRED: Abort incomplete multipart uploads to prevent storage costsrule {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 = 90storage_class = "STANDARD_IA"}noncurrent_version_transition {noncurrent_days = 30storage_class = "STANDARD_IA"}noncurrent_version_expiration {noncurrent_days = 365}}}
Why? Incomplete multipart uploads consume storage and incur costs. Checkov checkCKV_AWS_300enforces 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:
- Check HCL syntax with
terraform fmt -check - Initialize the configuration with
terraform init - Validate the configuration with
terraform validate - Run security scan with Checkov
- Perform dry-run testing (if requested) with
terraform plan
CRITICAL: Fix-and-Revalidate Loop
If ANY validation or security check fails, you MUST:
- Review the error - Understand what failed and why
- Fix the issue - Edit the generated file to resolve the problem
- Re-run validation - Invoke
Skill(devops-skills:terraform-validator)again - 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:
## 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 Steps1.Review and customize `terraform.tfvars` with your values2.Initialize Terraform:```bashterraform init```3.Review the execution plan:```bashterraform plan```4.Apply the configuration:```bashterraform 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 enabledvariables.tf- Bucket name, tags variablesoutputs.tf- Bucket ARN and name outputsversions.tf- AWS provider version constraints
Pattern 2: Module-Based Infrastructure
User request: "Set up a VPC using the official AWS VPC module"
Actions:
- Identify module: terraform-aws-modules/vpc/aws
- Web search for latest version and documentation
- Generate configuration using module with appropriate inputs
- Validate with devops-skills:terraform-validator
Pattern 3: Multi-Provider Configuration
User request: "Create infrastructure across AWS and Datadog"
Actions:
- Identify standard provider (AWS) and custom provider (Datadog)
- Web search for Datadog provider documentation with version
- Generate configuration with both providers properly configured
- Ensure provider aliases if needed
- Validate with devops-skills:terraform-validator
Pattern 4: Complex Resource with Dependencies
User request: "Create an ECS cluster with ALB and auto-scaling"
Generated structure:
- Multiple resource blocks with proper dependencies
- Data sources for AMIs, availability zones, etc.
- Local values for computed configurations
- Comprehensive variables and outputs
- Proper dependency management using implicit references
Error Handling
Common Issues and Solutions:
- Provider Not Found:
- Ensure provider is listed in
required_providersblock - Verify source address format:
namespace/name - Check version constraint syntax
- Invalid Resource Arguments:
- Refer to web search results for custom providers
- Check for required vs optional arguments
- Verify attribute value types (string, number, bool, list, map)
- Circular Dependencies:
- Review resource references
- Use
depends_onexplicit dependencies if needed - Consider breaking into separate modules
- Validation Failures:
- Run devops-skills:terraform-validator skill to get detailed errors
- Fix issues one at a time
- Re-validate after each fix
Version Awareness
Always consider version compatibility:
- Terraform Version:
- Use
required_versionconstraint with both lower and upper bounds - If generated configuration includes write-only arguments (
*_wo): userequired_version = ">= 1.11, < 2.0". - Else if it uses ephemeral constructs (
ephemeralblocks, ephemeral variables/outputs) without write-only arguments: userequired_version = ">= 1.10, < 2.0". - Else use the project baseline (default
>= 1.8, < 2.0unless repository policy requires newer). - Use
>= 1.14, < 2.0for latest features (actions, query command) - Document any version-specific features used (see below)
- Provider Version Policy (canonical):
- Pin provider major versions with
~>constraints (for example~> 6.0,~> 4.0,~> 7.0). - Do not claim "latest" version unless verified online during the current run.
- Keep cross-provider guidance consistent:
- AWS family: major-pin policy (for example
~> 6.0) - AzureRM: major-pin policy (for example
~> 4.0) - Google: major-pin policy (for example
~> 7.0) - Kubernetes: major/minor pin based on target cluster/provider compatibility
- Use the same provider/version language in
SKILL.md,references/terraform_best_practices.md, and templateassets/minimal-project/versions.tf.
- Module Versions:
- Always pin module versions
- Review module documentation for version compatibility
- Test module updates in non-production first
Required Version Decision Table
| Generated Output Contains | Required Version to Emit | |
|---|---|---|
Any write-only argument (*_wo) | >= 1.11, < 2.0 | |
| Ephemeral constructs only (no write-only) | >= 1.10, < 2.0 | |
| Neither write-only nor ephemeral | Project baseline (default >= 1.8, < 2.0) |
Feature-Gating Examples
# Positive: write-only usage requires Terraform 1.11+terraform {required_version = ">= 1.11, < 2.0"}ephemeral "random_password" "db_password" {length = 16}resource "aws_db_instance" "main" {identifier = "mydb"instance_class = "db.t3.micro"allocated_storage = 20engine = "postgres"username = "admin"skip_final_snapshot = truepassword_wo = ephemeral.random_password.db_password.resultpassword_wo_version = 1}
# Negative: reject this pattern (write-only with Terraform 1.10)terraform {required_version = ">= 1.10, < 2.0"}resource "aws_db_instance" "invalid" {password_wo = "do-not-generate-this"}
Terraform Version Feature Matrix
| Feature | Minimum Version | |
|---|---|---|
terraform_data resource | 1.4+ | |
import {} blocks | 1.5+ | |
check {} blocks | 1.5+ | |
Native testing (.tftest.hcl) | 1.6+ | |
| Test mocking | 1.7+ | |
removed {} blocks | 1.7+ | |
| Provider-defined functions | 1.8+ | |
| Cross-type refactoring | 1.8+ | |
| Enhanced variable validations | 1.9+ | |
templatestring function | 1.9+ | |
| Ephemeral resources | 1.10+ | |
| Write-only arguments | 1.11+ | |
| S3 native state locking | 1.11+ | |
Import blocks with for_each | 1.12+ | |
| Actions block | 1.14+ | |
List resources (tfquery.hcl) | 1.14+ | |
terraform query command | 1.14+ |
Modern Terraform Features (1.8+)
Provider-Defined Functions (Terraform 1.8+)
Provider-defined functions extend Terraform's built-in functions with provider-specific logic.
Syntax: provider::<provider_name>::<function_name>(arguments)
# AWS Provider Functions (v5.40+)locals {# Parse an ARN into componentsparsed_arn = provider::aws::arn_parse(aws_instance.web.arn)account_id = local.parsed_arn.accountregion = local.parsed_arn.region# Build an ARN from componentscustom_arn = provider::aws::arn_build({partition = "aws"service = "s3"region = ""account = ""resource = "my-bucket/my-key"})}# Google Cloud Provider Functions (v5.23+)locals {# Extract region from zoneregion = provider::google::region_from_zone(var.zone) # "us-west1-a" → "us-west1"}# Kubernetes Provider Functions (v2.28+)locals {# Encode HCL to Kubernetes manifest YAMLmanifest_yaml = provider::kubernetes::manifest_encode(local.deployment_config)}
Ephemeral Resources (Terraform 1.10+)
Ephemeral resources provide temporary values that are never persisted in state or plan files. Critical for handling secrets securely.
# Generate a password that never touches stateephemeral "random_password" "db_password" {length = 16special = trueoverride_special = "!#$%&*()-_=+[]{}<>:?"}# Fetch secrets ephemerally from AWS Secrets Managerephemeral "aws_secretsmanager_secret_version" "api_key" {secret_id = aws_secretsmanager_secret.api_key.id}# Ephemeral variables (declare with ephemeral = true)variable "temporary_token" {type = stringephemeral = true # Value won't be stored in state}# Ephemeral outputsoutput "session_token" {value = ephemeral.aws_secretsmanager_secret_version.api_key.secret_stringephemeral = true # Won't be stored in state}
Write-Only Arguments (Terraform 1.11+)
Write-only arguments accept ephemeral values and are never persisted. They use _wo suffix and require a version attribute.
terraform {required_version = ">= 1.11, < 2.0"}# Secure database password handlingephemeral "random_password" "db_password" {length = 16}resource "aws_db_instance" "main" {identifier = "mydb"instance_class = "db.t3.micro"allocated_storage = 20engine = "postgres"username = "admin"# Write-only password - never stored in state!password_wo = ephemeral.random_password.db_password.resultpassword_wo_version = 1 # Increment to trigger password rotationskip_final_snapshot = true}# Secrets Manager with write-onlyresource "aws_secretsmanager_secret_version" "db_password" {secret_id = aws_secretsmanager_secret.db_password.id# Write-only secret stringsecret_string_wo = ephemeral.random_password.db_password.resultsecret_string_wo_version = 1}
Enhanced Variable Validations (Terraform 1.9+)
Validation conditions can now reference other variables, data sources, and local values.
# Reference data sources in validationdata "aws_ec2_instance_type_offerings" "available" {filter {name = "location"values = [var.availability_zone]}}variable "instance_type" {type = stringdescription = "EC2 instance type"validation {# NEW: Can reference data sourcescondition = contains(data.aws_ec2_instance_type_offerings.available.instance_types,var.instance_type)error_message = "Instance type ${var.instance_type} is not available in the selected AZ."}}# Cross-variable validationvariable "min_instances" {type = numberdefault = 1}variable "max_instances" {type = numberdefault = 10validation {# NEW: Can reference other variablescondition = var.max_instances >= var.min_instanceserror_message = "max_instances must be >= min_instances"}}
S3 Native State Locking (Terraform 1.11+)
S3 now supports native state locking without DynamoDB.
terraform {backend "s3" {bucket = "my-terraform-state"key = "project/terraform.tfstate"region = "us-east-1"encrypt = true# NEW: S3-native locking (Terraform 1.11+)use_lockfile = true# DEPRECATED: DynamoDB locking (still works but no longer required)# dynamodb_table = "terraform-locks"}}
Import Blocks (Terraform 1.5+)
Declarative resource imports without command-line operations.
# Import existing resources declarativelyimport {to = aws_instance.webid = "i-1234567890abcdef0"}resource "aws_instance" "web" {ami = "ami-0c55b159cbfafe1f0"instance_type = "t3.micro"# ... configuration must match existing resource}# Import with for_eachimport {for_each = var.existing_bucket_namesto = aws_s3_bucket.imported[each.key]id = each.value}
Moved and Removed Blocks
Safely refactor resources without destroying them.
# Rename a resourcemoved {from = aws_instance.old_nameto = aws_instance.new_name}# Move to a modulemoved {from = aws_vpc.mainto = module.networking.aws_vpc.main}# Cross-type refactoring (1.8+)moved {from = null_resource.exampleto = terraform_data.example}# Remove resource from state without destroying (1.7+)removed {from = aws_instance.legacylifecycle {destroy = false # Keep the actual resource, just remove from state}}
Import Blocks with for_each (Terraform 1.12+)
Import multiple resources using for_each meta-argument.
# Import multiple S3 buckets using a maplocals {buckets = {"staging" = "bucket1""uat" = "bucket2""prod" = "bucket3"}}import {for_each = local.bucketsto = aws_s3_bucket.this[each.key]id = each.value}resource "aws_s3_bucket" "this" {for_each = local.buckets}# Import across module instances using list of objectslocals {module_buckets = [{ group = "one", key = "bucket1", id = "one_1" },{ group = "one", key = "bucket2", id = "one_2" },{ group = "two", key = "bucket1", id = "two_1" },]}import {for_each = local.module_bucketsid = each.value.idto = module.group[each.value.group].aws_s3_bucket.this[each.value.key]}
Actions Block (Terraform 1.14+)
Actions enable provider-defined operations outside the standard CRUD model. Use for operations like Lambda invocations, cache invalidations, or database backups.
# Invoke a Lambda function (example syntax)action "aws_lambda_invoke" "process_data" {function_name = aws_lambda_function.processor.function_namepayload = jsonencode({ action = "process" })}# Create CloudFront invalidationaction "aws_cloudfront_create_invalidation" "invalidate_cache" {distribution_id = aws_cloudfront_distribution.main.idpaths = ["/*"]}# Actions support for_eachaction "aws_lambda_invoke" "batch_process" {for_each = toset(["task1", "task2", "task3"])function_name = aws_lambda_function.processor.function_namepayload = jsonencode({ task = each.value })}
Triggering Actions via Lifecycle:
Use action_trigger within a resource's lifecycle block to automatically invoke actions:
resource "aws_lambda_function" "example" {function_name = "my-function"# ... other config ...lifecycle {action_trigger {events = [after_create, after_update]actions = [action.aws_lambda_invoke.process_data]}}}action "aws_lambda_invoke" "process_data" {function_name = aws_lambda_function.example.function_namepayload = jsonencode({ action = "initialize" })}
Manual Invocation:
Actions can also be invoked manually via CLI:
terraform apply -invoke action.aws_lambda_invoke.process_data
List Resources and Query Command (Terraform 1.14+)
Query and filter existing infrastructure using .tfquery.hcl files and the terraform query command.
# my-resources.tfquery.hcl# Define list resources to query existing infrastructurelist "aws_instance" "web_servers" {filter {name = "tag:Environment"values = [var.environment]}include_resource = true # Include full resource details}list "aws_s3_bucket" "data_buckets" {filter {name = "tag:Purpose"values = ["data-storage"]}}
# Query infrastructure and output resultsterraform query# Generate import configuration from query resultsterraform query -generate-config-out="import_config.tf"# Output in JSON formatterraform query -json# Use with variablesterraform query -var 'environment=prod'
Preconditions and Postconditions (Terraform 1.5+)
Add custom validation within resource lifecycle.
resource "aws_instance" "example" {instance_type = "t3.micro"ami = data.aws_ami.example.idlifecycle {# Check before creationprecondition {condition = data.aws_ami.example.architecture == "x86_64"error_message = "The selected AMI must be for the x86_64 architecture."}# Verify after creationpostcondition {condition = self.public_dns != ""error_message = "EC2 instance must be in a VPC that has public DNS hostnames enabled."}}}# Preconditions on outputsoutput "web_url" {value = "https://${aws_instance.web.public_dns}"precondition {condition = aws_instance.web.public_dns != ""error_message = "Instance must have a public DNS name."}}
Resources
references/
The references/ directory contains detailed documentation for reference:
terraform_best_practices.md- Comprehensive best practices guidecommon_patterns.md- Common Terraform patterns and examplesprovider_examples.md- Example configurations for popular providers
Open a reference directly by relative path:
devops-skills-plugin/skills/terraform-generator/references/[filename].md
assets/
The assets/ directory contains template files:
minimal-project/- Minimal Terraform project template
Templates can be copied and customized for the user's specific needs.
Notes
- Always run devops-skills:terraform-validator after generation
- For feature/version drift checks in CI, run
bash scripts/run_ci_checks.sh - Web search is essential for custom providers/modules
- Follow the principle of least surprise in configurations
- Make configurations readable and maintainable
- Include helpful comments and documentation
- Generate realistic examples in terraform.tfvars when helpful