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  ```