From devops-skills
Validates Terragrunt HCL files, stacks, modules with linting (tflint), security scans (Trivy/Checkov), dependency graphs, formatting, and dry-run plans.
npx claudepluginhub akin-ozer/cc-devops-skills --plugin devops-skillsThis skill uses the workspace's default tool permissions.
This skill provides comprehensive validation, linting, and testing capabilities for Terragrunt configurations. Terragrunt is a thin wrapper for Terraform/OpenTofu that provides extra tools for keeping configurations DRY (Don't Repeat Yourself), working with multiple modules, and managing remote state.
references/best_practices.mdscripts/detect_custom_resources.pyscripts/run_ci_checks.shscripts/validate_terragrunt.shtest/infrastructure/common.hcltest/infrastructure/dev/app/terragrunt.hcltest/infrastructure/dev/backend.tftest/infrastructure/dev/cache/terragrunt.hcltest/infrastructure/dev/database/terragrunt.hcltest/infrastructure/dev/env.hcltest/infrastructure/dev/monitoring/terragrunt.hcltest/infrastructure/dev/provider.tftest/infrastructure/dev/versions.tftest/infrastructure/dev/vpc/terragrunt.hcltest/infrastructure/prod/backend.tftest/infrastructure/prod/database/terragrunt.hcltest/infrastructure/prod/env.hcltest/infrastructure/prod/monitoring/terragrunt.hcltest/infrastructure/prod/provider.tftest/infrastructure/prod/versions.tfSearches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Searches prompts.chat for AI prompt templates by keyword or category, retrieves by ID with variable handling, and improves prompts via AI. Use for discovering or enhancing prompts.
Checks Next.js compilation errors using a running Turbopack dev server after code edits. Fixes actionable issues before reporting complete. Replaces `next build`.
This skill provides comprehensive validation, linting, and testing capabilities for Terragrunt configurations. Terragrunt is a thin wrapper for Terraform/OpenTofu that provides extra tools for keeping configurations DRY (Don't Repeat Yourself), working with multiple modules, and managing remote state.
Use this skill when:
terragrunt stack generate/run)terragrunt planThis skill is designed for Terragrunt 0.93+ which includes the new CLI redesign.
| Deprecated Command | New Command |
|---|---|
run-all | run --all |
hclfmt | hcl fmt |
hclvalidate | hcl validate |
validate-inputs | hcl validate --inputs |
graph-dependencies | dag graph |
render-json | render --json -w |
terragrunt-info | info print |
plan-all, apply-all | run --all plan, run --all apply |
terragrunt run --all replaces terragrunt run-all for multi-module operationsterragrunt dag graph replaces terragrunt graph-dependencies for dependency visualizationterragrunt hcl validate --inputs replaces validate-inputs for input validationterragrunt hcl fmt --check or terragrunt hcl validateterragrunt init && terragrunt validateIf using an older Terragrunt version, some commands may need adjustment.
Run the comprehensive validation script to perform all checks at once:
bash scripts/validate_terragrunt.sh [TARGET_DIR]
What it validates:
terragrunt hcl fmt --check)terragrunt hcl validate --inputs)Environment variables:
SKIP_PLAN=true - Skip terragrunt plan stepSKIP_SECURITY=true - Skip security scanning (Trivy/tfsec)SKIP_LINT=true - Skip tflint lintingSKIP_INIT=true - Skip terragrunt init before validationSKIP_BACKEND_INIT=true - Run init with -backend=false (useful in CI/offline)SOFT_FAIL_SECURITY=true - Report security findings without failingTG_STRICT_MODE=true - Enable strict mode (errors on deprecated features)Example usage:
# 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.sh
Use the detection script to identify custom providers and modules that may require documentation lookup:
python3 scripts/detect_custom_resources.py [DIRECTORY] [--format text|json]
What it detects:
Output formats:
text - Human-readable report with search recommendationsjson - Machine-readable format for automationWhen custom resources are detected:
CRITICAL: You MUST look up documentation for EVERY detected custom resource (both providers AND modules). Do NOT skip any. This is mandatory, not optional.
For custom providers:
"{provider_source} terraform provider documentation version {version}""mongodb/mongodbatlas terraform provider documentation version 1.14.0"mcp__context7__resolve-library-id with provider name (e.g., "datadog terraform provider")mcp__context7__query-docs with the resolved library ID"authentication requirements" and "configuration examples"For custom modules (EQUALLY IMPORTANT - DO NOT SKIP):
mcp__context7__resolve-library-id with module name (e.g., "terraform-aws-modules vpc")mcp__context7__query-docshttps://registry.terraform.io/modules/{source}/{version}Documentation lookup workflow (MANDATORY for ALL detected resources):
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__query-docs with:
- libraryId: "{resolved ID}"
- query: "authentication requirements" (for auth requirements)
3. mcp__context7__query-docs with:
- libraryId: "{resolved ID}"
- query: "configuration examples" (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
Example using Context7 MCP:
# 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__query-docs with:
libraryId: "/datadog/terraform-provider-datadog"
query: "authentication requirements"
# 4. Fetch configuration docs
mcp__context7__query-docs with:
libraryId: "/datadog/terraform-provider-datadog"
query: "configuration examples"
Example using WebSearch:
# 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"
For manual or granular validation, use these individual commands:
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 --recursive
Note: 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 plan
For projects with multiple Terragrunt modules, use run --all (replaces deprecated run-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 that all required inputs are set and no unused inputs exist:
# 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)
Enable strict mode to catch deprecated features early:
# 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
Specific Strict Controls:
For finer-grained control, use --strict-control to enable specific controls:
# 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.csv
Terragrunt Stacks provide declarative infrastructure generation using terragrunt.stack.hcl files.
# 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 output
Use no_validation attribute to skip validation for specific units:
unit "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-stack directoryThe exec command allows you to run arbitrary programs against units with Terragrunt context. This is useful for integrating other tools like tflint, checkov, or AWS CLI with Terragrunt's configuration.
# 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_terragrunt.sh
# Run across all units
terragrunt run --all exec -- tflint
Key Features:
TF_VAR_ prefixed environment variablesrun --all for multi-unit operationsUse Cases:
Terragrunt supports first-class Feature Flags for safe infrastructure changes. Feature flags allow you to integrate incomplete work without risk, decouple release from deployment, and codify IaC evolution.
# 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
Benefits:
Terragrunt provides an experiments system for trying unstable features before they're GA:
# 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 plan
Available Experiments:
symlinks - Support symlink resolution for Terragrunt unitscas - Content Addressable Storage for faster Git/module cloningfilter-flag - Advanced filtering capabilities (coming in 1.0)Follow this workflow when validating Terragrunt configurations:
Use one executable path so docs and scripts stay aligned:
# Main validation
bash scripts/validate_terragrunt.sh <target-directory>
# Deterministic fixture tests (required after script changes)
python3 test/test_detect_custom_resources.py
bash test/test_validate_terragrunt.sh
Execution expectations:
You MUST read the best practices reference file BEFORE starting validation. This is not optional.
# Read the best practices reference file first
if [ -f references/best_practices.md ]; then
cat references/best_practices.md
else
echo "WARNING: references/best_practices.md not found; continue with built-in checklist below."
fi
This ensures you understand the patterns, anti-patterns, and checklists you will verify.
Understand the structure:
tree -L 3 <infrastructure-directory>
Identify Terragrunt files:
find . -name "*.hcl" -o -name "terragrunt.hcl"
Detect custom resources:
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.
For EACH detected custom provider - look up documentation:
mcp__context7__resolve-library-id with provider namemcp__context7__query-docs with query: "authentication requirements"mcp__context7__query-docs with query: "configuration examples""{provider} terraform provider {version} documentation"For EACH detected custom module - look up documentation:
mcp__context7__resolve-library-id with module name (e.g., "terraform-aws-modules vpc")mcp__context7__query-docs with relevant configuration queryDocument findings for each resource:
Run comprehensive validation:
bash scripts/validate_terragrunt.sh <target-directory>
Review output for errors:
terragrunt hcl fmtYou MUST verify each checklist item below and document the result (✅ pass or ❌ fail). Incomplete verification is not acceptable.
Perform explicit best practices verification using references/best_practices.md:
Configuration Pattern Checklist - verify each item:
[ ] 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()`
Dependency Management Checklist:
[ ] 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
Security Checklist:
[ ] 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
DRY Principle Checklist:
[ ] 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
Quick grep checks to run:
# 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 -20
Issue: Module not found
rm -rf .terragrunt-cache
terragrunt init
Issue: Provider authentication errors
Issue: Dependency errors
terragrunt dag graphIssue: State locking errors
terragrunt force-unlock <LOCK_ID>
Issue: S3 backend dynamodb_table deprecation warning
dynamodb_table is deprecated for S3 backends.use_lockfile = true in backend config when compatible with your workflow.dynamodb_table only for legacy compatibility needs.Issue: Unknown provider or module parameters
Issue: Generate block conflicts (file already exists)
ERROR: The file path ./versions.tf already exists and was not generated by terragrunt.
Can not generate terraform file: ./versions.tf already exists
Solution: This occurs when static .tf files exist that conflict with Terragrunt's generate blocks. Either:
versions.tf, provider.tf, backend.tf)if_exists = "skip" in the generate block to not overwrite existing files# Remove conflicting files
rm -f versions.tf provider.tf backend.tf
rm -rf .terragrunt-cache
Issue: Root terragrunt.hcl anti-pattern warning
WARN: Using `terragrunt.hcl` as the root of Terragrunt configurations is an anti-pattern
Solution: In Terragrunt 0.93+, the root configuration file should be named root.hcl instead of terragrunt.hcl. Rename the file:
mv terragrunt.hcl root.hcl
# Update include blocks in child modules to reference root.hcl
Reference the comprehensive best practices guide for detailed recommendations:
# Read the best practices reference
if [ -f references/best_practices.md ]; then
cat references/best_practices.md
else
echo "WARNING: references/best_practices.md not found; continue with checklist in this document."
fi
Key best practices to check:
include for shared configurationgenerate blocks for provider configWhen validating, check for anti-patterns:
Refer to references/best_practices.md for complete examples and detailed guidance.
Required:
Optional but recommended:
Deprecated tools:
Installation commands:
# 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 --version
If Context7 MCP is available, use it for provider/module documentation lookup:
Resolve library ID:
mcp__context7__resolve-library-id with libraryName: "mongodb/mongodbatlas"
Query documentation:
mcp__context7__query-docs with libraryId: "/mongodb/mongodbatlas" and query: "authentication requirements"
This provides version-aware documentation directly, as an alternative to WebSearch.
Use the deterministic skill-level CI gate as the blocking check:
bash scripts/run_ci_checks.sh --require-shellcheck
This gate runs:
bash -n)python3 -m py_compile)test/test_detect_custom_resources.py)test/test_validate_terragrunt.sh)--require-shellcheck is set)After that gate passes, run environment-dependent validation in jobs that have Terragrunt/Terraform credentials configured:
#!/bin/bash
# ci-validate.sh
set -euo pipefail
echo "Running deterministic validator checks..."
bash scripts/run_ci_checks.sh --require-shellcheck
echo "Installing dependencies..."
# Install terragrunt, terraform, tflint, trivy/checkov
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 SKIP_BACKEND_INIT=true bash scripts/validate_terragrunt.sh .
echo "Validation complete!"
Example pre-commit hook for local development:
#!/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!"
validate_terragrunt.sh derives mode from the target directory and changes the
Terragrunt command path accordingly:
| Mode | Directory shape | Terragrunt HCL check | Terraform check | Exit semantics |
|---|---|---|---|---|
single | terragrunt.hcl (or terragrunt.stack.hcl) in target dir | terragrunt hcl validate | terragrunt validate (with terragrunt init unless skipped) | Any syntax/validate failure exits non-zero |
multi | Nested units exist below target | terragrunt hcl validate --all (fallback to plain hcl validate if --all is unsupported) | terragrunt run --all validate (with run --all init unless skipped) | Any unit failure exits non-zero |
root-only | root.hcl only, no unit in target dir | Warn and skip | Warn and skip | Returns success (0) for these skipped steps |
none | No recognized Terragrunt config files | Error | Error | Returns non-zero |
Enable debug output for troubleshooting:
# Terragrunt debug
TERRAGRUNT_DEBUG=1 terragrunt plan
# Terraform trace
TF_LOG=TRACE terragrunt plan
"Error: Module not found"
rm -rf .terragrunt-cacheterragrunt init"Error: Provider not found"
"Error: Invalid function call"
"Cycle detected in dependency graph"
"Error acquiring state lock"
terragrunt force-unlock <LOCK_ID>"Error: unknown command" (Terragrunt 0.93+)
render-json, validate-inputs are deprecatedterragrunt run -- <command> for custom/unsupported commandsgraph-dependencies with dag graph✅ All checks passing:
⚠️ Review needed:
✗ Must fix:
Create custom tflint rules by adding .tflint.hcl:
plugin "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
}
Create custom tfsec policies by adding .tfsec/config.yml:
minimum_severity: MEDIUM
exclude:
- AWS001 # Example: exclude specific rules
Analyze complex dependency chains:
# 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.sh - Comprehensive validation suitescripts/detect_custom_resources.py - Custom provider/module detectorreferences/best_practices.md - Comprehensive best practices guide covering:
python3 test/test_detect_custom_resources.pybash test/test_validate_terragrunt.sh