Terraform 1.14 — The Complete Guide to List Resources (.tfquery.hcl), Actions Block, and `terraform query`: IaC's First Paradigm Shift in 5 Years
On November 19, 2025, HashiCorp shipped Terraform v1.14.0, and on April 20, 2026 they released the v1.14.9 patch that fixes a Stacks plugin installation bug. This minor release is not just a feature bump — it's the first crack in a five-year-old IaC consensus that "declarative + one-way provisioning is enough." Two new primitives do the cracking. First, List Resources (a new *.tfquery.hcl file type + the terraform query command) let you discover, filter, and bulk-import resources that already exist in your cloud from outside your codebase. Second, the Actions Block and -invoke CLI flag let you attach imperative side-effects — Lambda invocations, CloudFront invalidations, Ansible playbooks — to resource lifecycles in a declarative way. This article is a production-oriented tour of Terraform 1.14 with HCL examples, operational scenarios, and a comparison against OpenTofu. CNCF Q1 2026 data shows Terraform still holds a 71% share of cloud IaC tooling, with OpenTofu closing fast. In that environment, two 1.14 changes finally pull two long-outsourced workflows into the core. Long-standing pain Pre-1.13 workaround 1.14 answer Operational gain Bulk discovery/import of existing resources aws-cli + custom scripts + hand-written import blocks List Resources + terraform query -generate-config-out Discover, filter, and generate HCL with one command Post-deploy Lambda warmup, CloudFront invalidation, Slack alerts local-exec + null_resource + GitHub Actions post-steps action_trigger { events = [after_create] } Side effects visible in plan/apply One-shot secrets (passwords, tokens) Risk of plaintext in state (1.11) Ephemeral resources + write-only attributes, stabilized in 1.14 One-shot values without polluting state Splitting large module graphs terragrunt run-all + dir sharding HCP Terraform Stacks, plugin bug fixed in 1.14.9 Deploy/rollback per component Modules blocked by unknown values Multi-step apply (Experimental) Deferred actions scheduled for 1.16 Path to count/for_each with unknowns The key insight: 1.14 breaks Terraform's "it only manages what it knows" limit from both directions at once. List Resources pulls outside resources in; Actions push inside intent out. The line between IaC and automation scripts just narrowed. .tfquery.hcl and terraform query List Resources live in a separate .tfquery.hcl file for a clear reason: they are a read-only discovery graph that must not be mixed into the normal plan graph. The terraform query command evaluates .tfquery.hcl files in the current directory, calls the cloud API, and either prints results to the console or — with -generate-config-out — emits import + resource blocks to a new file. # find-unmanaged.tfquery.hcl # Find running EC2 in us-east-2 tagged ManagedBy=unmanaged provider "aws" { region = "us-east-2" } list "aws_instance" "unmanaged" { provider = aws config { filter { name = "tag:ManagedBy" values = ["unmanaged"] } filter { name = "instance-state-name" values = ["running"] } } } # 1) Print results to console terraform query # 2) Generate import + resource blocks automatically terraform query -generate-config-out=to-import/unmanaged.tf # 3) JSON output (for CI) terraform query -json > query.json # 4) Variable injection terraform query -var 'env=prod' terraform query -var-file=prod.tfvars The heart of the feature is -generate-config-out. The 1.5-era import block told Terraform where to map an existing resource, but you still had to know what existed. 1.14's List Resources express the "what exists" as code, and the command spits out ready-to-use import + resource scaffolds. A four-step workflow collapses into one command. list block argument Role Notes provider Provider alias used for discovery Required config { ... } Provider-specific filters / region / tags Per-resource schema limit Max results Safety net for large accounts include_resource Emit resource blocks alongside import Default false count / for_each Scan multiple scopes (accounts/regions) Same semantics as normal resources ⚠️ Warning: Not every provider exposes list schemas for every resource yet. The AWS provider supports EC2/S3/IAM and is expanding gradually; some community and official providers (e.g. terraform-provider-github) still do not support list (issue). Verify terraform query support for your target providers before standardizing this workflow. # Step 1: separate discovery dir mkdir -p discover && cd discover cat > find-prod-ec2.tfquery.hcl = 1.14 as a header comment to modules that use new features, so OpenTofu workspaces don't accidentally execute them. Terraform 1.14 is the first release to crack the five-year "pure declarative is enough" consensus. List Resources admit that resources the code doesn't know about exist and pull them inward; Actions admit that side effects the code must express exist and refuse to offload them to external automation. Both point the same way — IaC is becoming a system that continuously observes and intervenes in its environment, not a one-shot drawing tool. ManoIT recommends every 1.14 adoption come with a separate discover workspace and action-invocation guards on day one. The experimental deferred actions shipping in 1.16 will close the gaps that unknown values carve into the graph, and that's when the combination of List Resources + Actions + Deferred will reveal the IaC model of the next five years in full. This article was co-authored by the ManoIT engineering team and Anthropic's Claude Opus 4.7 LLM. Sources: Terraform v1.14.0 Release Notes, v1.14.9 Patch Notes, terraform query CLI Reference, list block reference, Invoke an action, action block reference. Originally published at ManoIT Tech Blog.
