Skip to content

Latest commit

 

History

History
207 lines (138 loc) · 5.19 KB

File metadata and controls

207 lines (138 loc) · 5.19 KB

hq Examples — Real-World Queries

Validated queries against a production Terraform code. All examples use structural mode.

For query syntax reference, see 04_hq.md.


Quick Reference

hq 'resource[*]' main.tf --json              # Query a file
hq 'resource[*]' infra/ --ndjson             # Query a directory (recursive)
hq 'resource[*]' main.tf vars.tf --json      # Multiple files
hq 'resource[*]' 'modules/**/*.tf' --json    # Glob pattern
hq 'resource[*]' infra/ --json --with-location  # With line numbers
hq 'locals.app_name?' dir/ --value           # Exit 0 even if missing

Discovery & Inventory

List all resources

hq 'resource[*] | .name_labels' infra/ --value --no-filename
['aws_instance', 'web_server']
['aws_security_group', 'allow_https']
['aws_iam_role', 'lambda_exec']

List resources of a specific type

hq 'resource.aws_s3_bucket[*] | .name_labels' infra/ --value

List all modules and their sources

hq 'module~[*] | .source | .value' infra/ --value

The ~ skips remaining labels (module names) and descends into all named module blocks. .source | .value unwraps the attribute.

infra/prod/api/main.tf:"../../modules/ecs_service/v2"
infra/prod/api/main.tf:"../../modules/alb/v1"

List module outputs

hq 'output[*] | .name_labels' modules/ecs_service/v2/ --value --no-filename

Count resources (blast radius)

hq 'resource[*] | .name_labels' infra/prod/ --value --no-filename | wc -l

Tags & Compliance

Find resources without tags

hq 'resource~[select(not .tags)] | .name_labels' infra/ --value

Non-empty output = potential compliance violation.

Check if a required local exists

# Script validation: exit 1 if missing
hq 'locals.app_name' infra/prod/new-service/ --value

# Soft check: exit 0 either way
hq 'locals.app_name?' infra/prod/new-service/ --value

Multi-Attribute Extraction

Object construction extracts multiple fields per result in one query.

Instance types for cost analysis

hq 'resource.aws_instance~[*] | {name: .name_labels, type: .instance_type}' infra/ --ndjson
{"__file__": "infra/prod/bastion/ec2.tf", "name": ["aws_instance", "bastion"], "type": "\"t3.small\""}

CPU and memory for ECS services

hq 'module~[select(.cpu)] | {cpu, memory}' infra/ --ndjson
{"__file__": "infra/prod/api/ecs.tf", "cpu": 1024, "memory": 2048}
{"__file__": "infra/prod/worker/ecs.tf", "cpu": 2048, "memory": 4096}

Resource inventory with tags

hq 'resource~[*] | {type: .name_labels, tags}' infra/prod/ --ndjson

Deployment & Scaling

Modules with a specific attribute

hq 'module~[select(.auto_deploy)] | .auto_deploy | .value' infra/ --value

Resources using for_each or count

hq 'resource~[select(.for_each)] | .name_labels' infra/ --value
hq 'resource~[select(.count)] | .count | .value' infra/ --value

Secrets & Parameters

List SSM parameter paths

hq 'resource.aws_ssm_parameter~[*] | .name | .value' infra/ --value
infra/prod/api/ssm.tf:"/${var.region}/${var.env}/api/db-password"

Secrets passed to modules

hq 'module~[select(.secrets)] | .secrets' infra/ --ndjson

Provider & Module Versions

Provider version pins

hq 'terraform.required_providers' infra/ --ndjson
{"__file__": "infra/prod/api/versions.tf", "aws": {"source": "\"hashicorp/aws\"", "version": "\"5.80.0\""}}

Find modules on a specific version

hq 'module~[*] | {source}' infra/ --ndjson | grep 'ecs_service/v1'

IAM & Networking

hq 'data.aws_iam_policy_document[*] | .name_labels' infra/ --value
hq 'resource.aws_iam_role[*] | .name_labels' infra/ --value
hq 'resource.aws_route53_record[*] | .name_labels' infra/ --value

Non-AWS and Non-Terraform

hq parses any HCL2 file — not just .tf.

hq 'resource.datadog_monitor[*] | .name_labels' config/datadog/ --value
hq 'resource.github_team[*] | .name_labels' config/github/ --value
hq 'resource[*] | .name_labels' config/snowflake/ --value
hq 'inputs' terragrunt.hcl --json
hq 'plugin[*]' .tflint.hcl --value

For output modes, exit codes, and all flags, see hq Reference.

Tip: Use --ndjson for directory queries (streams, works with head/grep/jq). Use --json for single files or when you need a parseable array.

Performance: When querying 20+ files with --json or --ndjson, hq automatically parallelizes across CPU cores. Use --jobs 0 to force serial, or --jobs N to set an explicit worker count.