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