Terraform
Machine-readable UI Output Reference
This topic provides reference information about the machine-readable output Terraform prints.
Introduction
By default, many Terraform commands display UI output as unstructured text that is intended to be read in a terminal emulator. This text stream is not a stable interface for integrations. Some commands support a -json
flag, which enables a structured JSON output mode with a defined interface.
For long-running commands such as plan
, apply
, refresh
, and test
, the -json
flag outputs a stream of JSON UI messages. The ouptut messages appear one per line so that you can process the messages by integrating software filtering, combining, or modifying the output as desired.
The first message output has type version
, and includes a ui
key, which as of Terraform 1.1.0 has
value "1.0"
. The semantics of this version are:
- We will increment the minor version, e.g.
"1.1"
, for backward-compatible changes or additions. Ignore any object properties with unrecognized names to remain forward-compatible with future minor versions. - We will increment the major version, e.g.
"2.0"
, for changes that are not backward-compatible. Reject any input which reports an unsupported major version.
Refer to Terraform 1.0 Compatibility Promises for additional information.
Sample JSON Output
Below is sample output from running terraform apply -json
:
{"@level":"info","@message":"Terraform 0.15.4","@module":"terraform.ui","@timestamp":"2021-05-25T13:32:41.275359-04:00","terraform":"0.15.4","type":"version","ui":"0.1.0"}
{"@level":"info","@message":"random_pet.animal: Plan to create","@module":"terraform.ui","@timestamp":"2021-05-25T13:32:41.705503-04:00","change":{"resource":{"addr":"random_pet.animal","module":"","resource":"random_pet.animal","implied_provider":"random","resource_type":"random_pet","resource_name":"animal","resource_key":null},"action":"create"},"type":"planned_change"}
{"@level":"info","@message":"Plan: 1 to add, 0 to change, 0 to destroy.","@module":"terraform.ui","@timestamp":"2021-05-25T13:32:41.705638-04:00","changes":{"add":1,"change":0,"remove":0,"operation":"plan"},"type":"change_summary"}
{"@level":"info","@message":"random_pet.animal: Creating...","@module":"terraform.ui","@timestamp":"2021-05-25T13:32:41.825308-04:00","hook":{"resource":{"addr":"random_pet.animal","module":"","resource":"random_pet.animal","implied_provider":"random","resource_type":"random_pet","resource_name":"animal","resource_key":null},"action":"create"},"type":"apply_start"}
{"@level":"info","@message":"random_pet.animal: Creation complete after 0s [id=smart-lizard]","@module":"terraform.ui","@timestamp":"2021-05-25T13:32:41.826179-04:00","hook":{"resource":{"addr":"random_pet.animal","module":"","resource":"random_pet.animal","implied_provider":"random","resource_type":"random_pet","resource_name":"animal","resource_key":null},"action":"create","id_key":"id","id_value":"smart-lizard","elapsed_seconds":0},"type":"apply_complete"}
{"@level":"info","@message":"Apply complete! Resources: 1 added, 0 changed, 0 destroyed.","@module":"terraform.ui","@timestamp":"2021-05-25T13:32:41.869168-04:00","changes":{"add":1,"change":0,"remove":0,"operation":"apply"},"type":"change_summary"}
{"@level":"info","@message":"Outputs: 1","@module":"terraform.ui","@timestamp":"2021-05-25T13:32:41.869280-04:00","outputs":{"pets":{"sensitive":false,"type":"string","value":"smart-lizard"}},"type":"outputs"}
Each line consists of a JSON object with several keys common to all messages. These are:
@level
: this is normally "info", but can be "error" or "warn" when showing diagnostics@message
: a human-readable summary of the contents of this message@module
: always "terraform.ui" when rendering UI output@timestamp
: an RFC3339 timestamp of when the message was outputtype
: defines which kind of message this is and determines how to interpret other keys which may be present
Clients presenting the logs as a user interface should handle unexpected message types by presenting at least the @message
field to the user.
Messages will be emitted as events occur to trigger them. This means that messages related to several resources may be interleaved (if Terraform is running with concurrency above 1). The resource
object value can be used to link multiple messages about a single resource.
Message Types
The following message types are supported:
Generic Messages
version
: information about the Terraform version and the version of the schema used for the following messageslog
: unstructured human-readable log linesdiagnostic
: diagnostic warning or error messages; see theterraform validate
docs for more details on the format
Operation Results
resource_drift
: describes a detected change to a single resource made outside of Terraformplanned_change
: describes a planned change to a single resourcechange_summary
: summary of all planned or applied changesoutputs
: list of all root module outputs
Resource Progress
apply_start
,apply_progress
,apply_complete
,apply_errored
: sequence of messages indicating progress of a single resource through applyprovision_start
,provision_progress
,provision_complete
,provision_errored
: sequence of messages indicating progress of a single provisioner steprefresh_start
,refresh_complete
: sequence of messages indicating progress of a single resource through refresh
Test Results
test_abstract
: describes the test operation that Terraform executestest_file
: describes the status of a completed test filetest_run
: describes the status of a completedrun
block within a test filetest_cleanup
: describes the result of the test cleanup after a completed test filetest_summary
: describes the overall status of the completed test operationtest_plan
: describes the output of a givenrun
block whencommand = plan
test_state
: describes the output of a givenrun
block whencommand = apply
test_interrupt
: describes the result of an interrupted test operation
Version Message
A machine-readable UI command output will always begin with a version
message. The following message-specific keys are defined:
terraform
: the Terraform version which emitted this messageui
: the machine-readable UI schema version defining the meaning of the following messages
Example
{
"@level": "info",
"@message": "Terraform 0.15.4",
"@module": "terraform.ui",
"@timestamp": "2021-05-25T13:32:41.275359-04:00",
"terraform": "0.15.4",
"type": "version",
"ui": "0.1.0"
}
Resource Drift
If drift is detected during planning, Terraform will emit a resource_drift
message for each resource which has changed outside of Terraform. This message has an embedded change
object with the following keys:
resource
: object describing the address of the resource to be changed; see resource object below for detailsaction
: the action planned to be taken for the resource. Values:update
,delete
.
This message does not include details about the exact changes which caused the change to be planned. That information is available in the JSON plan output.
Example
{
"@level": "info",
"@message": "random_pet.animal: Drift detected (update)",
"@module": "terraform.ui",
"@timestamp": "2021-05-25T13:32:41.705503-04:00",
"change": {
"resource": {
"addr": "random_pet.animal",
"module": "",
"resource": "random_pet.animal",
"implied_provider": "random",
"resource_type": "random_pet",
"resource_name": "animal",
"resource_key": null
},
"action": "update"
},
"type": "resource_drift"
}
Planned Change
At the end of a plan or before an apply, Terraform will emit a planned_change
message for each resource which has changes to apply. This message has an embedded change
object with the following keys:
resource
: object describing the address of the resource to be changed; see resource object below for detailsprevious_resource
: object describing the previous address of the resource, if this change includes a configuration-driven moveaction
: the action planned to be taken for the resource. Values:noop
,create
,read
,update
,replace
,delete
,move
,import
.reason
: an optional reason for the change, only used when the action isreplace
ordelete
. Values:tainted
: resource was marked as taintedrequested
: user requested that the resource be replaced, for example via the-replace
plan flagcannot_update
: changes to configuration force the resource to be deleted and created rather than updateddelete_because_no_resource_config
: no matching resource in configurationdelete_because_wrong_repetition
: resource instance key has no correspondingcount
orfor_each
in configurationdelete_because_count_index
: resource instance key is outside the range of thecount
argumentdelete_because_each_key
: resource instance key is not included in thefor_each
argumentdelete_because_no_module
: enclosing module instance is not in configuration
This message does not include details about the exact changes which caused the change to be planned. That information is available in the JSON plan output.
Example
{
"@level": "info",
"@message": "random_pet.animal: Plan to create",
"@module": "terraform.ui",
"@timestamp": "2021-05-25T13:32:41.705503-04:00",
"change": {
"resource": {
"addr": "random_pet.animal",
"module": "",
"resource": "random_pet.animal",
"implied_provider": "random",
"resource_type": "random_pet",
"resource_name": "animal",
"resource_key": null
},
"action": "create"
},
"type": "planned_change"
}
Change Summary
Terraform outputs a change summary when a plan or apply operation completes. Both message types include a changes
object, which has the following keys:
add
: count of resources to be created (including as part of replacement)change
: count of resources to be changed in-placeremove
: count of resources to be destroyed (including as part of replacement)operation
: one ofplan
,apply
, ordestroy
Example
{
"@level": "info",
"@message": "Apply complete! Resources: 1 added, 0 changed, 0 destroyed.",
"@module": "terraform.ui",
"@timestamp": "2021-05-25T13:32:41.869168-04:00",
"changes": {
"add": 1,
"change": 0,
"remove": 0,
"operation": "apply"
},
"type": "change_summary"
}
Outputs
After a successful plan or apply, a message with type outputs
contains the values of all root module output values. This message contains an outputs
object, the keys of which are the output names. The outputs values are objects with the following keys:
action
: for planned outputs, the action which will be taken for the output. Values:noop
,create
,update
,delete
value
: for applied outputs, the value of the output, encoded in JSONtype
: for applied outputs, the detected HCL type of the output valuesensitive
: boolean value,true
if the output is sensitive and should be hidden from UI by default
Note that sensitive
outputs still include the value
field, and integrating software should respect the sensitivity value as appropriate for the given use case.
Example
{
"@level": "info",
"@message": "Outputs: 1",
"@module": "terraform.ui",
"@timestamp": "2021-05-25T13:32:41.869280-04:00",
"outputs": {
"pets": {
"sensitive": false,
"type": "string",
"value": "smart-lizard"
}
},
"type": "outputs"
}
Operation Messages
Performing Terraform operations to a resource will often result in several messages being emitted. The message types include:
apply_start
: when starting to apply changes for a resourceapply_progress
: periodically, showing elapsed time outputapply_complete
: on successful operation completionapply_errored
: when an error is encountered during the operationprovision_start
: when starting a provisioner stepprovision_progress
: on provisioner outputprovision_complete
: on successful provisioningprovision_errored
: when an error is enountered during provisioningrefresh_start
: when reading a resource during refreshrefresh_complete
: on successful refreshephemeral_op_start
: when starting an ephemeral resource operationephemeral_op_progress
: periodically showing elapsed time output during ephemeral resource operationephemeral_op_complete
: on successful ephemeral resource operation completionephemeral_op_errored
: when an error is encountered during ephemeral resource operation
Each of these messages has a hook
object, which has different fields for each type. All hooks have a resource
object which identifies which resource is the subject of the operation.
Apply Start
The apply_start
message hook
object has the following keys:
resource
: aresource
object identifying the resourceaction
: the action to be taken for the resource. Values:noop
,create
,read
,update
,replace
,delete
id_key
andid_value
: a key/value pair used to identify this instance of the resource, omitted when unknown
Example
{
"@level": "info",
"@message": "random_pet.animal: Creating...",
"@module": "terraform.ui",
"@timestamp": "2021-05-25T13:32:41.825308-04:00",
"hook": {
"resource": {
"addr": "random_pet.animal",
"module": "",
"resource": "random_pet.animal",
"implied_provider": "random",
"resource_type": "random_pet",
"resource_name": "animal",
"resource_key": null
},
"action": "create"
},
"type": "apply_start"
}
Apply Progress
The apply_progress
message hook
object has the following keys:
resource
: aresource
object identifying the resourceaction
: the action being taken for the resource. Values:noop
,create
,read
,update
,replace
,delete
elapsed_seconds
: time elapsed since the apply operation started, expressed as an integer number of seconds
Example
{
"@level": "info",
"@message": "null_resource.none[4]: Still creating... [30s elapsed]",
"@module": "terraform.ui",
"@timestamp": "2021-03-17T09:34:26.222465-04:00",
"hook": {
"resource": {
"addr": "null_resource.none[4]",
"module": "",
"resource": "null_resource.none[4]",
"implied_provider": "null",
"resource_type": "null_resource",
"resource_name": "none",
"resource_key": 4
},
"action": "create",
"elapsed_seconds": 30
},
"type": "apply_progress"
}
Apply Complete
The apply_complete
message hook
object has the following keys:
resource
: aresource
object identifying the resourceaction
: the action taken for the resource. Values:noop
,create
,read
,update
,replace
,delete
id_key
andid_value
: a key/value pair used to identify this instance of the resource, omitted when unknownelapsed_seconds
: time elapsed since the apply operation started, expressed as an integer number of seconds
Example
{
"@level": "info",
"@message": "random_pet.animal: Creation complete after 0s [id=smart-lizard]",
"@module": "terraform.ui",
"@timestamp": "2021-05-25T13:32:41.826179-04:00",
"hook": {
"resource": {
"addr": "random_pet.animal",
"module": "",
"resource": "random_pet.animal",
"implied_provider": "random",
"resource_type": "random_pet",
"resource_name": "animal",
"resource_key": null
},
"action": "create",
"id_key": "id",
"id_value": "smart-lizard",
"elapsed_seconds": 0
},
"type": "apply_complete"
}
Apply Errored
The apply_complete
message hook
object has the following keys:
resource
: aresource
object identifying the resourceaction
: the action taken for the resource. Values:noop
,create
,read
,update
,replace
,delete
elapsed_seconds
: time elapsed since the apply operation started, expressed as an integer number of seconds
The exact detail of the error will be rendered as a separate diagnostic
message.
Example
{
"@level": "info",
"@message": "null_resource.none[0]: Creation errored after 10s",
"@module": "terraform.ui",
"@timestamp": "2021-03-26T16:38:54.013910-04:00",
"hook": {
"resource": {
"addr": "null_resource.none[0]",
"module": "",
"resource": "null_resource.none[0]",
"implied_provider": "null",
"resource_type": "null_resource",
"resource_name": "none",
"resource_key": 0
},
"action": "create",
"elapsed_seconds": 10
},
"type": "apply_errored"
}
Provision Start
The provision_start
message hook
object has the following keys:
resource
: aresource
object identifying the resourceprovisioner
: the type of provisioner
Example
{
"@level": "info",
"@message": "null_resource.none[0]: Provisioning with 'local-exec'...",
"@module": "terraform.ui",
"@timestamp": "2021-03-26T16:38:43.997431-04:00",
"hook": {
"resource": {
"addr": "null_resource.none[0]",
"module": "",
"resource": "null_resource.none[0]",
"implied_provider": "null",
"resource_type": "null_resource",
"resource_name": "none",
"resource_key": 0
},
"provisioner": "local-exec"
},
"type": "provision_start"
}
Provision Progress
The provision_progress
message hook
object has the following keys:
resource
: aresource
object identifying the resourceprovisioner
: the type of provisioneroutput
: the output log from the provisioner
One provision_progress
message is output for each log line received from the provisioner.
Example
{
"@level": "info",
"@message": "null_resource.none[0]: (local-exec): Executing: [\"/bin/sh\" \"-c\" \"sleep 10 && exit 1\"]",
"@module": "terraform.ui",
"@timestamp": "2021-03-26T16:38:43.997869-04:00",
"hook": {
"resource": {
"addr": "null_resource.none[0]",
"module": "",
"resource": "null_resource.none[0]",
"implied_provider": "null",
"resource_type": "null_resource",
"resource_name": "none",
"resource_key": 0
},
"provisioner": "local-exec",
"output": "Executing: [\"/bin/sh\" \"-c\" \"sleep 10 && exit 1\"]"
},
"type": "provision_progress"
}
Provision Complete
The provision_complete
message hook
object has the following keys:
resource
: aresource
object identifying the resourceprovisioner
: the type of provisioner
Example
{
"@level": "info",
"@message": "null_resource.none[0]: (local-exec) Provisioning complete",
"@module": "terraform.ui",
"@timestamp": "2021-03-17T09:34:06.239043-04:00",
"hook": {
"resource": {
"addr": "null_resource.none[0]",
"module": "",
"resource": "null_resource.none[0]",
"implied_provider": "null",
"resource_type": "null_resource",
"resource_name": "none",
"resource_key": 0
},
"provisioner": "local-exec"
},
"type": "provision_complete"
}
Provision Errored
The provision_errored
message hook
object has the following keys:
resource
: aresource
object identifying the resourceprovisioner
: the type of provisioner
Example
{
"@level": "info",
"@message": "null_resource.none[0]: (local-exec) Provisioning errored",
"@module": "terraform.ui",
"@timestamp": "2021-03-26T16:38:54.013572-04:00",
"hook": {
"resource": {
"addr": "null_resource.none[0]",
"module": "",
"resource": "null_resource.none[0]",
"implied_provider": "null",
"resource_type": "null_resource",
"resource_name": "none",
"resource_key": 0
},
"provisioner": "local-exec"
},
"type": "provision_errored"
}
Refresh Start
The refresh_start
message hook
object has the following keys:
resource
: aresource
object identifying the resourceid_key
andid_value
: a key/value pair used to identify this instance of the resource
Example
{
"@level": "info",
"@message": "null_resource.none[0]: Refreshing state... [id=1971614370559474622]",
"@module": "terraform.ui",
"@timestamp": "2021-03-26T14:18:06.508915-04:00",
"hook": {
"resource": {
"addr": "null_resource.none[0]",
"module": "",
"resource": "null_resource.none[0]",
"implied_provider": "null",
"resource_type": "null_resource",
"resource_name": "none",
"resource_key": 0
},
"id_key": "id",
"id_value": "1971614370559474622"
},
"type": "refresh_start"
}
Refresh Complete
The refresh_complete
message hook
object has the following keys:
resource
: aresource
object identifying the resourceid_key
andid_value
: a key/value pair used to identify this instance of the resource
Example
{
"@level": "info",
"@message": "null_resource.none[0]: Refresh complete [id=1971614370559474622]",
"@module": "terraform.ui",
"@timestamp": "2021-03-26T14:18:06.509371-04:00",
"hook": {
"resource": {
"addr": "null_resource.none[0]",
"module": "",
"resource": "null_resource.none[0]",
"implied_provider": "null",
"resource_type": "null_resource",
"resource_name": "none",
"resource_key": 0
},
"id_key": "id",
"id_value": "1971614370559474622"
},
"type": "refresh_complete"
}
Ephemeral Operation Start
The ephemeral_op_start
message hook
object has the following keys:
resource
: aresource
object identifying the resourceaction
: the action the ephemeral resource is going through. Values:open
,renew
,close
Example
{
"@level": "info",
"@message": "ephemeral.random_password.example: Opening...",
"@module": "terraform.ui",
"@timestamp": "2024-10-30T10:34:26.222465-00:00",
"hook": {
"resource": {
"addr": "ephemeral.random_password.example",
"module": "",
"resource": "ephemeral.random_password.example",
"implied_provider": "random",
"resource_type": "random_password",
"resource_name": "example",
"resource_key": null
},
"action": "open"
},
"type": "ephemeral_op_start"
}
Ephemeral Operation Progress
The ephemeral_op_progress
message hook
object has the following keys:
resource
: aresource
object identifying the resourceaction
: the action the ephemeral resource is going through. Values:open
,renew
,close
elapsed_seconds
: time elapsed since the operation started, expressed as an integer number of seconds
Example
{
"@level": "info",
"@message": "ephemeral.random_password.example: Closing... [3s elapsed]",
"@module": "terraform.ui",
"@timestamp": "2024-10-30T10:34:26.222465-00:00",
"hook": {
"resource": {
"addr": "ephemeral.random_password.example",
"module": "",
"resource": "ephemeral.random_password.example",
"implied_provider": "random",
"resource_type": "random_password",
"resource_name": "example",
"resource_key": null
},
"action": "close",
"elapsed_seconds": 3
},
"type": "ephemeral_op_progress"
}
Ephemeral Operation Complete
The ephemeral_op_start
message hook
object has the following keys:
resource
: aresource
object identifying the resourceaction
: the action the ephemeral resource is going through. Values:open
,renew
,close
elapsed_seconds
: time elapsed since the operation started, expressed as an integer number of seconds
Example
{
"@level": "info",
"@message": "ephemeral.random_password.example: Opening complete after 1s",
"@module": "terraform.ui",
"@timestamp": "2024-10-30T10:34:26.222465-00:00",
"hook": {
"resource": {
"addr": "ephemeral.random_password.example",
"module": "",
"resource": "ephemeral.random_password.example",
"implied_provider": "random",
"resource_type": "random_password",
"resource_name": "example",
"resource_key": null
},
"action": "open",
"elapsed_seconds": 1
},
"type": "ephemeral_op_complete"
}
Ephemeral Operation Errored
The ephemeral_op_start
message hook
object has the following keys:
resource
: aresource
object identifying the resourceaction
: the action the ephemeral resource is going through. Values:open
,renew
,close
elapsed_seconds
: time elapsed since the operation started, expressed as an integer number of seconds
The exact detail of the error will be rendered as a separate diagnostic
message.
Example
{
"@level": "info",
"@message": "ephemeral.random_password.example: Opening errored after 2s",
"@module": "terraform.ui",
"@timestamp": "2024-10-30T10:34:26.222465-00:00",
"hook": {
"resource": {
"addr": "ephemeral.random_password.example",
"module": "",
"resource": "ephemeral.random_password.example",
"implied_provider": "random",
"resource_type": "random_password",
"resource_name": "example",
"resource_key": null
},
"action": "open",
"elapsed_seconds": 2
},
"type": "ephemeral_op_errored"
}
Resource Object
The resource
object is a decomposed structure representing a resource address in configuration, which is used to identify which resource a given message is associated with. The object has the following keys:
addr
: the full unique address of the resource as a stringmodule
: the address of the module containing the resource, in the formmodule.foo.module.bar
, or an empty string for a root module resourceresource
: the module-relative address, which is identical toaddr
for root module resourcesresource_type
: the type of resource being addressedresource_name
: the name label for the resourceresource_key
: the address key (count
orfor_each
value), ornull
if the neither are usedimplied_provider
: the provider type implied by the resource type; this may not reflect the resource's provider if provider aliases are used
Example
{
"addr": "module.pets.random_pet.pet[\"friend\"]",
"module": "module.pets",
"resource": "random_pet.pet[\"friend\"]",
"implied_provider": "random",
"resource_type": "random_pet",
"resource_name": "pet",
"resource_key": "friend"
}
Test Abstract
The terraform test
command emits a test_abstract
message describing the test files and run
blocks that Terraform executes during the upcoming operation.
Example
{
"@level": "info",
"@message": "Found 1 file and 2 run blocks",
"@module": "terraform.ui",
"@timestamp": "2023-08-09T16:12:30.325582+02:00",
"test_abstract": {
"validation.tftest.hcl": [
"passed_validation",
"failed_validatation"
]
},
"type": "test_abstract"
}
Test File
Throughout a terraform test
execution, Terraform will produce several progress updates for each test file. The progress field can be starting
, teardown
, or complete
. Each test file will emit each progress update exactly once. When a test file emits the complete
progress update, it will also include a status field containing one of pass
, error
, fail
, or skip
denoting the overall status of the completed test file.
Example
{
"@level": "info",
"@message": "main.tftest.hcl... pass",
"@module": "terraform.ui",
"@testfile": "validation.tftest.hcl",
"@timestamp": "2023-08-09T16:12:30.724368+02:00",
"test_file": {
"path": "validation.tftest.hcl",
"progress": "complete",
"status": "pass"
},
"type": "test_file"
}
Test Run
While executing run
blocks within a test file, Terraform will also produce several status updates for each run
block. The progress field for a run
block progress update can be starting
, running
, teardown
, and complete
. The starting
and complete
progress updates will be emitted exactly once. While the running
and teardown
progress updates can be emitted multiple times.
The starting
, running
and teardown
updates will also include an elapsed
field indicating the number of milliseconds the current test operation (for starting
and running
) or the current destroy operation (for teardown
) has been in progress.
The complete
progress update will also include a status
field containing one of pass
, error
, fail
, or skip
denoting the overall status of the completed run
block`.
Not every run
block will emit teardown
progress updates, as only the most recently executed run
blocks reference the latest in-memory state files that need to be torn down. In addition, the run
block tear down process is only initiated once the overall test file has already emitted its teardown
status update. This means you can expect the complete
progress update to be issued for a run
block before any teardown
updates are provided. There will always be a complete
progress update issued by the enclosing test file when the tear down process for all run
blocks is complete.
Examples
{
"@level": "info",
"@message": " \"successful_validation\"... pass",
"@module": "terraform.ui",
"@testfile": "validation.tftest.hcl",
"@testrun": "successful_validation",
"@timestamp": "2023-08-09T16:12:30.724407+02:00",
"test_run": {
"path": "main.tftest.hcl",
"run": "successful_validation",
"progress": "complete",
"status": "pass"
},
"type": "test_run"
}
{
"@level": "info",
"@message": " \"successful_validation\"... in progress",
"@module": "terraform.ui",
"@testfile": "validation.tftest.hcl",
"@testrun": "successful_validation",
"@timestamp": "2023-08-09T16:12:30.724407+02:00",
"test_run": {
"path": "main.tftest.hcl",
"run": "successful_validation",
"progress": "running",
"elapsed": 2024
},
"type": "test_run"
}
Test Cleanup
After Terraform completes the execution of each test file, terraform test
may emit a series of test_cleanup
messages detailing any state it could not destroy. You must locate and destroy the resources listed in these resources manually.
As the test framework can manage multiple state files for each test file, you can see multiple versions of this message for each state file that holds resources that Terraform could not destroy. Using the @testrun
field, you can pinpoint the run block that last updated the state file to locate the resources that Terraform could not destroy.
Example
{
"@level": "info",
"@message": "Terraform left some resources in state after executing main.tftest.hcl, they need to be cleaned up manually.",
"@module": "terraform.ui",
"@testfile": "validation.tftest.hcl",
"@testrun": "successful_validation",
"@timestamp": "2023-08-09T16:12:30.724407+02:00",
"test_cleanup": {
"failed_resources": [
{
"instance": "aws_instance.primary"
},
{
"instance": "aws_instance.secondary"
}
]
},
"type": "test_cleanup"
}
Test Summary
After the test operation has completed all test files, terraform test
emits a test_summary
message with the status of the overall test operation.
Example
{
"@level": "info",
"@message": "Success! 2 passed, 0 failed.",
"@module": "terraform.ui",
"@timestamp": "2023-08-09T16:26:45.482070+02:00",
"test_summary": {
"status": "pass",
"passed": 2,
"failed": 0,
"errored": 0,
"skipped": 0
},
"type": "test_summary"
}
Test Plan
In -verbose
mode, terraform test
emits a test_plan
message for all run
blocks that executed a plan operation. The test_plan
message contains a subset of the attributes from the terraform show -json <planfile>
command output and the terraform providers schema -json
command output.
The message contains the following fields representing the plan: plan_format_version
, output_changes
, resource_changes
, resource_drift
and relevant_attributes
. These match the respective fields in the JSON Plan Representation.
The message contains the following fields representing the provider schemas: provider_format_version
and provider_schemas
. These match the respective fields in the JSON Providers Schema Representation.
Example
{
"@level": "info",
"@message": "-verbose flag enabled, printing plan",
"@module": "terraform.ui",
"@testfile": "validation.tftest.hcl",
"@testrun": "successful_validation",
"@timestamp": "2023-08-09T17:10:06.211942+02:00",
"test_plan": {
"plan_format_version": "1.2",
"resource_changes": [
{
"address": "aws_instance.primary",
"mode": "managed",
"type": "aws_instance",
"name": "primary",
"provider_name": "registry.terraform.io/hashicorp/aws",
"change": {
"actions": [
"create"
],
"before": null,
"after": {
"ami": "af84f887-e3eb-9e52-5f8b-8a2803734fd0"
},
"after_unknown": {},
"before_sensitive": false,
"after_sensitive": {}
}
}
],
"provider_format_version": "1.0",
"provider_schemas": {
"registry.terraform.io/hashicorp/aws": {
"provider": {
"version": 0
},
"resource_schemas": {
"aws_instance": {
"version": 0,
"block": {
"attributes": {
"ami": {
"type": "string",
"description_kind": "plain",
"required": true
}
},
"description_kind": "plain"
}
}
}
}
}
},
"type": "test_plan"
}
Test State
In -verbose
mode, terraform test
emits a test_state
message for all run
blocks that executed an apply operation. The test_state
message contains a subset of the terraform show -json
command output and the terraform providers schema -json
command output.
The message contains the following fields representing the state: state_format_version
, root_module
, and outputs
. These match the respective fields in the JSON Values Representation that are embedded in complete JSON state representation.
The message contains the following fields representing the provider schemas: provider_format_version
and provider_schemas
. These match the respective fields in the JSON Providers Schema Representation.
Example
{
"@level": "info",
"@message": "-verbose flag enabled, printing state",
"@module": "terraform.ui",
"@testfile": "validation.tftest.hcl",
"@testrun": "successful_validation",
"@timestamp": "2023-08-09T17:18:21.173008+02:00",
"test_state": {
"state_format_version": "1.0",
"root_module": {
"resources": [
{
"address": "aws_instance.primary",
"mode": "managed",
"type": "aws_instance",
"name": "primary",
"provider_name": "registry.terraform.io/hashicorp/aws",
"schema_version": 0,
"values": {
"ami": "af84f887-e3eb-9e52-5f8b-8a2803734fd0"
},
"sensitive_values": {}
}
]
},
"provider_format_version": "1.0",
"provider_schemas": {
"registry.terraform.io/hashicorp/aws": {
"provider": {
"version": 0
},
"resource_schemas": {
"aws_instance": {
"version": 0,
"block": {
"attributes": {
"ami": {
"type": "string",
"description_kind": "plain",
"required": true
}
},
"description_kind": "plain"
}
}
}
}
}
},
"type": "test_state"
}
Test Interrupt
When terraform test
is impeded or canceled, it emits a test_interrupt
message that describes the interrupted operation. This message includes any state that Terraform could not destroy before exiting and any leftover resources that Terraform did not finish creating.
As with the Test Cleanup message, Terraform might have been maintaining multiple state files. The state
field contains the resources from the main state for the test configuration, while the states
field contains a map of run
block names to the resources that each run
block created, which Terraform could not destroy.
Finally, the planned
field contains any resources that were in the process of being created by the interrupted run
block, which you can identify using the @testrun
field.
Example
{
"@level": "info",
"@message": "-verbose flag enabled, printing state",
"@module": "terraform.ui",
"@testfile": "validation.tftest.hcl",
"@testrun": "successful_validation",
"@timestamp": "2023-08-09T17:18:21.173008+02:00",
"test_interrupt": {
"state": [
{
"instance": "aws_instance.primary"
}
],
"states": {
"unsuccessful_validation": [
{
"instance": "aws_instance.secondary"
}
]
},
"planned": [
"aws_instance.secondary"
]
},
"type": "test_interrupt"
}