Note: This format is available in Terraform 0.15.3 and later.
By default, many Terraform commands display UI output as unstructured text, intended to be read by a user via 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, and refresh, the -json flag outputs a stream of JSON UI messages, one per line. These can be processed one message at a time, with 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.
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"}
{"@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 output
type: 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.
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 details
action: 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.
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 details
previous_resource: object describing the previous address of the resource, if this change includes a configuration-driven move
action: the action planned to be taken for the resource. Values: noop, create, read, update, replace, delete, move.
reason: an optional reason for the change, currently only used when the action is replace or delete. Values:
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.
{"@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":"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"}
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)
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 JSON
type: for applied outputs, the detected HCL type of the output value
sensitive: 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.
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.
{"@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"}
{"@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"}
{"@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"}
{"@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"}
{"@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"}
{"@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"}
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 string
module: the address of the module containing the resource, in the form module.foo.module.bar, or an empty string for a root module resource
resource: the module-relative address, which is identical to addr for root module resources