github.com/hugorut/terraform@v1.1.3/website/docs/internals/machine-readable-ui.mdx (about) 1 --- 2 page_title: 'Internals: Machine-Readable UI' 3 description: >- 4 Terraform provides a machine-readable streaming JSON UI output for plan, 5 apply, and refresh operations. 6 --- 7 8 # Machine-Readable UI 9 10 -> **Note:** This format is available in Terraform 0.15.3 and later. 11 12 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. 13 14 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. 15 16 The first message output has type `version`, and includes a `ui` key, which as of Terraform 1.1.0 has 17 value `"1.0"`. The semantics of this version are: 18 19 - We will increment the minor version, e.g. `"1.1"`, for backward-compatible 20 changes or additions. Ignore any object properties with unrecognized names to 21 remain forward-compatible with future minor versions. 22 - We will increment the major version, e.g. `"2.0"`, for changes that are not 23 backward-compatible. Reject any input which reports an unsupported major 24 version. 25 26 We will introduce new major versions only within the bounds of 27 [the Terraform 1.0 Compatibility Promises](/language/v1-compatibility-promises). 28 29 ## Sample JSON Output 30 31 Below is sample output from running `terraform apply -json`: 32 33 ```javascript 34 {"@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"} 35 {"@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"} 36 {"@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"} 37 {"@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"} 38 {"@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"} 39 {"@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"} 40 {"@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"} 41 ``` 42 43 Each line consists of a JSON object with several keys common to all messages. These are: 44 45 - `@level`: this is normally "info", but can be "error" or "warn" when showing diagnostics 46 - `@message`: a human-readable summary of the contents of this message 47 - `@module`: always "terraform.ui" when rendering UI output 48 - `@timestamp`: an RFC3339 timestamp of when the message was output 49 - `type`: defines which kind of message this is and determines how to interpret other keys which may be present 50 51 Clients presenting the logs as a user interface should handle unexpected message types by presenting at least the `@message` field to the user. 52 53 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](#resource-object) can be used to link multiple messages about a single resource. 54 55 ## Message Types 56 57 The following message types are supported: 58 59 ### Generic Messages 60 61 - `version`: information about the Terraform version and the version of the schema used for the following messages 62 - `log`: unstructured human-readable log lines 63 - `diagnostic`: diagnostic warning or error messages; [see the `terraform validate` docs for more details on the format](/cli/commands/validate#json) 64 65 ### Operation Results 66 67 - `resource_drift`: describes a detected change to a single resource made outside of Terraform 68 - `planned_change`: describes a planned change to a single resource 69 - `change_summary`: summary of all planned or applied changes 70 - `outputs`: list of all root module outputs 71 72 ### Resource Progress 73 74 - `apply_start`, `apply_progress`, `apply_complete`, `apply_errored`: sequence of messages indicating progress of a single resource through apply 75 - `provision_start`, `provision_progress`, `provision_complete`, `provision_errored`: sequence of messages indicating progress of a single provisioner step 76 - `refresh_start`, `refresh_complete`: sequence of messages indicating progress of a single resource through refresh 77 78 ## Version Message 79 80 A machine-readable UI command output will always begin with a `version` message. The following message-specific keys are defined: 81 82 - `terraform`: the Terraform version which emitted this message 83 - `ui`: the machine-readable UI schema version defining the meaning of the following messages 84 85 ### Example 86 87 ```json 88 { 89 "@level": "info", 90 "@message": "Terraform 0.15.4", 91 "@module": "terraform.ui", 92 "@timestamp": "2021-05-25T13:32:41.275359-04:00", 93 "terraform": "0.15.4", 94 "type": "version", 95 "ui": "0.1.0" 96 } 97 ``` 98 99 ## Resource Drift 100 101 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: 102 103 - `resource`: object describing the address of the resource to be changed; see [resource object](#resource-object) below for details 104 - `action`: the action planned to be taken for the resource. Values: `update`, `delete`. 105 106 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](/internals/json-format). 107 108 ### Example 109 110 ```json 111 { 112 "@level": "info", 113 "@message": "random_pet.animal: Drift detected (update)", 114 "@module": "terraform.ui", 115 "@timestamp": "2021-05-25T13:32:41.705503-04:00", 116 "change": { 117 "resource": { 118 "addr": "random_pet.animal", 119 "module": "", 120 "resource": "random_pet.animal", 121 "implied_provider": "random", 122 "resource_type": "random_pet", 123 "resource_name": "animal", 124 "resource_key": null 125 }, 126 "action": "update" 127 }, 128 "type": "resource_drift" 129 } 130 ``` 131 132 ## Planned Change 133 134 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: 135 136 - `resource`: object describing the address of the resource to be changed; see [resource object](#resource-object) below for details 137 - `previous_resource`: object describing the previous address of the resource, if this change includes a configuration-driven move 138 - `action`: the action planned to be taken for the resource. Values: `noop`, `create`, `read`, `update`, `replace`, `delete`, `move`. 139 - `reason`: an optional reason for the change, currently only used when the action is `replace` or `delete`. Values: 140 - `tainted`: resource was marked as tainted 141 - `requested`: user requested that the resource be replaced, for example via the `-replace` plan flag 142 - `cannot_update`: changes to configuration force the resource to be deleted and created rather than updated 143 - `delete_because_no_resource_config`: no matching resource in configuration 144 - `delete_because_wrong_repetition`: resource instance key has no corresponding `count` or `for_each` in configuration 145 - `delete_because_count_index`: resource instance key is outside the range of the `count` argument 146 - `delete_because_each_key`: resource instance key is not included in the `for_each` argument 147 - `delete_because_no_module`: enclosing module instance is not in configuration 148 149 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](/internals/json-format). 150 151 ### Example 152 153 ```json 154 { 155 "@level": "info", 156 "@message": "random_pet.animal: Plan to create", 157 "@module": "terraform.ui", 158 "@timestamp": "2021-05-25T13:32:41.705503-04:00", 159 "change": { 160 "resource": { 161 "addr": "random_pet.animal", 162 "module": "", 163 "resource": "random_pet.animal", 164 "implied_provider": "random", 165 "resource_type": "random_pet", 166 "resource_name": "animal", 167 "resource_key": null 168 }, 169 "action": "create" 170 }, 171 "type": "planned_change" 172 } 173 ``` 174 175 ## Change Summary 176 177 Terraform outputs a change summary when a plan or apply operation completes. Both message types include a `changes` object, which has the following keys: 178 179 - `add`: count of resources to be created (including as part of replacement) 180 - `change`: count of resources to be changed in-place 181 - `remove`: count of resources to be destroyed (including as part of replacement) 182 - `operation`: one of `plan`, `apply`, or `destroy` 183 184 ### Example 185 186 ```json 187 { 188 "@level": "info", 189 "@message": "Apply complete! Resources: 1 added, 0 changed, 0 destroyed.", 190 "@module": "terraform.ui", 191 "@timestamp": "2021-05-25T13:32:41.869168-04:00", 192 "changes": { 193 "add": 1, 194 "change": 0, 195 "remove": 0, 196 "operation": "apply" 197 }, 198 "type": "change_summary" 199 } 200 ``` 201 202 ## Outputs 203 204 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: 205 206 - `action`: for planned outputs, the action which will be taken for the output. Values: `noop`, `create`, `update`, `delete` 207 - `value`: for applied outputs, the value of the output, encoded in JSON 208 - `type`: for applied outputs, the detected HCL type of the output value 209 - `sensitive`: boolean value, `true` if the output is sensitive and should be hidden from UI by default 210 211 Note that `sensitive` outputs still include the `value` field, and integrating software should respect the sensitivity value as appropriate for the given use case. 212 213 ### Example 214 215 ```json 216 { 217 "@level": "info", 218 "@message": "Outputs: 1", 219 "@module": "terraform.ui", 220 "@timestamp": "2021-05-25T13:32:41.869280-04:00", 221 "outputs": { 222 "pets": { 223 "sensitive": false, 224 "type": "string", 225 "value": "smart-lizard" 226 } 227 }, 228 "type": "outputs" 229 } 230 ``` 231 232 ## Operation Messages 233 234 Performing Terraform operations to a resource will often result in several messages being emitted. The message types include: 235 236 - `apply_start`: when starting to apply changes for a resource 237 - `apply_progress`: periodically, showing elapsed time output 238 - `apply_complete`: on successful operation completion 239 - `apply_errored`: when an error is encountered during the operation 240 - `provision_start`: when starting a provisioner step 241 - `provision_progress`: on provisioner output 242 - `provision_complete`: on successful provisioning 243 - `provision_errored`: when an error is enountered during provisioning 244 - `refresh_start`: when reading a resource during refresh 245 - `refresh_complete`: on successful refresh 246 247 Each of these messages has a `hook` object, which has different fields for each type. All hooks have a [`resource` object](#resource-object) which identifies which resource is the subject of the operation. 248 249 ## Apply Start 250 251 The `apply_start` message `hook` object has the following keys: 252 253 - `resource`: a [`resource` object](#resource-object) identifying the resource 254 - `action`: the action to be taken for the resource. Values: `noop`, `create`, `read`, `update`, `replace`, `delete` 255 - `id_key` and `id_value`: a key/value pair used to identify this instance of the resource, omitted when unknown 256 257 ### Example 258 259 ```json 260 { 261 "@level": "info", 262 "@message": "random_pet.animal: Creating...", 263 "@module": "terraform.ui", 264 "@timestamp": "2021-05-25T13:32:41.825308-04:00", 265 "hook": { 266 "resource": { 267 "addr": "random_pet.animal", 268 "module": "", 269 "resource": "random_pet.animal", 270 "implied_provider": "random", 271 "resource_type": "random_pet", 272 "resource_name": "animal", 273 "resource_key": null 274 }, 275 "action": "create" 276 }, 277 "type": "apply_start" 278 } 279 ``` 280 281 ## Apply Progress 282 283 The `apply_progress` message `hook` object has the following keys: 284 285 - `resource`: a [`resource` object](#resource-object) identifying the resource 286 - `action`: the action being taken for the resource. Values: `noop`, `create`, `read`, `update`, `replace`, `delete` 287 - `elapsed_seconds`: time elapsed since the apply operation started, expressed as an integer number of seconds 288 289 ### Example 290 291 ```json 292 { 293 "@level": "info", 294 "@message": "null_resource.none[4]: Still creating... [30s elapsed]", 295 "@module": "terraform.ui", 296 "@timestamp": "2021-03-17T09:34:26.222465-04:00", 297 "hook": { 298 "resource": { 299 "addr": "null_resource.none[4]", 300 "module": "", 301 "resource": "null_resource.none[4]", 302 "implied_provider": "null", 303 "resource_type": "null_resource", 304 "resource_name": "none", 305 "resource_key": 4 306 }, 307 "action": "create", 308 "elapsed_seconds": 30 309 }, 310 "type": "apply_progress" 311 } 312 ``` 313 314 ## Apply Complete 315 316 The `apply_complete` message `hook` object has the following keys: 317 318 - `resource`: a [`resource` object](#resource-object) identifying the resource 319 - `action`: the action taken for the resource. Values: `noop`, `create`, `read`, `update`, `replace`, `delete` 320 - `id_key` and `id_value`: a key/value pair used to identify this instance of the resource, omitted when unknown 321 - `elapsed_seconds`: time elapsed since the apply operation started, expressed as an integer number of seconds 322 323 ### Example 324 325 ```json 326 { 327 "@level": "info", 328 "@message": "random_pet.animal: Creation complete after 0s [id=smart-lizard]", 329 "@module": "terraform.ui", 330 "@timestamp": "2021-05-25T13:32:41.826179-04:00", 331 "hook": { 332 "resource": { 333 "addr": "random_pet.animal", 334 "module": "", 335 "resource": "random_pet.animal", 336 "implied_provider": "random", 337 "resource_type": "random_pet", 338 "resource_name": "animal", 339 "resource_key": null 340 }, 341 "action": "create", 342 "id_key": "id", 343 "id_value": "smart-lizard", 344 "elapsed_seconds": 0 345 }, 346 "type": "apply_complete" 347 } 348 ``` 349 350 ## Apply Errored 351 352 The `apply_complete` message `hook` object has the following keys: 353 354 - `resource`: a [`resource` object](#resource-object) identifying the resource 355 - `action`: the action taken for the resource. Values: `noop`, `create`, `read`, `update`, `replace`, `delete` 356 - `elapsed_seconds`: time elapsed since the apply operation started, expressed as an integer number of seconds 357 358 The exact detail of the error will be rendered as a separate `diagnostic` message. 359 360 ### Example 361 362 ```json 363 { 364 "@level": "info", 365 "@message": "null_resource.none[0]: Creation errored after 10s", 366 "@module": "terraform.ui", 367 "@timestamp": "2021-03-26T16:38:54.013910-04:00", 368 "hook": { 369 "resource": { 370 "addr": "null_resource.none[0]", 371 "module": "", 372 "resource": "null_resource.none[0]", 373 "implied_provider": "null", 374 "resource_type": "null_resource", 375 "resource_name": "none", 376 "resource_key": 0 377 }, 378 "action": "create", 379 "elapsed_seconds": 10 380 }, 381 "type": "apply_errored" 382 } 383 ``` 384 385 ## Provision Start 386 387 The `provision_start` message `hook` object has the following keys: 388 389 - `resource`: a [`resource` object](#resource-object) identifying the resource 390 - `provisioner`: the type of provisioner 391 392 ### Example 393 394 ```json 395 { 396 "@level": "info", 397 "@message": "null_resource.none[0]: Provisioning with 'local-exec'...", 398 "@module": "terraform.ui", 399 "@timestamp": "2021-03-26T16:38:43.997431-04:00", 400 "hook": { 401 "resource": { 402 "addr": "null_resource.none[0]", 403 "module": "", 404 "resource": "null_resource.none[0]", 405 "implied_provider": "null", 406 "resource_type": "null_resource", 407 "resource_name": "none", 408 "resource_key": 0 409 }, 410 "provisioner": "local-exec" 411 }, 412 "type": "provision_start" 413 } 414 ``` 415 416 ## Provision Progress 417 418 The `provision_progress` message `hook` object has the following keys: 419 420 - `resource`: a [`resource` object](#resource-object) identifying the resource 421 - `provisioner`: the type of provisioner 422 - `output`: the output log from the provisioner 423 424 One `provision_progress` message is output for each log line received from the provisioner. 425 426 ### Example 427 428 ```json 429 { 430 "@level": "info", 431 "@message": "null_resource.none[0]: (local-exec): Executing: [\"/bin/sh\" \"-c\" \"sleep 10 && exit 1\"]", 432 "@module": "terraform.ui", 433 "@timestamp": "2021-03-26T16:38:43.997869-04:00", 434 "hook": { 435 "resource": { 436 "addr": "null_resource.none[0]", 437 "module": "", 438 "resource": "null_resource.none[0]", 439 "implied_provider": "null", 440 "resource_type": "null_resource", 441 "resource_name": "none", 442 "resource_key": 0 443 }, 444 "provisioner": "local-exec", 445 "output": "Executing: [\"/bin/sh\" \"-c\" \"sleep 10 && exit 1\"]" 446 }, 447 "type": "provision_progress" 448 } 449 ``` 450 451 ## Provision Complete 452 453 The `provision_complete` message `hook` object has the following keys: 454 455 - `resource`: a [`resource` object](#resource-object) identifying the resource 456 - `provisioner`: the type of provisioner 457 458 ### Example 459 460 ```json 461 { 462 "@level": "info", 463 "@message": "null_resource.none[0]: (local-exec) Provisioning complete", 464 "@module": "terraform.ui", 465 "@timestamp": "2021-03-17T09:34:06.239043-04:00", 466 "hook": { 467 "resource": { 468 "addr": "null_resource.none[0]", 469 "module": "", 470 "resource": "null_resource.none[0]", 471 "implied_provider": "null", 472 "resource_type": "null_resource", 473 "resource_name": "none", 474 "resource_key": 0 475 }, 476 "provisioner": "local-exec" 477 }, 478 "type": "provision_complete" 479 } 480 ``` 481 482 ## Provision Errored 483 484 The `provision_errored` message `hook` object has the following keys: 485 486 - `resource`: a [`resource` object](#resource-object) identifying the resource 487 - `provisioner`: the type of provisioner 488 489 ### Example 490 491 ```json 492 { 493 "@level": "info", 494 "@message": "null_resource.none[0]: (local-exec) Provisioning errored", 495 "@module": "terraform.ui", 496 "@timestamp": "2021-03-26T16:38:54.013572-04:00", 497 "hook": { 498 "resource": { 499 "addr": "null_resource.none[0]", 500 "module": "", 501 "resource": "null_resource.none[0]", 502 "implied_provider": "null", 503 "resource_type": "null_resource", 504 "resource_name": "none", 505 "resource_key": 0 506 }, 507 "provisioner": "local-exec" 508 }, 509 "type": "provision_errored" 510 } 511 ``` 512 513 ## Refresh Start 514 515 The `refresh_start` message `hook` object has the following keys: 516 517 - `resource`: a [`resource` object](#resource-object) identifying the resource 518 - `id_key` and `id_value`: a key/value pair used to identify this instance of the resource 519 520 ### Example 521 522 ```json 523 { 524 "@level": "info", 525 "@message": "null_resource.none[0]: Refreshing state... [id=1971614370559474622]", 526 "@module": "terraform.ui", 527 "@timestamp": "2021-03-26T14:18:06.508915-04:00", 528 "hook": { 529 "resource": { 530 "addr": "null_resource.none[0]", 531 "module": "", 532 "resource": "null_resource.none[0]", 533 "implied_provider": "null", 534 "resource_type": "null_resource", 535 "resource_name": "none", 536 "resource_key": 0 537 }, 538 "id_key": "id", 539 "id_value": "1971614370559474622" 540 }, 541 "type": "refresh_start" 542 } 543 ``` 544 545 ## Refresh Complete 546 547 The `refresh_complete` message `hook` object has the following keys: 548 549 - `resource`: a [`resource` object](#resource-object) identifying the resource 550 - `id_key` and `id_value`: a key/value pair used to identify this instance of the resource 551 552 ### Example 553 554 ```json 555 { 556 "@level": "info", 557 "@message": "null_resource.none[0]: Refresh complete [id=1971614370559474622]", 558 "@module": "terraform.ui", 559 "@timestamp": "2021-03-26T14:18:06.509371-04:00", 560 "hook": { 561 "resource": { 562 "addr": "null_resource.none[0]", 563 "module": "", 564 "resource": "null_resource.none[0]", 565 "implied_provider": "null", 566 "resource_type": "null_resource", 567 "resource_name": "none", 568 "resource_key": 0 569 }, 570 "id_key": "id", 571 "id_value": "1971614370559474622" 572 }, 573 "type": "refresh_complete" 574 } 575 ``` 576 577 ## Resource Object 578 579 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: 580 581 - `addr`: the full unique address of the resource as a string 582 - `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 583 - `resource`: the module-relative address, which is identical to `addr` for root module resources 584 - `resource_type`: the type of resource being addressed 585 - `resource_name`: the name label for the resource 586 - `resource_key`: the address key (`count` or `for_each` value), or `null` if the neither are used 587 - `implied_provider`: the provider type implied by the resource type; this may not reflect the resource's provider if provider aliases are used 588 589 ### Example 590 591 ```json 592 { 593 "addr": "module.pets.random_pet.pet[\"friend\"]", 594 "module": "module.pets", 595 "resource": "random_pet.pet[\"friend\"]", 596 "implied_provider": "random", 597 "resource_type": "random_pet", 598 "resource_name": "pet", 599 "resource_key": "friend" 600 } 601 ```