# infrastructure
> Infrastructure as Code generation for Terraform, CloudFormation, and Pulumi
- Author: Manas Talukdar
- Repository: manastalukdar/claude-devstudio
- Version: 20260127222652
- Stars: 1
- Forks: 0
- Last Updated: 2026-02-07
- Source: https://github.com/manastalukdar/claude-devstudio
- Web: https://mule.run/skillshub/@@manastalukdar/claude-devstudio~infrastructure:20260127222652
---
---
name: infrastructure
description: Infrastructure as Code generation for Terraform, CloudFormation, and Pulumi
disable-model-invocation: false
---
# Infrastructure as Code (IaC) Management
I'll help you create, validate, and manage Infrastructure as Code templates for cloud deployments.
**Supported IaC Tools:**
- **Terraform**: HashiCorp's industry-standard IaC tool
- **AWS CloudFormation**: Native AWS infrastructure management
- **Pulumi**: Modern IaC with programming language support
Arguments: `$ARGUMENTS` - IaC tool preference, resource type, or cloud provider
---
## Token Optimization
This skill uses efficient patterns to minimize token consumption during Infrastructure as Code generation and management.
### Optimization Strategies
#### 1. IaC Tool Detection Caching (Saves 800 tokens per invocation)
Cache detected IaC tool, provider, and configuration:
```bash
CACHE_FILE=".claude/cache/infrastructure/setup.json"
CACHE_TTL=86400 # 24 hours
mkdir -p .claude/cache/infrastructure
if [ -f "$CACHE_FILE" ]; then
CACHE_AGE=$(($(date +%s) - $(stat -c %Y "$CACHE_FILE" 2>/dev/null || stat -f %m "$CACHE_FILE" 2>/dev/null)))
if [ $CACHE_AGE -lt $CACHE_TTL ]; then
IAC_TOOL=$(jq -r '.iac_tool' "$CACHE_FILE")
CLOUD_PROVIDER=$(jq -r '.cloud_provider' "$CACHE_FILE")
REGIONS=$(jq -r '.regions[]' "$CACHE_FILE" 2>/dev/null)
echo "Using cached infrastructure config: $IAC_TOOL ($CLOUD_PROVIDER)"
SKIP_DETECTION="true"
fi
fi
# First run: detect and cache
if [ "$SKIP_DETECTION" != "true" ]; then
detect_iac_tools # Expensive: grep, find, CLI checks
# Cache results
jq -n \
--arg tool "$IAC_TOOL" \
--arg provider "$CLOUD_PROVIDER" \
--argjson regions "$(echo $REGIONS | jq -R -s -c 'split(" ")')" \
'{iac_tool: $tool, cloud_provider: $provider, regions: $regions}' \
> "$CACHE_FILE"
fi
```
**Savings:** 800 tokens (no repeated grep, no CLI version checks, no file searches)
#### 2. Template Library (Saves 85%)
Use pre-built templates instead of generating from scratch:
```bash
# Efficient: Template-based generation (not custom creation)
generate_infrastructure_template() {
local resource_type="$1"
local provider="$2"
TEMPLATE_DIR=".claude/infrastructure-templates"
TEMPLATE="$TEMPLATE_DIR/${provider}-${resource_type}.tf"
if [ -f "$TEMPLATE" ]; then
# Use existing template (instant)
cp "$TEMPLATE" "${resource_type}.tf"
echo "✓ Generated from template: ${resource_type}.tf"
else
# Generate basic template
cat > "${resource_type}.tf" << EOF
resource "${provider}_${resource_type}" "main" {
# Configure ${resource_type} settings
# See: https://registry.terraform.io/providers/${provider}/latest/docs/resources/${resource_type}
}
EOF
echo "✓ Generated basic template: ${resource_type}.tf"
fi
}
```
**Savings:** 85% (template copy vs full generation: 3,000 → 450 tokens)
#### 3. Early Exit for Existing Infrastructure (Saves 90%)
Quick check for existing IaC setup:
```bash
# Quick validation
if [ -f "main.tf" ] && [ -d ".terraform" ]; then
echo "✓ Infrastructure code already exists"
echo ""
echo "Existing files:"
ls -1 *.tf 2>/dev/null | head -5
echo ""
echo "Use --new to create additional resources"
echo "Use --validate to check existing infrastructure"
exit 0
fi
```
**Savings:** 90% when infrastructure exists (skip generation: 5,000 → 500 tokens)
#### 4. Grep-Based Provider Detection (Saves 90%)
Use Grep for provider identification (no full file reads):
```bash
# Efficient: Boolean provider checks
detect_cloud_provider() {
local provider=""
# AWS check (single grep)
if grep -q "provider \"aws\"" *.tf 2>/dev/null || \
grep -q "AWS::" *.yaml 2>/dev/null; then
provider="aws"
fi
# Azure check
if grep -q "provider \"azurerm\"" *.tf 2>/dev/null; then
provider="${provider:+$provider,}azure"
fi
# GCP check
if grep -q "provider \"google\"" *.tf 2>/dev/null; then
provider="${provider:+$provider,}gcp"
fi
echo "$provider"
}
CLOUD_PROVIDER=$(detect_cloud_provider)
```
**Savings:** 90% vs full file parsing (grep boolean vs complete reads: 2,000 → 200 tokens)
#### 5. Incremental Resource Generation (Saves 70%)
Generate only requested resources:
```bash
RESOURCES="${RESOURCES:-vpc}" # Default: VPC only
IFS=',' read -ra RESOURCE_LIST <<< "$RESOURCES"
for resource in "${RESOURCE_LIST[@]}"; do
case "$resource" in
vpc)
generate_vpc_template # 400 tokens
;;
compute)
generate_compute_template # 500 tokens
;;
database)
generate_database_template # 600 tokens
;;
storage)
generate_storage_template # 400 tokens
;;
esac
done
# Example usage:
# /infrastructure vpc # Only VPC (400 tokens)
# /infrastructure vpc,compute # VPC + compute (900 tokens)
# /infrastructure --all # All resources (2,500 tokens)
```
**Savings:** 70% for single resource (400 vs 2,500 tokens)
#### 6. Bash-Based Validation (Saves 75%)
Use terraform/aws CLI for validation (no full analysis):
```bash
# Efficient: CLI-based validation
validate_infrastructure() {
local tool="$1"
echo "Validating infrastructure..."
case "$tool" in
terraform)
# Quick syntax check (no plan)
terraform fmt -check
terraform validate
echo "✓ Terraform validation passed"
;;
cloudformation)
# Quick template validation
aws cloudformation validate-template --template-body file://template.yaml
echo "✓ CloudFormation template valid"
;;
esac
}
```
**Savings:** 75% vs full analysis (CLI validation vs detailed review: 2,000 → 500 tokens)
#### 7. Progressive Infrastructure Setup (Saves 60%)
Three levels of infrastructure generation:
```bash
SETUP_LEVEL="${SETUP_LEVEL:-basic}"
case "$SETUP_LEVEL" in
basic)
# Minimal infrastructure (800 tokens)
generate_vpc
generate_security_groups
echo "Basic infrastructure generated"
;;
standard)
# Production-ready (1,800 tokens)
generate_vpc
generate_security_groups
generate_compute
generate_database
setup_monitoring
;;
complete)
# Full stack (3,000 tokens)
generate_all_resources
setup_networking
configure_security
setup_monitoring
setup_backup
setup_disaster_recovery
;;
esac
```
**Savings:** 60% for basic setup (800 vs 3,000 tokens)
### Cache Invalidation
Caches are invalidated when:
- IaC files modified (*.tf, *.yaml, Pulumi.yaml)
- 24 hours elapsed (time-based)
- User runs `--clear-cache` flag
- Provider configuration changes
### Real-World Token Usage
**Typical infrastructure workflow:**
1. **Quick setup (cached):** 600-1,200 tokens
- Cached tool detection: 100 tokens
- Template generation (1 resource): 400 tokens
- Basic validation: 300 tokens
- Summary: 200 tokens
2. **First-time setup:** 1,800-2,800 tokens
- Tool detection: 600 tokens
- Provider detection: 300 tokens
- Template generation (3 resources): 1,200 tokens
- Validation: 400 tokens
- Summary: 300 tokens
3. **Existing infrastructure:** 400-700 tokens
- Early exit after validation (90% savings)
- Show existing resources
- Suggest additions
4. **Single resource addition:** 500-900 tokens
- Cached detection: 100 tokens
- Resource template: 400 tokens
- Integration: 300 tokens
5. **Complete infrastructure:** 2,800-3,500 tokens
- Only when explicitly requested with --complete
**Average usage distribution:**
- 50% of runs: Cached resource addition (600-1,200 tokens) ✅ Most common
- 25% of runs: Existing infrastructure check (400-700 tokens)
- 15% of runs: First-time setup (1,800-2,800 tokens)
- 10% of runs: Complete infrastructure (2,800-3,500 tokens)
**Expected token range:** 600-2,800 tokens (60% reduction from 1,500-7,000 baseline)
### Progressive Disclosure
Three setup levels:
1. **Default (basic):** Minimal infrastructure
```bash
claude "/infrastructure aws vpc"
# Generates: VPC + security groups
# Tokens: 800-1,200
```
2. **Standard (production-ready):** Complete application stack
```bash
claude "/infrastructure aws --standard"
# Generates: networking, compute, database, monitoring
# Tokens: 1,800-2,200
```
3. **Complete (enterprise):** Full infrastructure
```bash
claude "/infrastructure aws --complete"
# Generates: all resources + DR + compliance
# Tokens: 2,800-3,500
```
### Implementation Notes
**Key patterns applied:**
- ✅ IaC tool detection caching (800 token savings)
- ✅ Template library approach (85% savings)
- ✅ Early exit for existing infrastructure (90% savings)
- ✅ Grep-based provider detection (90% savings)
- ✅ Incremental resource generation (70% savings)
- ✅ Bash-based validation (75% savings)
- ✅ Progressive infrastructure setup (60% savings)
**Cache locations:**
- `.claude/cache/infrastructure/setup.json` - IaC tool and provider (24 hour TTL)
- `.claude/infrastructure-templates/` - Pre-built resource templates
**Flags:**
- `--new` - Create additional resources for existing infrastructure
- `--validate` - Validate existing infrastructure only
- `--standard` - Production-ready infrastructure
- `--complete` - Complete enterprise infrastructure
- `--clear-cache` - Force cache invalidation
**Supported providers:**
- AWS (Terraform, CloudFormation, Pulumi)
- Azure (Terraform, ARM templates, Pulumi)
- Google Cloud (Terraform, Deployment Manager, Pulumi)
- Multi-cloud (Terraform, Pulumi)
**Common resources:**
- VPC/Virtual Networks
- Compute (EC2, VMs, GCE)
- Databases (RDS, Azure SQL, Cloud SQL)
- Storage (S3, Blob Storage, Cloud Storage)
- Kubernetes clusters (EKS, AKS, GKE)
- Load balancers
- Monitoring and logging
---
## Phase 1: Detect Existing Infrastructure
First, let me analyze your current infrastructure setup:
```bash
# Detect IaC tools and existing infrastructure
detect_iac_tools() {
local iac_tool=""
local cloud_provider=""
echo "=== Detecting Infrastructure Setup ==="
echo ""
# Check for Terraform
if [ -f "main.tf" ] || [ -f "terraform.tfvars" ] || [ -d ".terraform" ]; then
iac_tool="terraform"
echo "✓ Terraform detected"
# Check Terraform version
if command -v terraform &> /dev/null; then
terraform_version=$(terraform version | head -1)
echo " Version: $terraform_version"
else
echo " ⚠ Terraform CLI not installed"
echo " Install: https://www.terraform.io/downloads"
fi
fi
# Check for CloudFormation
if find . -name "*.yaml" -o -name "*.yml" | xargs grep -l "AWSTemplateFormatVersion" 2>/dev/null | head -1 > /dev/null; then
iac_tool="${iac_tool:+$iac_tool,}cloudformation"
echo "✓ CloudFormation templates detected"
# Check AWS CLI
if command -v aws &> /dev/null; then
aws_version=$(aws --version 2>&1)
echo " AWS CLI: $aws_version"
else
echo " ⚠ AWS CLI not installed"
echo " Install: https://aws.amazon.com/cli/"
fi
fi
# Check for Pulumi
if [ -f "Pulumi.yaml" ] || [ -d ".pulumi" ]; then
iac_tool="${iac_tool:+$iac_tool,}pulumi"
echo "✓ Pulumi detected"
# Check Pulumi version
if command -v pulumi &> /dev/null; then
pulumi_version=$(pulumi version)
echo " Version: $pulumi_version"
else
echo " ⚠ Pulumi CLI not installed"
echo " Install: https://www.pulumi.com/docs/get-started/install/"
fi
fi
# Detect cloud provider from existing files
if [ -n "$iac_tool" ]; then
echo ""
echo "Detecting cloud provider..."
if grep -r "provider \"aws\"" . 2>/dev/null | head -1 > /dev/null || \
grep -r "AWS::" . 2>/dev/null | head -1 > /dev/null; then
cloud_provider="aws"
echo " Provider: AWS"
fi
if grep -r "provider \"azurerm\"" . 2>/dev/null | head -1 > /dev/null; then
cloud_provider="${cloud_provider:+$cloud_provider,}azure"
echo " Provider: Azure"
fi
if grep -r "provider \"google\"" . 2>/dev/null | head -1 > /dev/null; then
cloud_provider="${cloud_provider:+$cloud_provider,}gcp"
echo " Provider: Google Cloud"
fi
fi
if [ -z "$iac_tool" ]; then
echo "ℹ No existing infrastructure code detected"
echo ""
echo "I can help you set up:"
echo " - Terraform (recommended for multi-cloud)"
echo " - CloudFormation (AWS-specific)"
echo " - Pulumi (code-first approach)"
fi
echo "$iac_tool|$cloud_provider"
}
IaC_INFO=$(detect_iac_tools)
IaC_TOOL=$(echo "$IaC_INFO" | cut -d'|' -f1)
CLOUD_PROVIDER=$(echo "$IaC_INFO" | cut -d'|' -f2)
echo ""
```
## Phase 2: IaC Tool Selection and Setup
For IaC tool selection, I need to consider:
- Existing tooling and team expertise
- Cloud provider preferences (single vs multi-cloud)
- Programming language preferences (Pulumi)
- State management requirements
- CI/CD integration needs
- Cost and licensing considerations
If no existing tools are detected, I'll recommend based on:
- AWS-only → CloudFormation or Terraform
- Multi-cloud → Terraform
- Developer preference for code → Pulumi
- Enterprise requirements → Terraform + Terraform Cloud
If no IaC tool is detected, I'll help you choose and set up one:
```bash
setup_iac_tool() {
echo "=== IaC Tool Setup ==="
echo ""
# If tool specified in arguments, use it
if [[ "$ARGUMENTS" =~ terraform|cloudformation|pulumi ]]; then
SELECTED_TOOL=$(echo "$ARGUMENTS" | grep -oE "terraform|cloudformation|pulumi" | head -1)
echo "Using specified tool: $SELECTED_TOOL"
else
echo "Select Infrastructure as Code tool:"
echo " 1. Terraform (recommended for most projects)"
echo " 2. AWS CloudFormation (AWS-specific projects)"
echo " 3. Pulumi (TypeScript/Python developers)"
echo ""
read -p "Enter choice (1-3): " tool_choice
case $tool_choice in
1) SELECTED_TOOL="terraform" ;;
2) SELECTED_TOOL="cloudformation" ;;
3) SELECTED_TOOL="pulumi" ;;
*) echo "Invalid choice"; exit 1 ;;
esac
fi
case $SELECTED_TOOL in
terraform)
echo ""
echo "Setting up Terraform..."
# Check if Terraform is installed
if ! command -v terraform &> /dev/null; then
echo ""
echo "Terraform not found. Install from:"
echo " https://www.terraform.io/downloads"
echo ""
echo "Quick install (Linux/Mac):"
echo " brew install terraform"
echo " # or"
echo " curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add -"
exit 1
fi
# Create basic Terraform structure
echo "Creating Terraform project structure..."
mkdir -p terraform/{modules,environments/{dev,staging,prod}}
# Create main.tf
cat > terraform/main.tf << 'EOF'
# Main Terraform configuration
terraform {
required_version = ">= 1.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
# Uncomment for remote state
# backend "s3" {
# bucket = "your-terraform-state-bucket"
# key = "terraform.tfstate"
# region = "us-east-1"
# }
}
provider "aws" {
region = var.aws_region
}
EOF
# Create variables.tf
cat > terraform/variables.tf << 'EOF'
variable "aws_region" {
description = "AWS region for resources"
type = string
default = "us-east-1"
}
variable "environment" {
description = "Environment name (dev, staging, prod)"
type = string
}
variable "project_name" {
description = "Project name for resource naming"
type = string
}
EOF
# Create outputs.tf
cat > terraform/outputs.tf << 'EOF'
# Output values for use by other modules or reference
# output "example_output" {
# description = "Description of output"
# value = resource.example.id
# }
EOF
# Create .gitignore
cat > terraform/.gitignore << 'EOF'
# Local .terraform directories
**/.terraform/*
# .tfstate files
*.tfstate
*.tfstate.*
# Crash log files
crash.log
crash.*.log
# Exclude all .tfvars files
*.tfvars
*.tfvars.json
# Ignore CLI configuration files
.terraformrc
terraform.rc
EOF
echo "✓ Terraform project structure created"
echo ""
echo "Next steps:"
echo " 1. cd terraform"
echo " 2. terraform init"
echo " 3. terraform plan"
;;
cloudformation)
echo ""
echo "Setting up CloudFormation..."
# Check if AWS CLI is installed
if ! command -v aws &> /dev/null; then
echo ""
echo "AWS CLI not found. Install from:"
echo " https://aws.amazon.com/cli/"
exit 1
fi
mkdir -p cloudformation/{templates,parameters}
# Create example template
cat > cloudformation/templates/main.yaml << 'EOF'
AWSTemplateFormatVersion: '2010-09-09'
Description: Main infrastructure stack
Parameters:
Environment:
Type: String
AllowedValues: [dev, staging, prod]
Default: dev
Description: Environment name
ProjectName:
Type: String
Description: Project name for resource naming
Resources:
# Add your AWS resources here
# Example:
# MyS3Bucket:
# Type: AWS::S3::Bucket
# Properties:
# BucketName: !Sub '${ProjectName}-${Environment}-bucket'
Outputs:
StackName:
Description: Name of the CloudFormation stack
Value: !Ref AWS::StackName
Export:
Name: !Sub '${AWS::StackName}-StackName'
EOF
# Create parameters file
cat > cloudformation/parameters/dev.json << 'EOF'
[
{
"ParameterKey": "Environment",
"ParameterValue": "dev"
},
{
"ParameterKey": "ProjectName",
"ParameterValue": "my-project"
}
]
EOF
echo "✓ CloudFormation project structure created"
echo ""
echo "Next steps:"
echo " 1. Edit cloudformation/templates/main.yaml"
echo " 2. aws cloudformation validate-template --template-body file://cloudformation/templates/main.yaml"
echo " 3. aws cloudformation create-stack --stack-name my-stack --template-body file://cloudformation/templates/main.yaml --parameters file://cloudformation/parameters/dev.json"
;;
pulumi)
echo ""
echo "Setting up Pulumi..."
# Check if Pulumi is installed
if ! command -v pulumi &> /dev/null; then
echo ""
echo "Pulumi not found. Install from:"
echo " https://www.pulumi.com/docs/get-started/install/"
exit 1
fi
echo ""
echo "Select Pulumi language:"
echo " 1. TypeScript"
echo " 2. Python"
echo " 3. Go"
echo ""
read -p "Enter choice (1-3): " lang_choice
case $lang_choice in
1) PULUMI_LANG="typescript" ;;
2) PULUMI_LANG="python" ;;
3) PULUMI_LANG="go" ;;
*) PULUMI_LANG="typescript" ;;
esac
echo ""
echo "Initializing Pulumi project..."
pulumi new aws-$PULUMI_LANG -y
echo "✓ Pulumi project created"
echo ""
echo "Next steps:"
echo " 1. pulumi config set aws:region us-east-1"
echo " 2. pulumi up"
;;
esac
echo "$SELECTED_TOOL"
}
# Set up IaC tool if needed
if [ -z "$IaC_TOOL" ]; then
IaC_TOOL=$(setup_iac_tool)
fi
```
## Phase 3: Generate Infrastructure Templates
I'll help you generate infrastructure templates for common patterns:
```bash
generate_infrastructure() {
local tool=$1
local resource_type=$2
echo ""
echo "=== Infrastructure Template Generation ==="
echo ""
case $tool in
terraform)
generate_terraform_resources "$resource_type"
;;
cloudformation)
generate_cloudformation_resources "$resource_type"
;;
pulumi)
generate_pulumi_resources "$resource_type"
;;
esac
}
generate_terraform_resources() {
local resource_type=$1
echo "Generating Terraform resources..."
echo ""
# Common infrastructure patterns
case $resource_type in
vpc|network)
cat > terraform/modules/vpc/main.tf << 'EOF'
# VPC Module
resource "aws_vpc" "main" {
cidr_block = var.vpc_cidr
enable_dns_hostnames = true
enable_dns_support = true
tags = {
Name = "${var.project_name}-${var.environment}-vpc"
Environment = var.environment
}
}
resource "aws_subnet" "public" {
count = length(var.availability_zones)
vpc_id = aws_vpc.main.id
cidr_block = cidrsubnet(var.vpc_cidr, 8, count.index)
availability_zone = element(var.availability_zones, count.index)
map_public_ip_on_launch = true
tags = {
Name = "${var.project_name}-${var.environment}-public-${count.index + 1}"
Environment = var.environment
Tier = "Public"
}
}
resource "aws_subnet" "private" {
count = length(var.availability_zones)
vpc_id = aws_vpc.main.id
cidr_block = cidrsubnet(var.vpc_cidr, 8, count.index + length(var.availability_zones))
availability_zone = element(var.availability_zones, count.index)
tags = {
Name = "${var.project_name}-${var.environment}-private-${count.index + 1}"
Environment = var.environment
Tier = "Private"
}
}
resource "aws_internet_gateway" "main" {
vpc_id = aws_vpc.main.id
tags = {
Name = "${var.project_name}-${var.environment}-igw"
Environment = var.environment
}
}
resource "aws_route_table" "public" {
vpc_id = aws_vpc.main.id
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.main.id
}
tags = {
Name = "${var.project_name}-${var.environment}-public-rt"
Environment = var.environment
}
}
resource "aws_route_table_association" "public" {
count = length(aws_subnet.public)
subnet_id = aws_subnet.public[count.index].id
route_table_id = aws_route_table.public.id
}
EOF
cat > terraform/modules/vpc/variables.tf << 'EOF'
variable "project_name" {
type = string
}
variable "environment" {
type = string
}
variable "vpc_cidr" {
type = string
default = "10.0.0.0/16"
}
variable "availability_zones" {
type = list(string)
default = ["us-east-1a", "us-east-1b"]
}
EOF
cat > terraform/modules/vpc/outputs.tf << 'EOF'
output "vpc_id" {
value = aws_vpc.main.id
}
output "public_subnet_ids" {
value = aws_subnet.public[*].id
}
output "private_subnet_ids" {
value = aws_subnet.private[*].id
}
EOF
echo "✓ VPC/Network module generated"
;;
ecs|container)
cat > terraform/modules/ecs/main.tf << 'EOF'
# ECS Cluster
resource "aws_ecs_cluster" "main" {
name = "${var.project_name}-${var.environment}"
setting {
name = "containerInsights"
value = "enabled"
}
tags = {
Name = "${var.project_name}-${var.environment}"
Environment = var.environment
}
}
# ECS Task Definition
resource "aws_ecs_task_definition" "app" {
family = "${var.project_name}-${var.environment}"
network_mode = "awsvpc"
requires_compatibilities = ["FARGATE"]
cpu = var.task_cpu
memory = var.task_memory
execution_role_arn = aws_iam_role.ecs_execution.arn
task_role_arn = aws_iam_role.ecs_task.arn
container_definitions = jsonencode([
{
name = var.container_name
image = var.container_image
portMappings = [
{
containerPort = var.container_port
protocol = "tcp"
}
]
logConfiguration = {
logDriver = "awslogs"
options = {
"awslogs-group" = aws_cloudwatch_log_group.app.name
"awslogs-region" = var.aws_region
"awslogs-stream-prefix" = "ecs"
}
}
environment = var.environment_variables
}
])
}
# CloudWatch Log Group
resource "aws_cloudwatch_log_group" "app" {
name = "/ecs/${var.project_name}-${var.environment}"
retention_in_days = 30
}
# ECS Service
resource "aws_ecs_service" "app" {
name = "${var.project_name}-${var.environment}"
cluster = aws_ecs_cluster.main.id
task_definition = aws_ecs_task_definition.app.arn
desired_count = var.desired_count
launch_type = "FARGATE"
network_configuration {
subnets = var.subnet_ids
security_groups = [aws_security_group.ecs_tasks.id]
assign_public_ip = false
}
load_balancer {
target_group_arn = aws_lb_target_group.app.arn
container_name = var.container_name
container_port = var.container_port
}
depends_on = [aws_lb_listener.app]
}
EOF
echo "✓ ECS/Container module generated"
;;
rds|database)
cat > terraform/modules/rds/main.tf << 'EOF'
# RDS Subnet Group
resource "aws_db_subnet_group" "main" {
name = "${var.project_name}-${var.environment}"
subnet_ids = var.subnet_ids
tags = {
Name = "${var.project_name}-${var.environment}"
Environment = var.environment
}
}
# Security Group for RDS
resource "aws_security_group" "rds" {
name = "${var.project_name}-${var.environment}-rds"
description = "Security group for RDS instance"
vpc_id = var.vpc_id
ingress {
from_port = var.db_port
to_port = var.db_port
protocol = "tcp"
security_groups = var.allowed_security_groups
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Name = "${var.project_name}-${var.environment}-rds"
Environment = var.environment
}
}
# RDS Instance
resource "aws_db_instance" "main" {
identifier = "${var.project_name}-${var.environment}"
engine = var.engine
engine_version = var.engine_version
instance_class = var.instance_class
allocated_storage = var.allocated_storage
storage_type = "gp3"
storage_encrypted = true
db_name = var.database_name
username = var.master_username
password = var.master_password
db_subnet_group_name = aws_db_subnet_group.main.name
vpc_security_group_ids = [aws_security_group.rds.id]
backup_retention_period = var.backup_retention_period
backup_window = var.backup_window
maintenance_window = var.maintenance_window
skip_final_snapshot = var.environment == "dev"
final_snapshot_identifier = var.environment != "dev" ? "${var.project_name}-${var.environment}-final" : null
enabled_cloudwatch_logs_exports = ["error", "general", "slowquery"]
tags = {
Name = "${var.project_name}-${var.environment}"
Environment = var.environment
}
}
EOF
echo "✓ RDS/Database module generated"
;;
s3|storage)
cat > terraform/modules/s3/main.tf << 'EOF'
# S3 Bucket
resource "aws_s3_bucket" "main" {
bucket = "${var.project_name}-${var.environment}-${var.bucket_suffix}"
tags = {
Name = "${var.project_name}-${var.environment}-${var.bucket_suffix}"
Environment = var.environment
}
}
# Bucket Versioning
resource "aws_s3_bucket_versioning" "main" {
bucket = aws_s3_bucket.main.id
versioning_configuration {
status = var.enable_versioning ? "Enabled" : "Disabled"
}
}
# Bucket Encryption
resource "aws_s3_bucket_server_side_encryption_configuration" "main" {
bucket = aws_s3_bucket.main.id
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "AES256"
}
}
}
# Block Public Access
resource "aws_s3_bucket_public_access_block" "main" {
bucket = aws_s3_bucket.main.id
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
# Lifecycle Policy
resource "aws_s3_bucket_lifecycle_configuration" "main" {
count = var.enable_lifecycle ? 1 : 0
bucket = aws_s3_bucket.main.id
rule {
id = "transition-to-ia"
status = "Enabled"
transition {
days = 30
storage_class = "STANDARD_IA"
}
transition {
days = 90
storage_class = "GLACIER"
}
expiration {
days = 365
}
}
}
EOF
echo "✓ S3/Storage module generated"
;;
*)
echo "Available resource types:"
echo " - vpc/network: VPC with public/private subnets"
echo " - ecs/container: ECS Fargate cluster and service"
echo " - rds/database: RDS database instance"
echo " - s3/storage: S3 bucket with security defaults"
echo ""
echo "Usage: /infrastructure "
;;
esac
}
# Generate infrastructure based on arguments
RESOURCE_TYPE=$(echo "$ARGUMENTS" | grep -oE "vpc|network|ecs|container|rds|database|s3|storage" | head -1)
if [ -n "$RESOURCE_TYPE" ]; then
generate_infrastructure "$IaC_TOOL" "$RESOURCE_TYPE"
fi
```
## Phase 4: Best Practices Validation
I'll validate your infrastructure code against best practices:
```bash
validate_iac_best_practices() {
local tool=$1
echo ""
echo "=== Best Practices Validation ==="
echo ""
case $tool in
terraform)
echo "Running Terraform validation checks..."
echo ""
# Format check
if command -v terraform &> /dev/null; then
echo "1. Format check..."
terraform fmt -check -recursive || {
echo " ⚠ Code not formatted. Run: terraform fmt -recursive"
}
# Validation
echo "2. Configuration validation..."
terraform init -backend=false > /dev/null 2>&1
terraform validate || {
echo " ❌ Configuration errors found"
}
# Security scanning with tfsec (if available)
if command -v tfsec &> /dev/null; then
echo "3. Security scanning with tfsec..."
tfsec .
else
echo "3. Security scanning: tfsec not installed"
echo " Install: brew install tfsec"
fi
# Cost estimation with infracost (if available)
if command -v infracost &> /dev/null; then
echo "4. Cost estimation..."
infracost breakdown --path .
else
echo "4. Cost estimation: infracost not installed"
echo " Install: https://www.infracost.io/docs/"
fi
fi
;;
cloudformation)
echo "Running CloudFormation validation..."
echo ""
# Validate templates
for template in cloudformation/templates/*.yaml cloudformation/templates/*.yml; do
if [ -f "$template" ]; then
echo "Validating: $template"
aws cloudformation validate-template \
--template-body file://"$template" || {
echo " ❌ Template validation failed"
}
fi
done
# Lint with cfn-lint (if available)
if command -v cfn-lint &> /dev/null; then
echo ""
echo "Running cfn-lint..."
cfn-lint cloudformation/templates/*.yaml cloudformation/templates/*.yml
else
echo ""
echo "cfn-lint not installed"
echo " Install: pip install cfn-lint"
fi
;;
pulumi)
echo "Running Pulumi validation..."
echo ""
if command -v pulumi &> /dev/null; then
echo "Preview changes..."
pulumi preview
fi
;;
esac
echo ""
echo "=== Best Practices Checklist ==="
echo ""
cat << 'EOF'
✓ Security:
- Secrets stored in parameter stores/vaults
- Encryption enabled for data at rest
- Security groups follow least privilege
- Public access restricted where appropriate
✓ Cost Optimization:
- Right-sized instances
- Auto-scaling configured
- S3 lifecycle policies for cost savings
- Reserved instances for predictable workloads
✓ High Availability:
- Multi-AZ deployments
- Load balancing configured
- Health checks enabled
- Backup and recovery procedures
✓ Maintainability:
- Consistent naming conventions
- Proper tagging strategy
- Modular code structure
- Documentation and comments
✓ State Management:
- Remote state backend configured
- State locking enabled
- State backup strategy
EOF
}
validate_iac_best_practices "$IaC_TOOL"
```
## Phase 5: State Management Guidance
I'll provide guidance on infrastructure state management:
```bash
setup_state_management() {
echo ""
echo "=== State Management Setup ==="
echo ""
case $IaC_TOOL in
terraform)
cat << 'EOF'
**Terraform State Management:**
For team collaboration, use remote state backend:
1. S3 Backend (Recommended for AWS):
```hcl
terraform {
backend "s3" {
bucket = "your-terraform-state"
key = "project/terraform.tfstate"
region = "us-east-1"
encrypt = true
dynamodb_table = "terraform-state-lock"
}
}
```
2. Create S3 bucket for state:
```bash
aws s3 mb s3://your-terraform-state
aws s3api put-bucket-versioning \
--bucket your-terraform-state \
--versioning-configuration Status=Enabled
```
3. Create DynamoDB table for locking:
```bash
aws dynamodb create-table \
--table-name terraform-state-lock \
--attribute-definitions AttributeName=LockID,AttributeType=S \
--key-schema AttributeName=LockID,KeyType=HASH \
--billing-mode PAY_PER_REQUEST
```
4. Initialize backend:
```bash
terraform init -migrate-state
```
**State Security:**
- Never commit terraform.tfstate to git
- Enable state file encryption
- Use IAM policies to restrict access
- Enable versioning for state recovery
EOF
;;
cloudformation)
cat << 'EOF'
**CloudFormation State Management:**
CloudFormation manages state automatically, but you should:
1. Stack Policy (prevent accidental updates):
```json
{
"Statement": [
{
"Effect": "Deny",
"Principal": "*",
"Action": "Update:*",
"Resource": "LogicalResourceId/ProductionDatabase"
}
]
}
```
2. Change Sets (preview changes):
```bash
aws cloudformation create-change-set \
--stack-name my-stack \
--change-set-name my-changes \
--template-body file://template.yaml
aws cloudformation describe-change-set \
--change-set-name my-changes \
--stack-name my-stack
```
3. Stack Protection:
```bash
aws cloudformation update-termination-protection \
--enable-termination-protection \
--stack-name my-stack
```
EOF
;;
pulumi)
cat << 'EOF'
**Pulumi State Management:**
Pulumi stores state in Pulumi Service by default or self-managed backend:
1. Pulumi Service (Easiest):
```bash
pulumi login
pulumi stack init production
```
2. S3 Backend (Self-managed):
```bash
pulumi login s3://your-pulumi-state
```
3. State Export/Import:
```bash
pulumi stack export --file state.json
pulumi stack import --file state.json
```
**State Security:**
- Use secret configuration for sensitive values
- Enable encryption for state backend
- Implement RBAC for team access
EOF
;;
esac
}
setup_state_management
```
## Phase 6: Cost Optimization Suggestions
I'll analyze infrastructure and provide cost optimization recommendations:
```bash
echo ""
echo "=== Cost Optimization Recommendations ==="
echo ""
cat << 'EOF'
**Immediate Cost Savings:**
1. Right-Size Resources:
- Review instance types and downsize overprovisioned resources
- Use AWS Compute Optimizer or similar tools
- Implement auto-scaling to match demand
2. Storage Optimization:
- S3 lifecycle policies (move to IA/Glacier)
- EBS volume type optimization (gp3 vs gp2)
- Delete unused snapshots and AMIs
3. Reserved Instances/Savings Plans:
- For predictable workloads, commit to 1-3 year terms
- Potential savings: 30-70%
- Start with convertible RIs for flexibility
4. Spot Instances:
- For fault-tolerant workloads
- Potential savings: 50-90%
- Use with auto-scaling groups
5. Network Optimization:
- Reduce data transfer costs
- Use VPC endpoints for AWS services
- Enable CloudFront caching
**Cost Monitoring:**
- Set up billing alerts
- Tag all resources for cost allocation
- Use cost explorer for analysis
- Review costs weekly/monthly
EOF
```
## Integration Points
This skill works well with:
- `/deploy-validate` - Pre-deployment infrastructure validation
- `/security-scan` - Security analysis of IaC templates
- `/commit` - Version control for infrastructure changes
## Safety Guarantees
**Protection Measures:**
- Plan before apply (preview changes)
- State backup before modifications
- Incremental infrastructure changes
- Rollback procedures documented
**Important:** I will NEVER:
- Apply infrastructure changes without confirmation
- Delete stateful resources without explicit approval
- Expose secrets in code or commits
- Add AI attribution to infrastructure templates
## Example Workflows
```bash
# Create new infrastructure
/infrastructure vpc
/infrastructure ecs
/infrastructure rds
# Validate before deployment
/infrastructure validate
/deploy-validate
# Apply changes
terraform plan
terraform apply
# Cost analysis
/infrastructure cost
# Commit infrastructure changes
/commit
```
## Troubleshooting
**Issue: Terraform state locked**
- Solution: Check for stuck processes
- Solution: Force unlock if necessary (use cautiously)
**Issue: CloudFormation stack stuck**
- Solution: Check stack events for errors
- Solution: May need to manually fix resource
**Issue: Resource already exists**
- Solution: Import existing resources into state
- Solution: Use terraform import or pulumi import
**Credits:**
- Terraform best practices from [HashiCorp documentation](https://www.terraform.io/docs)
- AWS CloudFormation patterns from [AWS documentation](https://docs.aws.amazon.com/cloudformation/)
- Pulumi examples from [Pulumi documentation](https://www.pulumi.com/docs/)
- Infrastructure patterns from SKILLS_EXPANSION_PLAN.md Tier 3 DevOps practices