diff options
Diffstat (limited to 'vendor/github.com/hashicorp/hcl2/hcl/json/spec.md')
-rw-r--r-- | vendor/github.com/hashicorp/hcl2/hcl/json/spec.md | 405 |
1 files changed, 405 insertions, 0 deletions
diff --git a/vendor/github.com/hashicorp/hcl2/hcl/json/spec.md b/vendor/github.com/hashicorp/hcl2/hcl/json/spec.md new file mode 100644 index 0000000..9b33c7f --- /dev/null +++ b/vendor/github.com/hashicorp/hcl2/hcl/json/spec.md | |||
@@ -0,0 +1,405 @@ | |||
1 | # HCL JSON Syntax Specification | ||
2 | |||
3 | This is the specification for the JSON serialization for hcl. HCL is a system | ||
4 | for defining configuration languages for applications. The HCL information | ||
5 | model is designed to support multiple concrete syntaxes for configuration, | ||
6 | and this JSON-based format complements [the native syntax](../hclsyntax/spec.md) | ||
7 | by being easy to machine-generate, whereas the native syntax is oriented | ||
8 | towards human authoring and maintenence. | ||
9 | |||
10 | This syntax is defined in terms of JSON as defined in | ||
11 | [RFC7159](https://tools.ietf.org/html/rfc7159). As such it inherits the JSON | ||
12 | grammar as-is, and merely defines a specific methodology for interpreting | ||
13 | JSON constructs into HCL structural elements and expressions. | ||
14 | |||
15 | This mapping is defined such that valid JSON-serialized HCL input can be | ||
16 | _produced_ using standard JSON implementations in various programming languages. | ||
17 | _Parsing_ such JSON has some additional constraints not beyond what is normally | ||
18 | supported by JSON parsers, so a specialized parser may be required that | ||
19 | is able to: | ||
20 | |||
21 | * Preserve the relative ordering of properties defined in an object. | ||
22 | * Preserve multiple definitions of the same property name. | ||
23 | * Preserve numeric values to the precision required by the number type | ||
24 | in [the HCL syntax-agnostic information model](../spec.md). | ||
25 | * Retain source location information for parsed tokens/constructs in order | ||
26 | to produce good error messages. | ||
27 | |||
28 | ## Structural Elements | ||
29 | |||
30 | [The HCL syntax-agnostic information model](../spec.md) defines a _body_ as an | ||
31 | abstract container for attribute definitions and child blocks. A body is | ||
32 | represented in JSON as either a single JSON object or a JSON array of objects. | ||
33 | |||
34 | Body processing is in terms of JSON object properties, visited in the order | ||
35 | they appear in the input. Where a body is represented by a single JSON object, | ||
36 | the properties of that object are visited in order. Where a body is | ||
37 | represented by a JSON array, each of its elements are visited in order and | ||
38 | each element has its properties visited in order. If any element of the array | ||
39 | is not a JSON object then the input is erroneous. | ||
40 | |||
41 | When a body is being processed in the _dynamic attributes_ mode, the allowance | ||
42 | of a JSON array in the previous paragraph does not apply and instead a single | ||
43 | JSON object is always required. | ||
44 | |||
45 | As defined in the language-agnostic model, body processing is in terms | ||
46 | of a schema which provides context for interpreting the body's content. For | ||
47 | JSON bodies, the schema is crucial to allow differentiation of attribute | ||
48 | definitions and block definitions, both of which are represented via object | ||
49 | properties. | ||
50 | |||
51 | The special property name `"//"`, when used in an object representing a HCL | ||
52 | body, is parsed and ignored. A property with this name can be used to | ||
53 | include human-readable comments. (This special property name is _not_ | ||
54 | processed in this way for any _other_ HCL constructs that are represented as | ||
55 | JSON objects.) | ||
56 | |||
57 | ### Attributes | ||
58 | |||
59 | Where the given schema describes an attribute with a given name, the object | ||
60 | property with the matching name — if present — serves as the attribute's | ||
61 | definition. | ||
62 | |||
63 | When a body is being processed in the _dynamic attributes_ mode, each object | ||
64 | property serves as an attribute definition for the attribute whose name | ||
65 | matches the property name. | ||
66 | |||
67 | The value of an attribute definition property is interpreted as an _expression_, | ||
68 | as described in a later section. | ||
69 | |||
70 | Given a schema that calls for an attribute named "foo", a JSON object like | ||
71 | the following provides a definition for that attribute: | ||
72 | |||
73 | ```json | ||
74 | { | ||
75 | "foo": "bar baz" | ||
76 | } | ||
77 | ``` | ||
78 | |||
79 | ### Blocks | ||
80 | |||
81 | Where the given schema describes a block with a given type name, each object | ||
82 | property with the matching name serves as a definition of zero or more blocks | ||
83 | of that type. | ||
84 | |||
85 | Processing of child blocks is in terms of nested JSON objects and arrays. | ||
86 | If the schema defines one or more _labels_ for the block type, a nested JSON | ||
87 | object or JSON array of objects is required for each labelling level. These | ||
88 | are flattened to a single ordered sequence of object properties using the | ||
89 | same algorithm as for body content as defined above. Each object property | ||
90 | serves as a label value at the corresponding level. | ||
91 | |||
92 | After any labelling levels, the next nested value is either a JSON object | ||
93 | representing a single block body, or a JSON array of JSON objects that each | ||
94 | represent a single block body. Use of an array accommodates the definition | ||
95 | of multiple blocks that have identical type and labels. | ||
96 | |||
97 | Given a schema that calls for a block type named "foo" with no labels, the | ||
98 | following JSON objects are all valid definitions of zero or more blocks of this | ||
99 | type: | ||
100 | |||
101 | ```json | ||
102 | { | ||
103 | "foo": { | ||
104 | "child_attr": "baz" | ||
105 | } | ||
106 | } | ||
107 | ``` | ||
108 | |||
109 | ```json | ||
110 | { | ||
111 | "foo": [ | ||
112 | { | ||
113 | "child_attr": "baz" | ||
114 | }, | ||
115 | { | ||
116 | "child_attr": "boz" | ||
117 | } | ||
118 | ] | ||
119 | } | ||
120 | ``` | ||
121 | ```json | ||
122 | { | ||
123 | "foo": [] | ||
124 | } | ||
125 | ``` | ||
126 | |||
127 | The first of these defines a single child block of type "foo". The second | ||
128 | defines _two_ such blocks. The final example shows a degenerate definition | ||
129 | of zero blocks, though generators should prefer to omit the property entirely | ||
130 | in this scenario. | ||
131 | |||
132 | Given a schema that calls for a block type named "foo" with _two_ labels, the | ||
133 | extra label levels must be represented as objects or arrays of objects as in | ||
134 | the following examples: | ||
135 | |||
136 | ```json | ||
137 | { | ||
138 | "foo": { | ||
139 | "bar": { | ||
140 | "baz": { | ||
141 | "child_attr": "baz" | ||
142 | }, | ||
143 | "boz": { | ||
144 | "child_attr": "baz" | ||
145 | } | ||
146 | }, | ||
147 | "boz": { | ||
148 | "baz": { | ||
149 | "child_attr": "baz" | ||
150 | }, | ||
151 | } | ||
152 | } | ||
153 | } | ||
154 | ``` | ||
155 | |||
156 | ```json | ||
157 | { | ||
158 | "foo": { | ||
159 | "bar": { | ||
160 | "baz": { | ||
161 | "child_attr": "baz" | ||
162 | }, | ||
163 | "boz": { | ||
164 | "child_attr": "baz" | ||
165 | } | ||
166 | }, | ||
167 | "boz": { | ||
168 | "baz": [ | ||
169 | { | ||
170 | "child_attr": "baz" | ||
171 | }, | ||
172 | { | ||
173 | "child_attr": "boz" | ||
174 | } | ||
175 | ] | ||
176 | } | ||
177 | } | ||
178 | } | ||
179 | ``` | ||
180 | |||
181 | ```json | ||
182 | { | ||
183 | "foo": [ | ||
184 | { | ||
185 | "bar": { | ||
186 | "baz": { | ||
187 | "child_attr": "baz" | ||
188 | }, | ||
189 | "boz": { | ||
190 | "child_attr": "baz" | ||
191 | } | ||
192 | }, | ||
193 | }, | ||
194 | { | ||
195 | "bar": { | ||
196 | "baz": [ | ||
197 | { | ||
198 | "child_attr": "baz" | ||
199 | }, | ||
200 | { | ||
201 | "child_attr": "boz" | ||
202 | } | ||
203 | ] | ||
204 | } | ||
205 | } | ||
206 | ] | ||
207 | } | ||
208 | ``` | ||
209 | |||
210 | ```json | ||
211 | { | ||
212 | "foo": { | ||
213 | "bar": { | ||
214 | "baz": { | ||
215 | "child_attr": "baz" | ||
216 | }, | ||
217 | "boz": { | ||
218 | "child_attr": "baz" | ||
219 | } | ||
220 | }, | ||
221 | "bar": { | ||
222 | "baz": [ | ||
223 | { | ||
224 | "child_attr": "baz" | ||
225 | }, | ||
226 | { | ||
227 | "child_attr": "boz" | ||
228 | } | ||
229 | ] | ||
230 | } | ||
231 | } | ||
232 | } | ||
233 | ``` | ||
234 | |||
235 | Arrays can be introduced at either the label definition or block body | ||
236 | definition levels to define multiple definitions of the same block type | ||
237 | or labels while preserving order. | ||
238 | |||
239 | A JSON HCL parser _must_ support duplicate definitions of the same property | ||
240 | name within a single object, preserving all of them and the relative ordering | ||
241 | between them. The array-based forms are also required so that JSON HCL | ||
242 | configurations can be produced with JSON producing libraries that are not | ||
243 | able to preserve property definition order and multiple definitions of | ||
244 | the same property. | ||
245 | |||
246 | ## Expressions | ||
247 | |||
248 | JSON lacks a native expression syntax, so the HCL JSON syntax instead defines | ||
249 | a mapping for each of the JSON value types, including a special mapping for | ||
250 | strings that allows optional use of arbitrary expressions. | ||
251 | |||
252 | ### Objects | ||
253 | |||
254 | When interpreted as an expression, a JSON object represents a value of a HCL | ||
255 | object type. | ||
256 | |||
257 | Each property of the JSON object represents an attribute of the HCL object type. | ||
258 | The property name string given in the JSON input is interpreted as a string | ||
259 | expression as described below, and its result is converted to string as defined | ||
260 | by the syntax-agnostic information model. If such a conversion is not possible, | ||
261 | an error is produced and evaluation fails. | ||
262 | |||
263 | An instance of the constructed object type is then created, whose values | ||
264 | are interpreted by again recursively applying the mapping rules defined in | ||
265 | this section to each of the property values. | ||
266 | |||
267 | If any evaluated property name strings produce null values, an error is | ||
268 | produced and evaluation fails. If any produce _unknown_ values, the _entire | ||
269 | object's_ result is an unknown value of the dynamic pseudo-type, signalling | ||
270 | that the type of the object cannot be determined. | ||
271 | |||
272 | It is an error to define the same property name multiple times within a single | ||
273 | JSON object interpreted as an expression. In full expression mode, this | ||
274 | constraint applies to the name expression results after conversion to string, | ||
275 | rather than the raw string that may contain interpolation expressions. | ||
276 | |||
277 | ### Arrays | ||
278 | |||
279 | When interpreted as an expression, a JSON array represents a value of a HCL | ||
280 | tuple type. | ||
281 | |||
282 | Each element of the JSON array represents an element of the HCL tuple type. | ||
283 | The tuple type is constructed by enumerationg the JSON array elements, creating | ||
284 | for each an element whose type is the result of recursively applying the | ||
285 | expression mapping rules. Correspondance is preserved between the array element | ||
286 | indices and the tuple element indices. | ||
287 | |||
288 | An instance of the constructed tuple type is then created, whose values are | ||
289 | interpreted by again recursively applying the mapping rules defined in this | ||
290 | section. | ||
291 | |||
292 | ### Numbers | ||
293 | |||
294 | When interpreted as an expression, a JSON number represents a HCL number value. | ||
295 | |||
296 | HCL numbers are arbitrary-precision decimal values, so a JSON HCL parser must | ||
297 | be able to translate exactly the value given to a number of corresponding | ||
298 | precision, within the constraints set by the HCL syntax-agnostic information | ||
299 | model. | ||
300 | |||
301 | In practice, off-the-shelf JSON serializers often do not support customizing the | ||
302 | processing of numbers, and instead force processing as 32-bit or 64-bit | ||
303 | floating point values. | ||
304 | |||
305 | A _producer_ of JSON HCL that uses such a serializer can provide numeric values | ||
306 | as JSON strings where they have precision too great for representation in the | ||
307 | serializer's chosen numeric type in situations where the result will be | ||
308 | converted to number (using the standard conversion rules) by a calling | ||
309 | application. | ||
310 | |||
311 | Alternatively, for expressions that are evaluated in full expression mode an | ||
312 | embedded template interpolation can be used to faithfully represent a number, | ||
313 | such as `"${1e150}"`, which will then be evaluated by the underlying HCL native | ||
314 | syntax expression evaluator. | ||
315 | |||
316 | ### Boolean Values | ||
317 | |||
318 | The JSON boolean values `true` and `false`, when interpreted as expressions, | ||
319 | represent the corresponding HCL boolean values. | ||
320 | |||
321 | ### The Null Value | ||
322 | |||
323 | The JSON value `null`, when interpreted as an expression, represents a | ||
324 | HCL null value of the dynamic pseudo-type. | ||
325 | |||
326 | ### Strings | ||
327 | |||
328 | When intepreted as an expression, a JSON string may be interpreted in one of | ||
329 | two ways depending on the evaluation mode. | ||
330 | |||
331 | If evaluating in literal-only mode (as defined by the syntax-agnostic | ||
332 | information model) the literal string is intepreted directly as a HCL string | ||
333 | value, by directly using the exact sequence of unicode characters represented. | ||
334 | Template interpolations and directives MUST NOT be processed in this mode, | ||
335 | allowing any characters that appear as introduction sequences to pass through | ||
336 | literally: | ||
337 | |||
338 | ```json | ||
339 | "Hello world! Template sequences like ${ are not intepreted here." | ||
340 | ``` | ||
341 | |||
342 | When evaluating in full expression mode (again, as defined by the syntax- | ||
343 | agnostic information model) the literal string is instead interpreted as a | ||
344 | _standalone template_ in the HCL Native Syntax. The expression evaluation | ||
345 | result is then the direct result of evaluating that template with the current | ||
346 | variable scope and function table. | ||
347 | |||
348 | ```json | ||
349 | "Hello, ${name}! Template sequences are interpreted in full expression mode." | ||
350 | ``` | ||
351 | |||
352 | In particular the _Template Interpolation Unwrapping_ requirement from the | ||
353 | HCL native syntax specification must be implemented, allowing the use of | ||
354 | single-interpolation templates to represent expressions that would not | ||
355 | otherwise be representable in JSON, such as the following example where | ||
356 | the result must be a number, rather than a string representation of a number: | ||
357 | |||
358 | ```json | ||
359 | "${ a + b }" | ||
360 | ``` | ||
361 | |||
362 | ## Static Analysis | ||
363 | |||
364 | The HCL static analysis operations are implemented for JSON values that | ||
365 | represent expressions, as described in the following sections. | ||
366 | |||
367 | Due to the limited expressive power of the JSON syntax alone, use of these | ||
368 | static analyses functions rather than normal expression evaluation is used | ||
369 | as additional context for how a JSON value is to be interpreted, which means | ||
370 | that static analyses can result in a different interpretation of a given | ||
371 | expression than normal evaluation. | ||
372 | |||
373 | ### Static List | ||
374 | |||
375 | An expression interpreted as a static list must be a JSON array. Each of the | ||
376 | values in the array is interpreted as an expression and returned. | ||
377 | |||
378 | ### Static Map | ||
379 | |||
380 | An expression interpreted as a static map must be a JSON object. Each of the | ||
381 | key/value pairs in the object is presented as a pair of expressions. Since | ||
382 | object property names are always strings, evaluating the key expression with | ||
383 | a non-`nil` evaluation context will evaluate any template sequences given | ||
384 | in the property name. | ||
385 | |||
386 | ### Static Call | ||
387 | |||
388 | An expression interpreted as a static call must be a string. The content of | ||
389 | the string is interpreted as a native syntax expression (not a _template_, | ||
390 | unlike normal evaluation) and then the static call analysis is delegated to | ||
391 | that expression. | ||
392 | |||
393 | If the original expression is not a string or its contents cannot be parsed | ||
394 | as a native syntax expression then static call analysis is not supported. | ||
395 | |||
396 | ### Static Traversal | ||
397 | |||
398 | An expression interpreted as a static traversal must be a string. The content | ||
399 | of the string is interpreted as a native syntax expression (not a _template_, | ||
400 | unlike normal evaluation) and then static traversal analysis is delegated | ||
401 | to that expression. | ||
402 | |||
403 | If the original expression is not a string or its contents cannot be parsed | ||
404 | as a native syntax expression then static call analysis is not supported. | ||
405 | |||