310 lines
11 KiB
Plaintext
310 lines
11 KiB
Plaintext
---
|
|
page_title: JSON Configuration Syntax - Configuration Language
|
|
sidebar_title: JSON Syntax
|
|
description: |-
|
|
In addition to the native syntax that is most commonly used with Packer,
|
|
the HCL language can also be expressed in a JSON-compatible syntax.
|
|
---
|
|
|
|
# JSON Configuration Syntax
|
|
|
|
`@include 'from-1.5/beta-hcl2-note.mdx'`
|
|
|
|
Most Packer configurations are written in [the native HCL
|
|
syntax](/docs/templates/hcl_templates/syntax), which is designed to be easy for humans to read and
|
|
update.
|
|
|
|
Packer also supports an alternative syntax that is JSON-compatible. This
|
|
syntax is useful when generating portions of a configuration programmatically,
|
|
since existing JSON libraries can be used to prepare the generated
|
|
configuration files.
|
|
|
|
This syntax is not to be confused with the pre-version-1.5 "legacy" Packer
|
|
templates, which were exclusively JSON and follow a different format.
|
|
|
|
The JSON syntax is defined in terms of the native syntax. Everything that can
|
|
be expressed in native syntax can also be expressed in JSON syntax, but some
|
|
constructs are more complex to represent in JSON due to limitations of the
|
|
JSON grammar.
|
|
|
|
Packer expects native syntax for files named with a `.pkr.hcl` suffix, and JSON
|
|
syntax for files named with a `.pkr.json` suffix. If you leave out the `.pkr`
|
|
portion of suffix, Packer will try to read your json file as a legacy Packer
|
|
template.
|
|
|
|
The low-level JSON syntax, just as with the native syntax, is defined in terms
|
|
of a specification called _HCL_. It is not necessary to know all of the details
|
|
of HCL syntax or its JSON mapping in order to use Packer, and so this page
|
|
summarizes the most important differences between native and JSON syntax. If
|
|
you are interested, you can find a full definition of HCL's JSON syntax in [its
|
|
specification](https://github.com/hashicorp/hcl/blob/hcl2/hclsyntax/spec.md).
|
|
|
|
## JSON File Structure
|
|
|
|
At the root of any JSON-based Packer configuration is a JSON object. The
|
|
properties of this object correspond to the top-level block types of the
|
|
Packer language. For example:
|
|
|
|
```json
|
|
{
|
|
"variables": {
|
|
"example": "value"
|
|
}
|
|
}
|
|
```
|
|
|
|
Each top-level object property must match the name of one of the expected
|
|
top-level block types. Block types that expect labels, such as `variable` shown
|
|
above, are represented by one nested object value for each level of label.
|
|
`source` blocks expect two labels, so two levels of nesting are required:
|
|
|
|
```json
|
|
{
|
|
"source": {
|
|
"amazon-ebs": {
|
|
"example": {
|
|
"instance_type": "t2.micro",
|
|
"ami_name": "ami-abc123"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
After any nested objects representing the labels, finally one more nested
|
|
object represents the body of the block itself. In the above example the
|
|
`instance_type` and `ami_name` arguments for `source "amazon-ebs" "example"`
|
|
are specified.
|
|
|
|
Taken together, the above two configuration files are equivalent to the
|
|
following blocks in the native syntax:
|
|
|
|
```hcl
|
|
variables {
|
|
example = "value"
|
|
}
|
|
|
|
source "amazon-ebs" "example" {
|
|
instance_type = "t2.micro"
|
|
ami_name = "ami-abc123"
|
|
}
|
|
```
|
|
|
|
Within each top-level block type the rules for mapping to JSON are slightly
|
|
different (see [block-type-specific exceptions](#block-type-specific-exceptions) below), but the following general rules apply in most cases:
|
|
|
|
- The JSON object representing the block body contains properties that
|
|
correspond either to argument names or to nested block type names.
|
|
|
|
- Where a property corresponds to an argument that accepts
|
|
[arbitrary expressions](/docs/templates/hcl_templates/expressions) in the native syntax, the
|
|
property value is mapped to an expression as described under
|
|
[_Expression Mapping_](#expression-mapping) below. For arguments that
|
|
do _not_ accept arbitrary expressions, the interpretation of the property
|
|
value depends on the argument, as described in the
|
|
[block-type-specific exceptions](#block-type-specific-exceptions)
|
|
given later in this page.
|
|
|
|
- Where a property name corresponds to an expected nested block type name,
|
|
the value is interpreted as described under
|
|
[_Nested Block Mapping_](#nested-block-mapping) below, unless otherwise
|
|
stated in [the block-type-specific exceptions](#block-type-specific-exceptions)
|
|
given later in this page.
|
|
|
|
## Expression Mapping
|
|
|
|
Since JSON grammar is not able to represent all of the Packer language
|
|
[expression syntax](/docs/templates/hcl_templates/expressions), JSON values interpreted as expressions
|
|
are mapped as follows:
|
|
|
|
| JSON | Packer Language Interpretation |
|
|
| ------- | ----------------------------------------------------------------------------------------------------------------- |
|
|
| Boolean | A literal `bool` value. |
|
|
| Number | A literal `number` value. |
|
|
| String | Parsed as a [string template](/docs/templates/hcl_templates/expressions#string-templates) and then evaluated as described below. |
|
|
| Object | Each property value is mapped per this table, producing an `object(...)` value with suitable attribute types. |
|
|
| Array | Each element is mapped per this table, producing a `tuple(...)` value with suitable element types. |
|
|
| Null | A literal `null`. |
|
|
|
|
When a JSON string is encountered in a location where arbitrary expressions are
|
|
expected, its value is first parsed as a [string template](/docs/templates/hcl_templates/expressions#string-templates)
|
|
and then it is evaluated to produce the final result.
|
|
|
|
If the given template consists _only_ of a single interpolation sequence,
|
|
the result of its expression is taken directly, without first converting it
|
|
to a string. This allows non-string expressions to be used within the
|
|
JSON syntax.
|
|
|
|
## Nested Block Mapping
|
|
|
|
When a JSON object property is named after a nested block type, the value
|
|
of this property represents one or more blocks of that type. The value of
|
|
the property must be either a JSON object or a JSON array.
|
|
|
|
The simplest situation is representing only a single block of the given type
|
|
when that type expects no labels, as with the `tags` nested block used
|
|
within `source` blocks:
|
|
|
|
```json
|
|
{
|
|
"source": {
|
|
"amazon-ebs": {
|
|
"example": {
|
|
"tags": {
|
|
"key": "value"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
The above is equivalent to the following native syntax configuration:
|
|
|
|
```hcl
|
|
source "amazon-ebs" "example" {
|
|
tags = {
|
|
key = "value"
|
|
}
|
|
}
|
|
```
|
|
|
|
When the nested block type requires one or more labels, or when multiple
|
|
blocks of the same type can be given, the mapping gets a little more
|
|
complicated. For example, the `provisioner` nested block type used
|
|
within `build` blocks expects a label giving the provisioner to use,
|
|
and the ordering of provisioner blocks is significant to decide the order
|
|
of operations.
|
|
|
|
The following native syntax example shows a `build` block with a number
|
|
of provisioners of different types:
|
|
|
|
```hcl
|
|
build {
|
|
# (source configuration omitted for brevity)
|
|
|
|
provisioner "shell-local" {
|
|
inline = ["echo 'Hello World' >example.txt"]
|
|
}
|
|
provisioner "file" {
|
|
source = "example.txt"
|
|
destination = "/tmp/example.txt"
|
|
}
|
|
provisioner "shell" {
|
|
inline = [
|
|
"sudo install-something -f /tmp/example.txt",
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
In order to preserve the order of these blocks, you must use a JSON array
|
|
as the direct value of the property representing this block type, as in
|
|
this JSON equivalent of the above:
|
|
|
|
```json
|
|
{
|
|
"build": {
|
|
"//": "(source configuration omitted for brevity)",
|
|
|
|
"provisioner": [
|
|
{
|
|
"shell-local": {
|
|
"inline": ["echo 'Hello World' >example.txt"]
|
|
}
|
|
},
|
|
{
|
|
"file": {
|
|
"source": "example.txt",
|
|
"destination": "/tmp/example.txt"
|
|
}
|
|
},
|
|
{
|
|
"shell": {
|
|
"inline": ["sudo install-something -f /tmp/example.txt"]
|
|
}
|
|
}
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
Each element of the `provisioner` array is an object with a single property
|
|
whose name represents the label for each `provisioner` block. For block types
|
|
that expect multiple labels, this pattern of alternating array and object
|
|
nesting can be used for each additional level.
|
|
|
|
If a nested block type requires labels but the order does _not_ matter, you
|
|
may omit the array and provide just a single object whose property names
|
|
correspond to unique block labels. This is allowed as a shorthand for the above
|
|
for simple cases, but the alternating array and object approach is the most
|
|
general. We recommend using the most general form if systematically converting
|
|
from native syntax to JSON, to ensure that the meaning of the configuration is
|
|
preserved exactly.
|
|
|
|
### Comment Properties
|
|
|
|
Although we do not recommend hand-editing of JSON syntax configuration files
|
|
-- this format is primarily intended for programmatic generation and consumption --
|
|
a limited form of _comments_ are allowed inside JSON objects that represent
|
|
block bodies using a special property name:
|
|
|
|
```json
|
|
{
|
|
"source": {
|
|
"amazon-ebs": {
|
|
"example": {
|
|
"//": "This instance runs the scheduled tasks for backup",
|
|
|
|
"instance_type": "t2.micro",
|
|
"ami_name": "ami-abc123"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
In any object that represents a block body, properties named `"//"` are
|
|
ignored by Packer entirely. This exception does _not_ apply to objects
|
|
that are being [interpreted as expressions](#expression-mapping), where this
|
|
would be interpreted as an object type attribute named `"//"`.
|
|
|
|
This special property name can also be used at the root of a JSON-based
|
|
configuration file. This can be useful to note which program created the file.
|
|
|
|
```json
|
|
{
|
|
"//": "This file is generated by generate-outputs.py. DO NOT HAND-EDIT!"
|
|
}
|
|
```
|
|
|
|
## Block-type-specific Exceptions
|
|
|
|
[inpage-block]: #block-type-specific-exceptions
|
|
|
|
Certain arguments within specific block types are processed in a special way,
|
|
and so their mapping to the JSON syntax does not follow the general rules
|
|
described above. The following sub-sections describe the special mapping rules
|
|
that apply to each top-level block type.
|
|
|
|
### `variable` blocks
|
|
|
|
All arguments inside `variable` blocks have non-standard mappings to JSON:
|
|
|
|
- `type`: a string containing a type expression, like `"string"` or `"list(string)"`.
|
|
- `default`: a literal JSON value that can be converted to the given type.
|
|
Strings within this value are taken literally and _not_ interpreted as
|
|
string templates.
|
|
- `description`: a literal JSON string, _not_ interpreted as a template.
|
|
|
|
```json
|
|
{
|
|
"variable": {
|
|
"example": {
|
|
"type": "string",
|
|
"default": "hello"
|
|
}
|
|
}
|
|
}
|
|
```
|