July 26, 2023·4 min read·engineeringterraformchecksimport

Terraform 1.5.4 executes checks during CLI import

A crash involving scoped data sources exposed a missing operation mode in check handling. Terraform 1.5.4 registers and executes checks during import.

Adding a language construct to Terraform also requires deciding which operations execute it. Plans and applies are the obvious cases, but the CLI import command walks configuration through a separate operation mode. A check block with a nested data source exposed an inconsistency in that path. Terraform 1.5.4, released on July 26, fixes the crash and makes checks execute during import operations.

The release notes describe two related corrections. Nested check data sources no longer crash when present in configuration targeted by terraform import. Checks also execute during import consistently with other checkable objects. These statements concern the existing CLI command, which remains distinct from the configuration-driven import blocks introduced in Terraform 1.5.

I like that Terraform can express infrastructure expectations beside the resources they concern. Those expectations become more useful when their execution rules are consistent across commands. A configuration should not become unusable for adoption merely because it contains an observation that normal plan and apply operations can handle.

Import walks configuration for a different purpose

The CLI import documentation at this release defines the command as terraform import [options] ADDRESS ID. It finds the remote resource identified by the provider-specific ID and adds it to state at the given address. Provider configuration comes from the configuration files or other supported provider inputs.

For an existing EC2 instance, the command can look like the following. The instance ID is illustrative and must refer to the actual object in the configured account and region.

terraform import aws_instance.example i-abcd1234

Terraform needs configuration while performing this operation, even though the command is not a general request to apply every configured resource. That makes constructs present elsewhere in the configuration relevant to import processing. The import path must decide whether to validate them, execute them, or omit them under a defined rule.

The 1.5 release changelog says configuration-driven imports did not modify the existing CLI command. Consequently, the addition of an import block did not eliminate the command's separate execution behavior. The July correction addresses that path's interaction with another new construct, the independent check block.

Checks need registration before execution

The patch and regression test change two decisions in the check graph transformer. ReportChecks now returns true for import as well as planning. ExecuteChecks now includes import alongside plan and apply in its executable operation modes. Both decisions need to agree about the work that the graph will perform.

The implementation comments explain why planning and apply differ. Planning reports the checks expected to execute. Apply reconstructs the expected checks from the plan. CLI import cannot rely on that same plan-to-apply sequence, so the transformer reports checks during import itself before they execute.

This is more specific than an instruction to ignore nested data sources while importing. The patch gives import an affirmative execution policy. It registers the checks and enables their evaluation in that mode, allowing the data-source and assertion paths to operate with the expected bookkeeping.

The regression fixture contains a managed resource plus a check with a nested data source. Its mock provider imports a managed instance and supplies the data-source behavior required by the assertion. After the import, the test expects state containing both the ordinary imported instance and the data-source result. It also asserts that the operation returns no errors.

Those tests use Terraform's internal test provider with AWS-shaped names. They establish the behavior of the core import context without requiring an actual AWS deployment. Reading the fixture as a complete production AWS example would be misleading because its mock data-source type exists for the test.

Warning semantics still distinguish checks

A check's behavior remains different from a blocking resource condition. The check documentation specifies that failed assertions warn instead of halting the operation. Errors from a data source scoped inside the check also become warnings. The new execution mode does not turn these observations into preconditions for adopting a remote object.

Scoping matters as much as failure behavior. A nested data-source result belongs to its enclosing check, so resource configuration elsewhere cannot depend on it. This keeps an observational read separate from the ordinary data dependencies used to configure managed resources. The check can inspect infrastructure without supplying a required input to the resource being imported.

I prefer that separation for system-level health observations. An import establishes Terraform's association with an existing object. A warning about an observed condition can provide useful information during that operation without changing the meaning of adoption into a request to repair every surrounding resource.

For users encountering the crash, the patch removes a reason to strip checks out of otherwise valid configuration before using the CLI command. For module authors, it makes import another operation in which check data sources and assertions can run. The relevant provider access must therefore be available during import as well as during ordinary plans. Terraform 1.5.4 now reports and executes that check work through the import graph.