Terraform 1.14 adds infrastructure queries and provider actions
Terraform 1.14 separates discovery from import and gives providers a way to describe operations outside resource CRUD. Both additions make provider capabilities more important.
Existing infrastructure and operational commands fit awkwardly into a model centered on resource creation and subsequent reconciliation. Finding objects before importing them is a different task from managing objects already bound to state. Invoking an operation such as a cache invalidation is different again. Terraform 1.14.0, released on November 19, introduces list resources and terraform query for discovery, alongside provider-defined actions for operations outside the normal create, read, update and delete model.
I reach for Terraform because its language makes infrastructure APIs reusable. These additions interest me because they give two previously awkward activities explicit forms. Their value depends on preserving the difference between discovering an object, accepting management of it, and invoking an operation that does not represent a continuously reconciled resource.
Discovery has its own configuration files
The query command implementation searches the current configuration for .tfquery.hcl files. It uses configured providers to execute list operations and prints matching results. The command can also generate configuration intended for importing those results. Provider implementations therefore determine what can be queried and how a particular list operation selects objects.
The file distinction is useful. A discovery expression describes what to search for in an existing environment. A resource declaration describes an object Terraform should manage. Keeping those roles explicit makes it possible to review a search before deciding which results belong in managed configuration.
The command also accepts variables and variable files for its query inputs. That lets a query express a reusable search with parameters, instead of requiring an operator to edit identifiers directly into the source each time. The parameters still need a defined meaning in the selected provider's list schema. A general query command cannot supply a universal filtering language independently of the providers implementing the remote operations.
Generated configuration proposes a management boundary
The command's -generate-config-out option produces resource and import blocks for discovered results. The output path must not already exist. This makes generation a distinct artifact-producing step, rather than an implicit request to overwrite the operator's existing resource definitions.
For an initialized configuration containing suitable query files, the invocation can be short. The provider and query definitions supply the discovery behavior.
terraform query -generate-config-out=discovered.tf
The resulting file should be understood as a proposal for managed configuration. Finding an object and generating an import block do not establish that every returned object belongs in the same state or that every observed setting expresses the intended long-term policy. Discovery reduces the effort needed to obtain identities and initial configuration. The management decision still concerns the relationship the author is asking Terraform to maintain.
This distinction follows from Terraform's existing state model. State binds resource instances in configuration to objects in remote systems. Import establishes that relationship for something already present. A query can supply candidates for the relationship without itself making the candidates interchangeable with resources already under management.
A useful adoption process can therefore retain the query as evidence of how the candidates were selected. The generated definitions describe the proposed new management scope. Those artifacts answer different questions, and retaining that distinction helps a reviewer reason about why each existing object is being added.
Providers can improve generated resource values
The configuration-generation protocol change adds a provider RPC for producing resource configuration. This gives the implementation that understands a remote resource's schema a role in producing more precise configuration values during import. The release notes identify this capability separately from the query command itself.
That division matters because a remote object's readable state is not automatically an ideal declaration of desired configuration. Some values describe observations, while others are inputs the author intends to manage. The provider has resource-specific knowledge that generic generation cannot infer solely from the presence of fields in a returned object.
As a provider author, I find this a useful allocation of responsibility. Core Terraform can coordinate generation, but a provider is better placed to explain how its resource state corresponds to valid configuration. The capability does not eliminate review. It improves the information available to the author making the management decision.
The protocol addition also means that support depends on the provider implementation. Upgrading the CLI supplies the new coordination mechanism. It cannot retroactively add resource-specific generation logic to every installed provider. Compatibility claims need to identify the provider capability as well as the core executable version.
The released provider protocol makes that exchange concrete. A generation request identifies a resource type and supplies its state. The response returns configuration data and diagnostics. That design gives the provider an opportunity to reject or explain a conversion, rather than returning only text that the CLI must assume is usable. It also separates resource-specific value selection from the final presentation of generated configuration. A caller can assess diagnostics before treating the output as an acceptable declaration. The request's resource type is therefore part of the interpretation, even when two remote objects happen to expose fields with similar names.
Query validation does not require running discovery
The query-validation change adds a way to validate query configuration without executing list operations against the remote infrastructure. The released validate command includes query files when its query flag is selected. This provides an explicit check for a configuration category that ordinary validation would otherwise omit.
terraform validate -query
Validation and discovery establish different facts. A valid query configuration can still return no objects, encounter remote access restrictions or describe a search with a broader scope than intended. Offline validation addresses the configuration's validity. Executing the query establishes what the configured provider returns in the target environment.
That separation makes query files easier to include in a normal source-review process. An author can check syntax and configuration relationships before a run with remote credentials. The eventual discovery result still needs its own assessment because it depends on the environment and the authority used to query it.
Actions give operational side effects a provider contract
The actions change enables top-level action declarations and lifecycle action triggers outside the earlier experiment. Its purpose is to represent provider-defined operations that do not fit ordinary resource CRUD. The release gives examples such as invoking a Lambda function and creating a CloudFront invalidation.
An action can be invoked through a resource lifecycle trigger or through the CLI's -invoke option. That supplies an explicit relationship between a declared operation and the point at which Terraform should request it. A command hidden inside an unrelated resource definition would make that relationship harder to inspect.
The operational distinction remains important after the action has a language construct. An invocation may cause an external effect without producing a resource whose continued existence Terraform reconciles. Whether repeating that invocation is acceptable depends on the operation. Declaring an action does not, by itself, prove that every possible provider operation is idempotent or reversible.
Lifecycle triggers have defined events
The action parser in this release accepts before_create, after_create, before_update and after_update as lifecycle trigger events. It diagnoses unsupported event names. That matters because a broad description such as lifecycle integration could otherwise imply that every resource transition already has a supported action hook.
The parser also represents the action's provider relationship and configuration separately from the trigger that refers to it. This gives the operation its own declaration while letting a resource describe when to invoke it. A reviewer can identify the action and then examine the event relationship instead of searching through an arbitrary command string for the intended operation.
I prefer that explicit relationship because infrastructure maintenance includes operations whose purpose is narrower than managing another persistent object. The distinction lets the language describe an operation honestly. It also makes the trigger's scope reviewable without inventing a resource lifecycle for an operation that has none.
The September HashiConf announcement had already described infrastructure search and actions, including the intended connection with operational automation. November's release supplies the core CLI and language capabilities. The practical result is a broader provider contract, with discovery before import and explicit operations alongside managed resources, each retaining its own meaning in the workflow.