github.com/hugorut/terraform@v1.1.3/website/docs/internals/json-format.mdx (about) 1 --- 2 page_title: 'Internals: JSON Output Format' 3 description: >- 4 Terraform provides a machine-readable JSON representation of state, 5 configuration and plan. 6 --- 7 8 # JSON Output Format 9 10 -> **Note:** This format is available in Terraform 0.12 and later. 11 12 When Terraform plans to make changes, it prints a human-readable summary to the terminal. It can also, when run with `-out=<PATH>`, write a much more detailed binary plan file, which can later be used to apply those changes. 13 14 Since the format of plan files isn't suited for use with external tools (and likely never will be), Terraform can output a machine-readable JSON representation of a plan file's changes. It can also convert state files to the same format, to simplify data loading and provide better long-term compatibility. 15 16 Use `terraform show -json <FILE>` to generate a JSON representation of a plan or state file. See [the `terraform show` documentation](/cli/commands/show) for more details. 17 18 The output includes a `format_version` key, which as of Terraform 1.1.0 has 19 value `"1.0"`. The semantics of this version are: 20 21 - We will increment the minor version, e.g. `"1.1"`, for backward-compatible 22 changes or additions. Ignore any object properties with unrecognized names to 23 remain forward-compatible with future minor versions. 24 - We will increment the major version, e.g. `"2.0"`, for changes that are not 25 backward-compatible. Reject any input which reports an unsupported major 26 version. 27 28 We will introduce new major versions only within the bounds of 29 [the Terraform 1.0 Compatibility Promises](/language/v1-compatibility-promises). 30 31 ## Format Summary 32 33 The following sections describe the JSON output format by example, using a pseudo-JSON notation. 34 35 Important elements are described with comments, which are prefixed with `//`. 36 37 To avoid excessive repetition, we've split the complete format into several discrete sub-objects, described under separate headers. References wrapped in angle brackets (like `<values-representation>`) are placeholders which, in the real output, would be replaced by an instance of the specified sub-object. 38 39 The JSON output format consists of the following objects and sub-objects: 40 41 - [State Representation](#state-representation) — The complete top-level object returned by `terraform show -json <STATE FILE>`. 42 - [Plan Representation](#plan-representation) — The complete top-level object returned by `terraform show -json <PLAN FILE>`. 43 - [Values Representation](#values-representation) — A sub-object of both plan and state output that describes current state or planned state. 44 - [Configuration Representation](#configuration-representation) — A sub-object of plan output that describes a parsed Terraform configuration. 45 - [Expression Representation](#expression-representation) — A sub-object of a configuration representation that describes an unevaluated expression. 46 - [Block Expressions Representation](#block-expressions-representation) — A sub-object of a configuration representation that describes the expressions nested inside a block. 47 - [Change Representation](#change-representation) — A sub-object of plan output that describes planned changes to an object. 48 49 ## State Representation 50 51 Because state does not currently have any significant metadata not covered by the common values representation ([described below](#values-representation)), the `<state-representation>` is straightforward: 52 53 ```javascript 54 { 55 // "values" is a values representation object derived from the values in the 56 // state. Because the state is always fully known, this is always complete. 57 "values": <values-representation> 58 59 "terraform_version": "version.string" 60 } 61 ``` 62 63 The extra wrapping object here will allow for any extension we may need to add in future versions of this format. 64 65 ## Plan Representation 66 67 A plan consists of a prior state, the configuration that is being applied to that state, and the set of changes Terraform plans to make to achieve that. 68 69 For ease of consumption by callers, the plan representation includes a partial representation of the values in the final state (using a [value representation](#values-representation)), allowing callers to easily analyze the planned outcome using similar code as for analyzing the prior state. 70 71 ```javascript 72 { 73 "format_version": "1.0", 74 75 // "prior_state" is a representation of the state that the configuration is 76 // being applied to, using the state representation described above. 77 "prior_state": <state-representation>, 78 79 // "configuration" is a representation of the configuration being applied to the 80 // prior state, using the configuration representation described above. 81 "configuration": <configuration-representation>, 82 83 // "planned_values" is a description of what is known so far of the outcome in 84 // the standard value representation, with any as-yet-unknown values omitted. 85 "planned_values": <values-representation>, 86 87 // "proposed_unknown" is a representation of the attributes, including any 88 // potentially-unknown attributes. Each value is replaced with "true" or 89 // "false" depending on whether it is known in the proposed plan. 90 "proposed_unknown": <values-representation>, 91 92 // "variables" is a representation of all the variables provided for the given 93 // plan. This is structured as a map similar to the output map so we can add 94 // additional fields in later. 95 "variables": { 96 "varname": { 97 "value": "varvalue" 98 }, 99 }, 100 101 // "changes" is a description of the individual change actions that Terraform 102 // plans to use to move from the prior state to a new state matching the 103 // configuration. 104 "resource_changes": [ 105 // Each element of this array describes the action to take 106 // for one instance object. All resources in the 107 // configuration are included in this list. 108 { 109 // "address" is the full absolute address of the resource instance this 110 // change applies to, in the same format as addresses in a value 111 // representation. 112 "address": "module.child.aws_instance.foo[0]", 113 114 // "previous_address" is the full absolute address of this resource 115 // instance as it was known after the previous Terraform run. 116 // Included only if the address has changed, e.g. by handling 117 // a "moved" block in the configuration. 118 "previous_address": "module.instances.aws_instance.foo[0]", 119 120 // "module_address", if set, is the module portion of the above address. 121 // Omitted if the instance is in the root module. 122 "module_address": "module.child", 123 124 // "mode", "type", "name", and "index" have the same meaning as in a 125 // value representation. 126 "mode": "managed", 127 "type": "aws_instance", 128 "name": "foo", 129 "index": 0, 130 131 // "deposed", if set, indicates that this action applies to a "deposed" 132 // object of the given instance rather than to its "current" object. 133 // Omitted for changes to the current object. "address" and "deposed" 134 // together form a unique key across all change objects in a particular 135 // plan. The value is an opaque key representing the specific deposed 136 // object. 137 "deposed": "deadbeef", 138 139 // "change" describes the change that will be made to the indicated 140 // object. The <change-representation> is detailed in a section below. 141 "change": <change-representation>, 142 143 // "action_reason" is some optional extra context about why the 144 // actions given inside "change" were selected. This is the JSON 145 // equivalent of annotations shown in the normal plan output like 146 // "is tainted, so must be replaced" as opposed to just "must be 147 // replaced". 148 // 149 // These reason codes are display hints only and the set of possible 150 // hints may change over time. Users of this must be prepared to 151 // encounter unrecognized reasons and treat them as unspecified reasons. 152 // 153 // The current set of possible values is: 154 // - "replace_because_tainted": the object in question is marked as 155 // "tainted" in the prior state, so Terraform planned to replace it. 156 // - "replace_because_cannot_update": the provider indicated that one 157 // of the requested changes isn't possible without replacing the 158 // existing object with a new object. 159 // - "replace_by_request": the user explicitly called for this object 160 // to be replaced as an option when creating the plan, which therefore 161 // overrode what would have been a "no-op" or "update" action otherwise. 162 // - "delete_because_no_resource_config": Terraform found no resource 163 // configuration corresponding to this instance. 164 // - "delete_because_no_module": The resource instance belongs to a 165 // module instance that's no longer declared, perhaps due to changing 166 // the "count" or "for_each" argument on one of the containing modules. 167 // - "delete_because_wrong_repetition": The instance key portion of the 168 // resource address isn't of a suitable type for the corresponding 169 // resource's configured repetition mode (count, for_each, or neither). 170 // - "delete_because_count_index": The corresponding resource uses count, 171 // but the instance key is out of range for the currently-configured 172 // count value. 173 // - "delete_because_each_key": The corresponding resource uses for_each, 174 // but the instance key doesn't match any of the keys in the 175 // currently-configured for_each value. 176 // 177 // If there is no special reason to note, Terraform will omit this 178 // property altogether. 179 action_reason: "replace_because_tainted" 180 } 181 ], 182 183 // "output_changes" describes the planned changes to the output values of the 184 // root module. 185 "output_changes": { 186 // Keys are the defined output value names. 187 "foo": { 188 189 // "change" describes the change that will be made to the indicated output 190 // value, using the same representation as for resource changes except 191 // that the only valid actions values are: 192 // ["create"] 193 // ["update"] 194 // ["delete"] 195 // In the Terraform CLI 0.12.0 release, Terraform is not yet fully able to 196 // track changes to output values, so the actions indicated may not be 197 // fully accurate, but the "after" value will always be correct. 198 "change": <change-representation>, 199 } 200 } 201 } 202 ``` 203 204 This overall plan structure, fully expanded, is what will be printed by the `terraform show -json <planfile>` command. 205 206 ## Values Representation 207 208 A values representation is used in both state and plan output to describe current state (which is always complete) and planned state (which omits values not known until apply). 209 210 The following example illustrates the structure of a `<values-representation>`: 211 212 ```javascript 213 { 214 // "outputs" describes the outputs from the root module. Outputs from 215 // descendent modules are not available because they are not retained in all 216 // of the underlying structures we will build this values representation from. 217 "outputs": { 218 "private_ip": { 219 "value": "192.168.3.2", 220 "sensitive": false 221 } 222 }, 223 224 // "root_module" describes the resources and child modules in the root module. 225 "root_module": { 226 "resources": [ 227 { 228 // "address" is the absolute resource address, which callers must consider 229 // opaque but may do full string comparisons with other address strings or 230 // pass this verbatim to other Terraform commands that are documented to 231 // accept absolute resource addresses. The module-local portions of this 232 // address are extracted in other properties below. 233 "address": "aws_instance.example[1]", 234 235 // "mode" can be "managed", for resources, or "data", for data resources 236 "mode": "managed", 237 "type": "aws_instance", 238 "name": "example", 239 240 // If the count or for_each meta-arguments are set for this resource, the 241 // additional key "index" is present to give the instance index key. This 242 // is omitted for the single instance of a resource that isn't using count 243 // or for_each. 244 "index": 1, 245 246 // "provider_name" is the name of the provider that is responsible for 247 // this resource. This is only the provider name, not a provider 248 // configuration address, and so no module path nor alias will be 249 // indicated here. This is included to allow the property "type" to be 250 // interpreted unambiguously in the unusual situation where a provider 251 // offers a resource type whose name does not start with its own name, 252 // such as the "googlebeta" provider offering "google_compute_instance". 253 "provider_name": "aws", 254 255 // "schema_version" indicates which version of the resource type schema 256 // the "values" property conforms to. 257 "schema_version": 2, 258 259 // "values" is the JSON representation of the attribute values of the 260 // resource, whose structure depends on the resource type schema. Any 261 // unknown values are omitted or set to null, making them 262 // indistinguishable from absent values; callers which need to distinguish 263 // unknown from unset must use the plan-specific or configuration-specific 264 // structures described in later sections. 265 "values": { 266 "id": "i-abc123", 267 "instance_type": "t2.micro", 268 // etc, etc 269 }, 270 271 // "sensitive_values" is the JSON representation of the sensitivity of 272 // the resource's attribute values. Only attributes which are sensitive 273 // are included in this structure. 274 "sensitive_values": { 275 "id": true, 276 } 277 } 278 ] 279 280 "child_modules": [ 281 // Each entry in "child_modules" has the same structure as the root_module 282 // object, with the additional "address" property shown below. 283 { 284 // "address" is the absolute module address, which callers must treat as 285 // opaque but may do full string comparisons with other module address 286 // strings and may pass verbatim to other Terraform commands that are 287 // documented as accepting absolute module addresses. 288 "address": "module.child", 289 290 // "resources" is the same as in "root_module" above 291 "resources": [ 292 { 293 "address": "module.child.aws_instance.foo", 294 // etc, etc 295 } 296 ], 297 298 // Each module object can optionally have its own 299 // nested "child_modules", recursively describing the 300 // full module tree. 301 "child_modules": [ ... ], 302 } 303 ] 304 } 305 } 306 ``` 307 308 The translation of attribute and output values is the same intuitive mapping from HCL types to JSON types used by Terraform's [`jsonencode`](/language/functions/jsonencode) function. This mapping does lose some information: lists, sets, and tuples all lower to JSON arrays while maps and objects both lower to JSON objects. Unknown values and null values are both treated as absent or null. 309 310 Only the "current" object for each resource instance is described. "Deposed" objects are not reflected in this structure at all; in plan representations, you can refer to the change representations for further details. 311 312 The intent of this structure is to give a caller access to a similar level of detail as is available to expressions within the configuration itself. This common representation is not suitable for all use-cases because it loses information compared to the data structures it is built from. For more complex needs, use the more elaborate changes and configuration representations. 313 314 ## Configuration Representation 315 316 Configuration is the most complicated structure in Terraform, since it includes unevaluated expression nodes and other complexities. 317 318 Because the configuration models are produced at a stage prior to expression evaluation, it is not possible to produce a values representation for configuration. Instead, we describe the physical structure of the configuration, giving access to constant values where possible and allowing callers to analyze any references to other objects that are present: 319 320 ```javascript 321 { 322 // "provider_configs" describes all of the provider configurations throughout 323 // the configuration tree, flattened into a single map for convenience since 324 // provider configurations are the one concept in Terraform that can span 325 // across module boundaries. 326 "provider_configs": { 327 328 // Keys in the provider_configs map are to be considered opaque by callers, 329 // and used just for lookups using the "provider_config_key" property in each 330 // resource object. 331 "opaque_provider_ref_aws": { 332 333 // "name" is the name of the provider without any alias 334 "name": "aws", 335 336 // "alias" is the alias set for a non-default configuration, or unset for 337 // a default configuration. 338 "alias": "foo", 339 340 // "module_address" is included only for provider configurations that are 341 // declared in a descendent module, and gives the opaque address for the 342 // module that contains the provider configuration. 343 "module_address": "module.child", 344 345 // "expressions" describes the provider-specific content of the 346 // configuration block, as a block expressions representation (see section 347 // below). 348 "expressions": <block-expressions-representation> 349 } 350 }, 351 352 // "root_module" describes the root module in the configuration, and serves 353 // as the root of a tree of similar objects describing descendent modules. 354 "root_module": { 355 356 // "outputs" describes the output value configurations in the module. 357 "outputs": { 358 359 // Property names here are the output value names 360 "example": { 361 "expression": <expression-representation>, 362 "sensitive": false 363 } 364 }, 365 366 // "resources" describes the "resource" and "data" blocks in the module 367 // configuration. 368 "resources": [ 369 { 370 // "address" is the opaque absolute address for the resource itself. 371 "address": "aws_instance.example", 372 373 // "mode", "type", and "name" have the same meaning as for the resource 374 // portion of a value representation. 375 "mode": "managed", 376 "type": "aws_instance", 377 "name": "example", 378 379 // "provider_config_key" is the key into "provider_configs" (shown 380 // above) for the provider configuration that this resource is 381 // associated with. 382 "provider_config_key": "opaque_provider_ref_aws", 383 384 // "provisioners" is an optional field which describes any provisioners. 385 // Connection info will not be included here. 386 "provisioners": [ 387 { 388 "type": "local-exec", 389 390 // "expressions" describes the provisioner configuration 391 "expressions": <block-expressions-representation> 392 }, 393 ], 394 395 // "expressions" describes the resource-type-specific content of the 396 // configuration block. 397 "expressions": <block-expressions-representation>, 398 399 // "schema_version" is the schema version number indicated by the 400 // provider for the type-specific arguments described in "expressions". 401 "schema_version": 2, 402 403 // "count_expression" and "for_each_expression" describe the expressions 404 // given for the corresponding meta-arguments in the resource 405 // configuration block. These are omitted if the corresponding argument 406 // isn't set. 407 "count_expression": <expression-representation>, 408 "for_each_expression": <expression-representation> 409 }, 410 ], 411 412 // "module_calls" describes the "module" blocks in the module. During 413 // evaluation, a module call with count or for_each may expand to multiple 414 // module instances, but in configuration only the block itself is 415 // represented. 416 "module_calls": { 417 418 // Key is the module call name chosen in the configuration. 419 "child": { 420 421 // "resolved_source" is the resolved source address of the module, after 422 // any normalization and expansion. This could be either a 423 // go-getter-style source address or a local path starting with "./" or 424 // "../". If the user gave a registry source address then this is the 425 // final location of the module as returned by the registry, after 426 // following any redirect indirection. 427 "resolved_source": "./child" 428 429 // "expressions" describes the expressions for the arguments within the 430 // block that correspond to input variables in the child module. 431 "expressions": <block-expressions-representation>, 432 433 // "count_expression" and "for_each_expression" describe the expressions 434 // given for the corresponding meta-arguments in the module 435 // configuration block. These are omitted if the corresponding argument 436 // isn't set. 437 "count_expression": <expression-representation>, 438 "for_each_expression": <expression-representation>, 439 440 // "module" is a representation of the configuration of the child module 441 // itself, using the same structure as the "root_module" object, 442 // recursively describing the full module tree. 443 "module": <module-configuration-representation>, 444 } 445 } 446 } 447 } 448 ``` 449 450 ### Expression Representation 451 452 Each unevaluated expression in the configuration is represented with an `<expression-representation>` object with the following structure: 453 454 ```javascript 455 { 456 // "constant_value" is set only if the expression contains no references to 457 // other objects, in which case it gives the resulting constant value. This is 458 // mapped as for the individual values in a value representation. 459 "constant_value": "hello", 460 461 // Alternatively, "references" will be set to a list of references in the 462 // expression. Multi-step references will be unwrapped and duplicated for each 463 // significant traversal step, allowing callers to more easily recognize the 464 // objects they care about without attempting to parse the expressions. 465 // Callers should only use string equality checks here, since the syntax may 466 // be extended in future releases. 467 "references": [ 468 "data.template_file.foo[1].vars[\"baz\"]", 469 "data.template_file.foo[1].vars", // implied by previous 470 "data.template_file.foo[1]", // implied by previous 471 "data.template_file.foo", // implied by previous 472 "module.foo.bar", 473 "module.foo", // implied by the previous 474 "var.example[0]", 475 "var.example", // implied by the previous 476 477 // Partial references like "data" and "module" are not included, because 478 // Terraform considers "module.foo" to be an atomic reference, not an 479 // attribute access. 480 ] 481 } 482 ``` 483 484 -> **Note:** Expressions in `dynamic` blocks are not included in the configuration representation. 485 486 ### Block Expressions Representation 487 488 In some cases, it is the entire content of a block (possibly after certain special arguments have already been handled and removed) that must be represented. For that, we have an `<block-expressions-representation>` structure: 489 490 ```javascript 491 { 492 // Attribute arguments are mapped directly with the attribute name as key and 493 // an <expression-representation> as value. 494 "ami": <expression-representation>, 495 "instance_type": <expression-representation>, 496 497 // Nested block arguments are mapped as either a single nested 498 // <block-expressions-representation> or an array object of these, depending on the 499 // block nesting mode chosen in the schema. 500 // - "single" nesting is a direct <block-expressions-representation> 501 // - "list" and "set" produce arrays 502 // - "map" produces an object 503 "root_block_device": <expression-representation>, 504 "ebs_block_device": [ 505 <expression-representation> 506 ] 507 } 508 ``` 509 510 For now we expect callers to just hard-code assumptions about the schemas of particular resource types in order to process these expression representations. In a later release we will add new inspection commands to return machine-readable descriptions of the schemas themselves, allowing for more generic handling in programs such as visualization tools. 511 512 ## Change Representation 513 514 A `<change-representation>` describes the change that will be made to the indicated object. 515 516 ```javascript 517 { 518 // "actions" are the actions that will be taken on the object selected by the 519 // properties below. 520 // Valid actions values are: 521 // ["no-op"] 522 // ["create"] 523 // ["read"] 524 // ["update"] 525 // ["delete", "create"] 526 // ["create", "delete"] 527 // ["delete"] 528 // The two "replace" actions are represented in this way to allow callers to 529 // e.g. just scan the list for "delete" to recognize all three situations 530 // where the object will be deleted, allowing for any new deletion 531 // combinations that might be added in future. 532 "actions": ["update"], 533 534 // "before" and "after" are representations of the object value both before 535 // and after the action. For ["create"] and ["delete"] actions, either 536 // "before" or "after" is unset (respectively). For ["no-op"], the before and 537 // after values are identical. The "after" value will be incomplete if there 538 // are values within it that won't be known until after apply. 539 "before": <value-representation>, 540 "after": <value-representation>, 541 542 // "after_unknown" is an object value with similar structure to "after", but 543 // with all unknown leaf values replaced with "true", and all known leaf 544 // values omitted. This can be combined with "after" to reconstruct a full 545 // value after the action, including values which will only be known after 546 // apply. 547 "after_unknown": { 548 "id": true 549 }, 550 551 // "before_sensitive" and "after_sensitive" are object values with similar 552 // structure to "before" and "after", but with all sensitive leaf values 553 // replaced with true, and all non-sensitive leaf values omitted. These 554 // objects should be combined with "before" and "after" to prevent accidental 555 // display of sensitive values in user interfaces. 556 "before_sensitive": {}, 557 "after_sensitive": { 558 "triggers": { 559 "boop": true 560 } 561 }, 562 563 // "replace_paths" is an array of arrays representing a set of paths into the 564 // object value which resulted in the action being "replace". This will be 565 // omitted if the action is not replace, or if no paths caused the 566 // replacement (for example, if the resource was tainted). Each path 567 // consists of one or more steps, each of which will be a number or a 568 // string. 569 "replace_paths": [["triggers"]] 570 } 571 ```