|
1 | 1 | # HCL
|
2 | 2 |
|
3 |
| -[](https://godoc.org/github.com/hashicorp/hcl) [](https://travis-ci.org/hashicorp/hcl) |
| 3 | +HCL is a toolkit for creating structured configuration languages that are |
| 4 | +both human- and machine-friendly, for use with command-line tools. |
| 5 | +Although intended to be generally useful, it is primarily targeted |
| 6 | +towards devops tools, servers, etc. |
4 | 7 |
|
5 |
| -HCL (HashiCorp Configuration Language) is a configuration language built |
6 |
| -by HashiCorp. The goal of HCL is to build a structured configuration language |
7 |
| -that is both human and machine friendly for use with command-line tools, but |
8 |
| -specifically targeted towards DevOps tools, servers, etc. |
| 8 | +HCL has both a _native syntax_, intended to be pleasant to read and write for |
| 9 | +humans, and a JSON-based variant that is easier for machines to generate |
| 10 | +and parse. |
9 | 11 |
|
10 |
| -HCL is also fully JSON compatible. That is, JSON can be used as completely |
11 |
| -valid input to a system expecting HCL. This helps makes systems |
12 |
| -interoperable with other systems. |
| 12 | +The HCL native syntax is inspired by [libucl](https://github.com/vstakhov/libucl), |
| 13 | +[nginx configuration](http://nginx.org/en/docs/beginners_guide.html#conf_structure), |
| 14 | +and others. |
13 | 15 |
|
14 |
| -HCL is heavily inspired by |
15 |
| -[libucl](https://github.com/vstakhov/libucl), |
16 |
| -nginx configuration, and others similar. |
| 16 | +It includes an expression syntax that allows basic inline computation and, |
| 17 | +with support from the calling application, use of variables and functions |
| 18 | +for more dynamic configuration languages. |
17 | 19 |
|
18 |
| -## Why? |
19 |
| - |
20 |
| -A common question when viewing HCL is to ask the question: why not |
21 |
| -JSON, YAML, etc.? |
22 |
| - |
23 |
| -Prior to HCL, the tools we built at [HashiCorp](http://www.hashicorp.com) |
24 |
| -used a variety of configuration languages from full programming languages |
25 |
| -such as Ruby to complete data structure languages such as JSON. What we |
26 |
| -learned is that some people wanted human-friendly configuration languages |
27 |
| -and some people wanted machine-friendly languages. |
28 |
| - |
29 |
| -JSON fits a nice balance in this, but is fairly verbose and most |
30 |
| -importantly doesn't support comments. With YAML, we found that beginners |
31 |
| -had a really hard time determining what the actual structure was, and |
32 |
| -ended up guessing more often than not whether to use a hyphen, colon, etc. |
33 |
| -in order to represent some configuration key. |
| 20 | +HCL provides a set of constructs that can be used by a calling application to |
| 21 | +construct a configuration language. The application defines which attribute |
| 22 | +names and nested block types are expected, and HCL parses the configuration |
| 23 | +file, verifies that it conforms to the expected structure, and returns |
| 24 | +high-level objects that the application can use for further processing. |
34 | 25 |
|
35 |
| -Full programming languages such as Ruby enable complex behavior |
36 |
| -a configuration language shouldn't usually allow, and also forces |
37 |
| -people to learn some set of Ruby. |
| 26 | +## Experimental HCL2 |
38 | 27 |
|
39 |
| -Because of this, we decided to create our own configuration language |
40 |
| -that is JSON-compatible. Our configuration language (HCL) is designed |
41 |
| -to be written and modified by humans. The API for HCL allows JSON |
42 |
| -as an input so that it is also machine-friendly (machines can generate |
43 |
| -JSON instead of trying to generate HCL). |
| 28 | +This repository contains the experimental version 2 of HCL. This new version |
| 29 | +combines the initial iteration of HCL with the interpolation language HIL |
| 30 | +to produce a single configuration language that supports arbitrary expressions. |
44 | 31 |
|
45 |
| -Our goal with HCL is not to alienate other configuration languages. |
46 |
| -It is instead to provide HCL as a specialized language for our tools, |
47 |
| -and JSON as the interoperability layer. |
| 32 | +At this time the HCL2 syntax and the Go API are still evolving. |
| 33 | +Backward-compatibility is not guaranteed and so any application using this |
| 34 | +library should use vendoring. |
48 | 35 |
|
49 |
| -## Syntax |
| 36 | +The new implementation has a completely new parser and Go API, with no direct |
| 37 | +migration path. Although the syntax is similar, the implementation takes some |
| 38 | +very different approaches to improve on some "rough edges" that existed with |
| 39 | +the original implementation and to allow for more robust error handling. |
50 | 40 |
|
51 |
| -For a complete grammar, please see the parser itself. A high-level overview |
52 |
| -of the syntax and grammar is listed here. |
| 41 | +Once this new implementation reaches stability, its package paths will be |
| 42 | +changed to reflect that it is the _current_ HCL implementation. At that time, |
| 43 | +the original implementation will be archived. |
53 | 44 |
|
54 |
| - * Single line comments start with `#` or `//` |
55 |
| - |
56 |
| - * Multi-line comments are wrapped in `/*` and `*/`. Nested block comments |
57 |
| - are not allowed. A multi-line comment (also known as a block comment) |
58 |
| - terminates at the first `*/` found. |
| 45 | +## Why? |
59 | 46 |
|
60 |
| - * Values are assigned with the syntax `key = value` (whitespace doesn't |
61 |
| - matter). The value can be any primitive: a string, number, boolean, |
62 |
| - object, or list. |
| 47 | +Newcomers to HCL often ask: why not JSON, YAML, etc? |
| 48 | + |
| 49 | +Whereas JSON and YAML are formats for serializing data structures, HCL is |
| 50 | +a syntax and API specifically designed for building structured configuration |
| 51 | +formats. |
| 52 | + |
| 53 | +HCL attempts to strike a compromise between generic serialization formats |
| 54 | +such as JSON and configuration formats built around full programming languages |
| 55 | +such as Ruby. HCL syntax is designed to be easily read and written by humans, |
| 56 | +and allows _declarative_ logic to permit its use in more complex applications. |
| 57 | + |
| 58 | +HCL is intended as a base syntax for configuration formats built |
| 59 | +around key-value pairs and hierarchical blocks whose structure is well-defined |
| 60 | +by the calling application, and this definition of the configuration structure |
| 61 | +allows for better error messages and more convenient definition within the |
| 62 | +calling application. |
| 63 | + |
| 64 | +It can't be denied that JSON is very convenient as a _lingua franca_ |
| 65 | +for interoperability between different pieces of software. Because of this, |
| 66 | +HCL defines a common configuration model that can be parsed from either its |
| 67 | +native syntax or from a well-defined equivalent JSON structure. This allows |
| 68 | +configuration to be provided as a mixture of human-authored configuration |
| 69 | +files in the native syntax and machine-generated files in JSON. |
| 70 | + |
| 71 | +## Information Model and Syntax |
| 72 | + |
| 73 | +HCL is built around two primary concepts: _attributes_ and _blocks_. In |
| 74 | +native syntax, a configuration file for a hypothetical application might look |
| 75 | +something like this: |
| 76 | + |
| 77 | +```hcl |
| 78 | +io_mode = "async" |
| 79 | +
|
| 80 | +service "http" "web_proxy" { |
| 81 | + listen_addr = "127.0.0.1:8080" |
| 82 | + |
| 83 | + process "main" { |
| 84 | + command = ["/usr/local/bin/awesome-app", "server"] |
| 85 | + } |
| 86 | +
|
| 87 | + process "mgmt" { |
| 88 | + command = ["/usr/local/bin/awesome-app", "mgmt"] |
| 89 | + } |
| 90 | +} |
| 91 | +``` |
63 | 92 |
|
64 |
| - * Strings are double-quoted and can contain any UTF-8 characters. |
65 |
| - Example: `"Hello, World"` |
| 93 | +The JSON equivalent of this configuration is the following: |
66 | 94 |
|
67 |
| - * Multi-line strings start with `<<EOF` at the end of a line, and end |
68 |
| - with `EOF` on its own line ([here documents](https://en.wikipedia.org/wiki/Here_document)). |
69 |
| - Any text may be used in place of `EOF`. Example: |
70 |
| -``` |
71 |
| -<<FOO |
72 |
| -hello |
73 |
| -world |
74 |
| -FOO |
| 95 | +```json |
| 96 | +{ |
| 97 | + "io_mode": "async", |
| 98 | + "service": { |
| 99 | + "http": { |
| 100 | + "web_proxy": { |
| 101 | + "listen_addr": "127.0.0.1:8080", |
| 102 | + "process": { |
| 103 | + "main": { |
| 104 | + "command": ["/usr/local/bin/awesome-app", "server"] |
| 105 | + }, |
| 106 | + "mgmt": { |
| 107 | + "command": ["/usr/local/bin/awesome-app", "mgmt"] |
| 108 | + }, |
| 109 | + } |
| 110 | + } |
| 111 | + } |
| 112 | + } |
| 113 | +} |
75 | 114 | ```
|
76 | 115 |
|
77 |
| - * Numbers are assumed to be base 10. If you prefix a number with 0x, |
78 |
| - it is treated as a hexadecimal. If it is prefixed with 0, it is |
79 |
| - treated as an octal. Numbers can be in scientific notation: "1e10". |
| 116 | +Regardless of which syntax is used, the API within the calling application |
| 117 | +is the same. It can either work directly with the low-level attributes and |
| 118 | +blocks, for more advanced use-cases, or it can use one of the _decoder_ |
| 119 | +packages to declaratively extract into either Go structs or dynamic value |
| 120 | +structures. |
80 | 121 |
|
81 |
| - * Boolean values: `true`, `false` |
| 122 | +Attribute values can be expressions as well as just literal values: |
82 | 123 |
|
83 |
| - * Arrays can be made by wrapping it in `[]`. Example: |
84 |
| - `["foo", "bar", 42]`. Arrays can contain primitives, |
85 |
| - other arrays, and objects. As an alternative, lists |
86 |
| - of objects can be created with repeated blocks, using |
87 |
| - this structure: |
| 124 | +```hcl |
| 125 | +# Arithmetic with literals and application-provided variables |
| 126 | +sum = 1 + addend |
88 | 127 |
|
89 |
| - ```hcl |
90 |
| - service { |
91 |
| - key = "value" |
92 |
| - } |
| 128 | +# String interpolation and templates |
| 129 | +message = "Hello, ${name}!" |
93 | 130 |
|
94 |
| - service { |
95 |
| - key = "value" |
96 |
| - } |
97 |
| - ``` |
| 131 | +# Application-provided functions |
| 132 | +shouty_message = upper(message) |
| 133 | +``` |
98 | 134 |
|
99 |
| -Objects and nested objects are created using the structure shown below: |
| 135 | +Although JSON syntax doesn't permit direct use of expressions, the interpolation |
| 136 | +syntax allows use of arbitrary expressions within JSON strings: |
100 | 137 |
|
101 |
| -``` |
102 |
| -variable "ami" { |
103 |
| - description = "the AMI to use" |
104 |
| -} |
105 |
| -``` |
106 |
| -This would be equivalent to the following json: |
107 |
| -``` json |
| 138 | +```json |
108 | 139 | {
|
109 |
| - "variable": { |
110 |
| - "ami": { |
111 |
| - "description": "the AMI to use" |
112 |
| - } |
113 |
| - } |
| 140 | + "sum": "${1 + addend}", |
| 141 | + "message": "Hello, ${name}!", |
| 142 | + "shouty_message": "${upper(message)}" |
114 | 143 | }
|
115 | 144 | ```
|
116 | 145 |
|
117 |
| -## Thanks |
| 146 | +For more information, see the detailed specifications: |
| 147 | + |
| 148 | +* [Syntax-agnostic Information Model](hcl/spec.md) |
| 149 | +* [HCL Native Syntax](hcl/hclsyntax/spec.md) |
| 150 | +* [JSON Representation](hcl/json/spec.md) |
| 151 | + |
| 152 | +## Acknowledgements |
| 153 | + |
| 154 | +HCL was heavily inspired by [libucl](https://github.com/vstakhov/libucl), |
| 155 | +by [Vsevolod Stakhov](https://github.com/vstakhov). |
| 156 | + |
| 157 | +HCL and HIL originate in [HashiCorp Terraform](https://terraform.io/), |
| 158 | +with the original parsers for each written by |
| 159 | +[Mitchell Hashimoto](https://github.com/mitchellh). |
118 | 160 |
|
119 |
| -Thanks to: |
| 161 | +The original HCL parser was ported to pure Go (from yacc) by |
| 162 | +[Fatih Arslan](https://github.com/fatih). The structure-related portions of |
| 163 | +the new native syntax parser build on that work. |
120 | 164 |
|
121 |
| - * [@vstakhov](https://github.com/vstakhov) - The original libucl parser |
122 |
| - and syntax that HCL was based off of. |
| 165 | +The original HIL parser was ported to pure Go (from yacc) by |
| 166 | +[Martin Atkins](https://github.com/apparentlymart). The expression-related |
| 167 | +portions of the new native syntax parser build on that work. |
123 | 168 |
|
124 |
| - * [@fatih](https://github.com/fatih) - The rewritten HCL parser |
125 |
| - in pure Go (no goyacc) and support for a printer. |
| 169 | +HCL2, which merged the original HCL and HIL languages into this single new |
| 170 | +language, builds on design and prototyping work by |
| 171 | +[Martin Atkins](https://github.com/apparentlymart) in |
| 172 | +[zcl](https://github.com/zclconf/go-zcl). |
0 commit comments