Loading...
Loading...
Comprehensive toolkit for validating, linting, testing, and automating Terragrunt configurations, HCL files, and Stacks. Use this skill when working with Terragrunt files (.hcl, terragrunt.hcl, terragrunt.stack.hcl), validating infrastructure-as-code, debugging Terragrunt configurations, performing dry-run testing with terragrunt plan, working with Terragrunt Stacks, or working with custom providers and modules.
npx skill4agent add akin-ozer/cc-devops-skills terragrunt-validatorterragrunt stack generate/runterragrunt plan| Deprecated Command | New Command |
|---|---|
| |
| |
| |
| |
| |
| |
| |
| |
terragrunt run --allterragrunt run-allterragrunt dag graphterragrunt graph-dependenciesterragrunt hcl validate --inputsvalidate-inputsterragrunt hcl fmt --checkterragrunt hcl validateterragrunt init && terragrunt validatebash scripts/validate_terragrunt.sh [TARGET_DIR]terragrunt hcl fmt --checkterragrunt hcl validate --inputsSKIP_PLAN=trueSKIP_SECURITY=trueSKIP_LINT=trueTG_STRICT_MODE=true# Full validation
bash scripts/validate_terragrunt.sh ./infrastructure/prod
# Skip plan generation (faster)
SKIP_PLAN=true bash scripts/validate_terragrunt.sh ./infrastructure
# Only validate, skip linting and security
SKIP_LINT=true SKIP_SECURITY=true bash scripts/validate_terragrunt.shpython3 scripts/detect_custom_resources.py [DIRECTORY] [--format text|json]textjsonCRITICAL: You MUST look up documentation for EVERY detected custom resource (both providers AND modules). Do NOT skip any. This is mandatory, not optional.
"{provider_source} terraform provider documentation version {version}""mongodb/mongodbatlas terraform provider documentation version 1.14.0"mcp__context7__resolve-library-idmcp__context7__get-library-docstopic: "authentication"topic: "configuration"mcp__context7__resolve-library-idmcp__context7__get-library-docshttps://registry.terraform.io/modules/{source}/{version}a) Run detect_custom_resources.py
b) For EACH custom provider/module:
- Note the exact version
- Use Context7 MCP:
1. mcp__context7__resolve-library-id with libraryName: "{provider/module name}"
2. mcp__context7__get-library-docs with:
- context7CompatibleLibraryID: "{resolved ID}"
- topic: "authentication" (for auth requirements)
- topic: "configuration" (for setup requirements)
- OR use WebSearch with version-specific queries
- Review documentation for:
* Required configuration blocks
* Authentication requirements (API keys, credentials)
* Available resources/data sources
* Known issues or breaking changes in the version
c) Apply learnings to validation/troubleshooting
d) Document findings if issues are encountered# 1. Detect custom resources
python3 scripts/detect_custom_resources.py ./infrastructure
# Output: Provider: datadog/datadog, Version: 3.30.0
# 2. Resolve library ID
mcp__context7__resolve-library-id with libraryName: "datadog terraform provider"
# Result: /datadog/terraform-provider-datadog
# 3. Fetch authentication docs (REQUIRED)
mcp__context7__get-library-docs with:
context7CompatibleLibraryID: "/datadog/terraform-provider-datadog"
topic: "authentication"
# 4. Fetch configuration docs
mcp__context7__get-library-docs with:
context7CompatibleLibraryID: "/datadog/terraform-provider-datadog"
topic: "configuration"# Detect custom resources
python3 scripts/detect_custom_resources.py ./infrastructure
# Then search for documentation:
# WebSearch: "datadog terraform provider 3.30.0 authentication configuration"
# WebSearch: "datadog terraform provider api_key app_key setup"cd <target-directory>
terragrunt hcl fmt --check
# To auto-fix formatting
terragrunt hcl fmt# Check HCL syntax and formatting
terragrunt hcl fmt --check
# Note: In Terragrunt 0.93+, for deeper configuration validation,
# initialize and validate (requires actual resources/credentials):
# terragrunt init && terragrunt validate# Initialize if needed
terragrunt init
# Validate
terragrunt validate# Initialize tflint (if .tflint.hcl exists)
tflint --init
# Run linting
tflint --recursiveNote: tfsec has been merged into Trivy and is no longer actively maintained. Use Trivy for all new projects.
# Using Trivy (recommended)
trivy config . --severity HIGH,CRITICAL
# With tfvars file
trivy config --tf-vars terraform.tfvars .
# Exclude downloaded modules
trivy config --tf-exclude-downloaded-modules .
# Legacy: Using tfsec (deprecated)
tfsec . --soft-fail# Scan directory
checkov -d . --framework terraform
# Scan with specific checks
checkov -d . --check CKV_AWS_21
# Output as JSON
checkov -d . --output json# Note: graph-dependencies command replaced with 'dag graph' in Terragrunt 0.93+
# Validate and display dependency graph
terragrunt dag graph
# Visualize dependencies (requires graphviz)
terragrunt dag graph | dot -Tpng > dependencies.png# Single module
terragrunt plan
# All modules (new syntax - Terragrunt 0.93+)
terragrunt run --all plan
# Legacy syntax (deprecated)
# terragrunt run-all planrun --allrun-all# Validate all modules
terragrunt run --all validate
# Plan all modules
terragrunt run --all plan
# Apply all modules
terragrunt run --all apply
# Destroy all modules
terragrunt run --all destroy
# Format all HCL files
terragrunt hcl fmt
# With parallelism
terragrunt run --all plan --parallelism 4
# With strict mode (errors on deprecated features)
terragrunt --strict-mode run --all plan
# Or via environment variable
TG_STRICT_MODE=true terragrunt run --all plan# Validate inputs
terragrunt hcl validate --inputs
# Show paths of invalid files
terragrunt hcl validate --show-config-path
# Combine with run --all to exclude invalid files
terragrunt run --all plan --queue-excludes-file <(terragrunt hcl validate --show-config-path || true)# Via CLI flag
terragrunt --strict-mode run --all plan
# Via environment variable (recommended for CI/CD)
export TG_STRICT_MODE=true
terragrunt run --all plan
# Check available strict controls
terragrunt info strict--strict-control# Enable specific strict controls
terragrunt run --all plan --strict-control cli-redesign --strict-control deprecated-commands
# Via environment variable (comma-separated)
TG_STRICT_CONTROL='cli-redesign,deprecated-commands' terragrunt run --all plan
# Available strict controls:
# - cli-redesign: Errors on deprecated CLI syntax
# - deprecated-commands: Errors on deprecated commands (run-all, hclfmt, etc.)
# - root-terragrunt-hcl: Errors when using root terragrunt.hcl (use root.hcl instead)
# - skip-dependencies-inputs: Improves performance by not reading dependency inputs
# - bare-include: Errors on bare include blocks (use named includes)# Render configuration to JSON
terragrunt render --json
# Render and write to file
terragrunt render --json --write
# Output goes to terragrunt.rendered.json# Get contextual information about current configuration
terragrunt info print
# Output includes:
# - config_path
# - download_dir
# - terraform_binary
# - working_dir# Find all units/stacks in directory
terragrunt find
# Output as JSON
terragrunt find --json
# Include dependency information
terragrunt find --json --dag
# List units (simpler output)
terragrunt list# Run with summary output (default in newer versions)
terragrunt run --all plan
# Disable summary output
terragrunt run --all plan --summary-disable
# Generate detailed report file
terragrunt run --all plan --report-file=report.json
# CSV format report
terragrunt run --all plan --report-file=report.csvterragrunt.stack.hcl# terragrunt.stack.hcl
locals {
environment = "dev"
aws_region = "us-east-1"
}
# Define a unit (generates a single terragrunt.hcl)
unit "vpc" {
source = "git::git@github.com:acme/infra-catalog.git//units/vpc?ref=v0.0.1"
path = "vpc"
values = {
environment = local.environment
cidr = "10.0.0.0/16"
}
}
unit "database" {
source = "git::git@github.com:acme/infra-catalog.git//units/database?ref=v0.0.1"
path = "database"
values = {
environment = local.environment
vpc_path = "../vpc"
}
}
# Include reusable stacks
stack "monitoring" {
source = "git::git@github.com:acme/infra-catalog.git//stacks/monitoring?ref=v0.0.1"
path = "monitoring"
values = {
environment = local.environment
}
}# Generate stack (creates .terragrunt-stack directory)
terragrunt stack generate
# Generate stack without validation
terragrunt stack generate --no-stack-validate
# Run command on all stack units
terragrunt stack run plan
terragrunt stack run apply
# Clean generated stack directories
terragrunt stack clean
# Get stack outputs
terragrunt stack outputno_validationunit "experimental" {
source = "git::git@github.com:acme/infra-catalog.git//units/experimental?ref=v0.0.1"
path = "experimental"
# Skip validation for this unit (useful for incomplete/experimental units)
no_validation = true
values = {
environment = local.environment
}
}.terragrunt-stackexec# Run tflint with unit context (TF_VAR_ env vars available)
terragrunt exec -- tflint
# Run checkov against specific unit
terragrunt exec -- checkov -d .
# Run AWS CLI with unit's configuration
terragrunt exec -- aws s3 ls s3://my-bucket
# Run custom scripts with Terragrunt context
terragrunt exec -- ./scripts/validate.sh
# Run across all units
terragrunt run --all exec -- tflintTF_VAR_run --all# terragrunt.hcl
feature "enable_monitoring" {
default = false
}
feature "use_new_vpc" {
default = true
}
inputs = {
monitoring_enabled = feature.enable_monitoring.value
vpc_version = feature.use_new_vpc.value ? "v2" : "v1"
}# Enable a feature flag
terragrunt plan --feature enable_monitoring=true
# Enable multiple feature flags
terragrunt plan --feature enable_monitoring=true --feature use_new_vpc=false
# Via environment variable
TG_FEATURE='enable_monitoring=true' terragrunt plan# Apply feature flag across all units
terragrunt run --all plan --feature enable_monitoring=true# Enable all experiments (not recommended for production)
terragrunt --experiment-mode run --all plan
# Enable specific experiment
terragrunt --experiment symlinks run --all plan
# Enable CAS (Content Addressable Storage) for faster cloning
terragrunt --experiment cas run --all plansymlinkscasfilter-flagYou MUST read the best practices reference file BEFORE starting validation. This is not optional.
# Read the best practices reference file first
cat references/best_practices.mdtree -L 3 <infrastructure-directory>find . -name "*.hcl" -o -name "terragrunt.hcl"python3 scripts/detect_custom_resources.py .CRITICAL: If ANY custom providers or modules are detected, you MUST look up documentation for EACH ONE. Do not skip any.
mcp__context7__resolve-library-idmcp__context7__get-library-docsmcp__context7__get-library-docs"{provider} terraform provider {version} documentation"mcp__context7__resolve-library-idmcp__context7__get-library-docsbash scripts/validate_terragrunt.sh <target-directory>terragrunt hcl fmtYou MUST verify each checklist item below and document the result (✅ pass or ❌ fail). Incomplete verification is not acceptable.
references/best_practices.md[ ] Include blocks: Child modules use `include "root" { path = find_in_parent_folders("root.hcl") }`
[ ] Named includes: All include blocks have names (not bare `include {}`)
[ ] Root file naming: Root config is named `root.hcl` (not `terragrunt.hcl`)
[ ] Environment configs: Environment-level configs named `env.hcl` (not `terragrunt.hcl`)
[ ] Common variables: Shared variables in `common.hcl` read via `read_terragrunt_config()`[ ] Mock outputs: ALL dependency blocks have mock_outputs for validation
[ ] Mock allowed commands: mock_outputs_allowed_terraform_commands includes ["validate", "plan", "init"]
[ ] Explicit paths: Dependency config_path uses relative paths ("../vpc" not absolute)
[ ] No circular deps: Run `terragrunt dag graph` to verify no cycles[ ] State encryption: remote_state config has `encrypt = true`
[ ] State locking: DynamoDB table configured for S3 backend
[ ] No hardcoded credentials: Search for patterns like "AKIA", "password =", account IDs
[ ] Sensitive variables: Passwords/keys use `sensitive = true` in variable blocks
[ ] IAM roles: Provider uses assume_role instead of static credentials[ ] Generate blocks: Provider and backend configs use `generate` blocks
[ ] Version constraints: terragrunt_version_constraint and terraform_version_constraint set
[ ] Reusable locals: Common values in shared files, not duplicated
[ ] if_exists: Generate blocks use appropriate if_exists strategy# Check for hardcoded AWS account IDs
grep -r "[0-9]\{12\}" --include="*.hcl" . | grep -v mock
# Check for potential credentials
grep -ri "password\s*=" --include="*.hcl" .
grep -ri "api_key\s*=" --include="*.hcl" .
# Check for dependencies without mock_outputs
grep -l "dependency\s" --include="*.hcl" -r . | xargs grep -L "mock_outputs"
# Check for terragrunt.hcl files in non-module directories (anti-pattern)
find . -name "terragrunt.hcl" -not -path "*/.terragrunt-cache/*" | head -20rm -rf .terragrunt-cache
terragrunt initterragrunt dag graphterragrunt force-unlock <LOCK_ID>ERROR: The file path ./versions.tf already exists and was not generated by terragrunt.
Can not generate terraform file: ./versions.tf already exists.tfgenerateversions.tfprovider.tfbackend.tfif_exists = "skip"# Remove conflicting files
rm -f versions.tf provider.tf backend.tf
rm -rf .terragrunt-cacheWARN: Using `terragrunt.hcl` as the root of Terragrunt configurations is an anti-patternroot.hclterragrunt.hclmv terragrunt.hcl root.hcl
# Update include blocks in child modules to reference root.hcl# Read the best practices reference
cat references/best_practices.mdincludegeneratereferences/best_practices.md# macOS
brew install terragrunt terraform tflint trivy graphviz jq
# Install Trivy (recommended security scanner)
brew install trivy
# Install Checkov (alternative security scanner)
pip3 install checkov
# Legacy tfsec (deprecated - use trivy instead)
# brew install tfsec
# Linux - Trivy
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin
# Linux - Checkov
pip3 install checkov
# Verify installations
terragrunt --version
trivy --version
checkov --versionmcp__context7__resolve-library-id with libraryName: "mongodb/mongodbatlas"mcp__context7__get-library-docs with context7CompatibleLibraryID: "/mongodb/mongodbatlas"#!/bin/bash
# ci-validate.sh
set -e
echo "Installing dependencies..."
# Install terragrunt, terraform, tflint, tfsec
echo "Detecting custom resources..."
python3 scripts/detect_custom_resources.py . --format json > custom_resources.json
# Could integrate with automated documentation lookup here
echo "Running validation suite..."
SKIP_PLAN=true bash scripts/validate_terragrunt.sh .
echo "Validation complete!"#!/bin/bash
# .git/hooks/pre-commit
# Format check
terragrunt hcl fmt --check || {
echo "HCL formatting issues found. Run: terragrunt hcl fmt"
exit 1
}
# Quick HCL syntax validation (Terragrunt 0.93+)
# Note: For full validation, use: terragrunt init && terragrunt validate
# But that requires credentials. HCL format check catches syntax errors.
echo "Pre-commit validation passed!"# Terragrunt debug
TERRAGRUNT_DEBUG=1 terragrunt plan
# Terraform trace
TF_LOG=TRACE terragrunt planrm -rf .terragrunt-cacheterragrunt initterragrunt force-unlock <LOCK_ID>render-jsonvalidate-inputsterragrunt run -- <command>graph-dependenciesdag graph.tflint.hclplugin "terraform" {
enabled = true
preset = "recommended"
}
plugin "aws" {
enabled = true
version = "0.27.0"
source = "github.com/terraform-linters/tflint-ruleset-aws"
}
rule "terraform_naming_convention" {
enabled = true
}.tfsec/config.ymlminimum_severity: MEDIUM
exclude:
- AWS001 # Example: exclude specific rules# Generate detailed graph (Terragrunt 0.93+ syntax)
terragrunt dag graph > graph.dot
# Convert to visual format
dot -Tpng graph.dot > graph.png
dot -Tsvg graph.dot > graph.svg
# Analyze for circular dependencies
grep -A5 "cycle" <(terragrunt dag graph 2>&1)scripts/validate_terragrunt.shscripts/detect_custom_resources.pyreferences/best_practices.md