mirror of https://github.com/hashicorp/packer
commit
bbc5bc0658
@ -0,0 +1,74 @@
|
||||
---
|
||||
layout: "docs"
|
||||
page_title: "Configuration Language"
|
||||
sidebar_current: "configuration"
|
||||
description: |-
|
||||
Packer uses text files to describe infrastructure and to set variables.
|
||||
These text files are called Packer _configurations_ and are
|
||||
written in the HCL language.
|
||||
---
|
||||
|
||||
# HCL Configuration Language
|
||||
|
||||
Packer uses the Hashicorp Configuration Language - HCL - designed to allow
|
||||
concise descriptions of the required steps to get to a build file.
|
||||
|
||||
## Builds
|
||||
|
||||
The main purpose of the HCL language is defining builds and sources. All other
|
||||
language features exist only to make the definition of builds more flexible and
|
||||
convenient.
|
||||
|
||||
|
||||
`packer build` takes one argument. When a directory is passed, all files in the
|
||||
folder with a name ending with ".pkr.hcl" or ".pkr.json" will be parsed using
|
||||
the HCL2 format. When a file ending with ".pkr.hcl" or ".pkr.json" is passed it
|
||||
will be parsed using the HCL2 schema. For every other case; the *JSON only* old
|
||||
packer schema will be used.
|
||||
|
||||
## Arguments, Blocks, and Expressions
|
||||
|
||||
The syntax of the HCL language consists of only a few basic elements:
|
||||
|
||||
```hcl
|
||||
source "amazon-ebs" "main" {
|
||||
ami_name = "main-ami"
|
||||
}
|
||||
|
||||
<BLOCK TYPE> "<BLOCK LABEL>" "<BLOCK LABEL>" {
|
||||
# Block body
|
||||
<IDENTIFIER> = <EXPRESSION> # Argument
|
||||
}
|
||||
```
|
||||
|
||||
- _Blocks_ are containers for other content and usually represent the
|
||||
configuration of some kind of object, like a source. Blocks have a
|
||||
_block type,_ can have zero or more _labels,_ and have a _body_ that contains
|
||||
any number of arguments and nested blocks. Most of Packer's features are
|
||||
controlled by top-level blocks in a configuration file.
|
||||
- _Arguments_ assign a value to a name. They appear within blocks.
|
||||
- _Expressions_ represent a value, either literally or by referencing and
|
||||
combining other values. They appear as values for arguments, or within other
|
||||
expressions.
|
||||
|
||||
For full details about Packer's syntax, see:
|
||||
|
||||
- [Configuration Syntax](./syntax.html)
|
||||
- [Expressions](./expressions.html)
|
||||
|
||||
## Code Organization
|
||||
|
||||
The HCL language uses configuration files that are named with the `.pkr.hcl`
|
||||
file extension. There is also [a JSON-based variant of the
|
||||
language](./syntax-json.html) that is named with the `.pkr.json` file
|
||||
extension.
|
||||
|
||||
Configuration files must always use UTF-8 encoding, and by convention are
|
||||
usually maintained with Unix-style line endings (LF) rather than Windows-style
|
||||
line endings (CRLF), though both are accepted.
|
||||
|
||||
## Configuration Ordering
|
||||
|
||||
The ordering of root blocks is not significant. The order of `provisioner` or
|
||||
`post-processor` blocks within a `build` is the only major feature where block
|
||||
order matters.
|
||||
@ -0,0 +1,276 @@
|
||||
---
|
||||
layout: "docs"
|
||||
page_title: "JSON Configuration Syntax - Configuration Language"
|
||||
sidebar_current: configuration-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
|
||||
|
||||
|
||||
Most Packer configurations are written in [the native HCL
|
||||
syntax](./syntax.html), 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.
|
||||
|
||||
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.
|
||||
|
||||
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][inpage-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](./expressions.html) 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](./expressions.html), 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](./expressions.html#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](./expressions.html#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 `source` 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 `source` block with a number
|
||||
of provisioners of different types:
|
||||
|
||||
```hcl
|
||||
source "amazon-ebs" "example" {
|
||||
# (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
|
||||
{
|
||||
"source": {
|
||||
"amazon-ebs": {
|
||||
"example": {
|
||||
"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!",
|
||||
}
|
||||
```
|
||||
@ -0,0 +1,119 @@
|
||||
---
|
||||
layout: "docs"
|
||||
page_title: "Syntax - Configuration Language"
|
||||
sidebar_current: configuration-syntax
|
||||
description: |-
|
||||
HCL has its own syntax, intended to combine declarative
|
||||
structure with expressions in a way that is easy for humans to read and
|
||||
understand.
|
||||
---
|
||||
|
||||
# HCL Configuration Syntax
|
||||
|
||||
Other pages in this section have described various configuration constructs
|
||||
that can appear in HCL. This page describes the lower-level syntax of the
|
||||
language in more detail, revealing the building blocks that those constructs
|
||||
are built from.
|
||||
|
||||
This page describes the _native syntax_ of HCL, which is a rich language
|
||||
designed to be easy for humans to read and write. The constructs in HCL can
|
||||
also be expressed in [JSON syntax](./syntax-json.html), which is harder for
|
||||
humans to read and edit but easier to generate and parse programmatically.
|
||||
|
||||
This low-level syntax of HCL is defined in terms of a syntax called _HCL_,
|
||||
which is also used by configuration languages in other applications, and in
|
||||
particular other HashiCorp products. It is not necessary to know all of the
|
||||
details of HCL in order to use Packer, and so this page summarizes the most
|
||||
important details. If you are interested, you can find a full definition of HCL
|
||||
syntax in [the HCL native syntax
|
||||
specification](https://github.com/hashicorp/hcl/blob/hcl2/hclsyntax/spec.md).
|
||||
|
||||
## Arguments and Blocks
|
||||
|
||||
HCL syntax is built around two key syntax constructs:
|
||||
arguments and blocks.
|
||||
|
||||
### Arguments
|
||||
|
||||
An _argument_ assigns a value to a particular name:
|
||||
|
||||
```hcl
|
||||
image_id = "abc123"
|
||||
```
|
||||
|
||||
The identifier before the equals sign is the _argument name_, and the expression
|
||||
after the equals sign is the argument's value.
|
||||
|
||||
The context where the argument appears determines what value types are valid
|
||||
(for example, each source type has a schema that defines the types of its
|
||||
arguments), but many arguments accept arbitrary
|
||||
[expressions](./expressions.html), which allow the value to
|
||||
either be specified literally or generated from other values programmatically.
|
||||
|
||||
### Blocks
|
||||
|
||||
A _block_ is a container for other content:
|
||||
|
||||
```hcl
|
||||
source "amazon-ebs" "example" {
|
||||
ami_name = "abc123"
|
||||
|
||||
tags {
|
||||
# ...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
A block has a _type_ (`source` in this example). Each block type defines
|
||||
how many _labels_ must follow the type keyword. The `source` block type
|
||||
expects two labels, which are `amazon-ebs` and `example` in the example above.
|
||||
A particular block type may have any number of required labels, or it may
|
||||
require none as with the nested `tags` block type.
|
||||
|
||||
After the block type keyword and any labels, the block _body_ is delimited
|
||||
by the `{` and `}` characters. Within the block body, further arguments
|
||||
and blocks may be nested, creating a hierarchy of blocks and their associated
|
||||
arguments.
|
||||
|
||||
HCL uses a limited number of _top-level block types,_ which
|
||||
are blocks that can appear outside of any other block in a configuration file.
|
||||
Most of Packer's features (including resources, input variables, output
|
||||
values, data sources, etc.) are implemented as top-level blocks.
|
||||
|
||||
## Identifiers
|
||||
|
||||
Argument names, block type names, and the names of most Packer-specific
|
||||
constructs like resources, input variables, etc. are all _identifiers_.
|
||||
|
||||
Identifiers can contain letters, digits, underscores (`_`), and hyphens (`-`).
|
||||
The first character of an identifier must not be a digit, to avoid ambiguity
|
||||
with literal numbers.
|
||||
|
||||
For complete identifier rules, Packer implements
|
||||
[the Unicode identifier syntax](http://unicode.org/reports/tr31/), extended to
|
||||
include the ASCII hyphen character `-`.
|
||||
|
||||
## Comments
|
||||
|
||||
HCL supports three different syntaxes for comments:
|
||||
|
||||
* `#` begins a single-line comment, ending at the end of the line.
|
||||
* `//` also begins a single-line comment, as an alternative to `#`.
|
||||
* `/*` and `*/` are start and end delimiters for a comment that might span
|
||||
over multiple lines.
|
||||
|
||||
The `#` single-line comment style is the default comment style and should be
|
||||
used in most cases. Automatic configuration formatting tools may automatically
|
||||
transform `//` comments into `#` comments, since the double-slash style is
|
||||
not idiomatic.
|
||||
|
||||
## Character Encoding and Line Endings
|
||||
|
||||
Packer configuration files must always be UTF-8 encoded. While the
|
||||
delimiters of the language are all ASCII characters, Packer accepts
|
||||
non-ASCII characters in identifiers, comments, and string values.
|
||||
|
||||
Packer accepts configuration files with either Unix-style line endings
|
||||
(LF only) or Windows-style line endings (CR then LF), but the idiomatic style
|
||||
is to use the Unix convention, and so automatic configuration formatting tools
|
||||
may automatically transform CRLF endings to LF.
|
||||
@ -0,0 +1,44 @@
|
||||
---
|
||||
layout: guides
|
||||
page_title: Generating code for config spec.
|
||||
sidebar_current: hcl-component-object-spec
|
||||
description: |-
|
||||
Learn how to generate the HCL2 configuration of your component easily.
|
||||
---
|
||||
|
||||
# Auto Generate the HCL2 code of a plugin
|
||||
|
||||
From v1.5, Packer can be configured using HCL2. Because Packer has so many
|
||||
builders, provisioner & post-processors, we relied on code generation to
|
||||
iterate more easily. The good new is that you can benefit from this code
|
||||
generator to get the HCL2 spec code of your component simply. It's a Go binary
|
||||
package and is located in [`cmd/mapstructure-to-hcl2`](https://github.com/hashicorp/packer/tree/master/cmd/mapstructure-to-hcl2).
|
||||
|
||||
Say you want to configure the `Config` struct of a `Builder` in a package
|
||||
located in `my/example-plugin/config.go`. Here are some simple steps you can
|
||||
follow to make it HCL2 enabled:
|
||||
|
||||
* run `go install github.com/hashicorp/packer/cmd/mapstructure-to-hcl2`
|
||||
|
||||
* Add `//go:generate mapstructure-to-hcl2 -type Config` at the top of
|
||||
`config.go`
|
||||
|
||||
* run `go generate ./my/example-plugin/...`
|
||||
|
||||
This will generate a `my/example-plugin/config.hcl2spec.go` file containing
|
||||
the configuration fields of `Config`.
|
||||
|
||||
* Make sure that all the nested structs of `Config` are also auto generated the
|
||||
same way.
|
||||
|
||||
* Now we only need to make Builder implement the interface by adding the
|
||||
following snippet:
|
||||
|
||||
```go
|
||||
func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() }
|
||||
```
|
||||
|
||||
From now on every time you add or change a field of Config you will need to
|
||||
run the `go generate` command again.
|
||||
|
||||
A good example of this is the [Config struct of the amazon-ebs builder](https://github.com/hashicorp/packer/blob/master/builder/amazon/ebs/builder.go)
|
||||
Loading…
Reference in new issue