github.com/hashicorp/hcl/v2@v2.20.0/cmd/hcldec/spec-format.md (about) 1 # `hcldec` spec format 2 3 The `hcldec` spec format instructs [`hcldec`](README.md) on how to validate 4 one or more configuration files given in the HCL syntax and how to translate 5 the result into JSON format. 6 7 The spec format is itself built from HCL syntax, with each HCL block serving 8 as a _spec_ whose block type and contents together describe a single mapping 9 action and, in most cases, a validation constraint. Each spec block produces 10 one JSON value. 11 12 A spec _file_ must have a single top-level spec block that describes the 13 top-level JSON value `hcldec` will return, and that spec block may have other 14 nested spec blocks (depending on its type) that produce nested structures and 15 additional validation constraints. 16 17 The most common usage of `hcldec` is to produce a JSON object whose properties 18 are derived from the top-level content of the input file. In this case, the 19 root of the given spec file will have an `object` spec block whose contents 20 describe how each of the object's properties are to be populated using 21 nested spec blocks. 22 23 Each spec is evaluated in the context of an HCL _body_, which is the HCL 24 terminology for one level of nesting in a configuration file. The top-level 25 objects in a file all belong to the root body of that file, and then each 26 nested block has its own body containing the elements within that block. 27 Some spec types select a new body as the context for their nested specs, 28 allowing nested HCL structures to be decoded. 29 30 ## Spec Block Types 31 32 The following sections describe the different block types that can be used to 33 define specs within a spec file. 34 35 ### `object` spec blocks 36 37 The `object` spec type is the most commonly used at the root of a spec file. 38 Its result is a JSON object whose properties are set based on any nested 39 spec blocks: 40 41 ```hcl 42 object { 43 attr "name" { 44 type = string 45 } 46 block "address" { 47 object { 48 attr "street" { 49 type = string 50 } 51 # ... 52 } 53 } 54 } 55 ``` 56 57 Nested spec blocks inside `object` must always have an extra block label 58 `"name"`, `"address"` and `"street"` in the above example) that specifies 59 the name of the property that should be created in the JSON object result. 60 This label also acts as a default name selector for the nested spec, allowing 61 the `attr` blocks in the above example to omit the usually-required `name` 62 argument in cases where the HCL input name and JSON output name are the same. 63 64 An `object` spec block creates no validation constraints, but it passes on 65 any validation constraints created by the nested specs. 66 67 ### `array` spec blocks 68 69 The `array` spec type produces a JSON array whose elements are set based on 70 any nested spec blocks: 71 72 ```hcl 73 array { 74 attr { 75 name = "first_element" 76 type = string 77 } 78 attr { 79 name = "second_element" 80 type = string 81 } 82 } 83 ``` 84 85 An `array` spec block creates no validation constraints, but it passes on 86 any validation constraints created by the nested specs. 87 88 ### `attr` spec blocks 89 90 The `attr` spec type reads the value of an attribute in the current body 91 and returns that value as its result. It also creates validation constraints 92 for the given attribute name and its value. 93 94 ```hcl 95 attr { 96 name = "document_root" 97 type = string 98 required = true 99 } 100 ``` 101 102 `attr` spec blocks accept the following arguments: 103 104 * `name` (required) - The attribute name to expect within the HCL input file. 105 This may be omitted when a default name selector is created by a parent 106 `object` spec, if the input attribute name should match the output JSON 107 object property name. 108 109 * `type` (optional) - A [type expression](#type-expressions) that the given 110 attribute value must conform to. If this argument is set, `hcldec` will 111 automatically convert the given input value to this type or produce an 112 error if that is not possible. 113 114 * `required` (optional) - If set to `true`, `hcldec` will produce an error 115 if a value is not provided for the source attribute. 116 117 `attr` is a leaf spec type, so no nested spec blocks are permitted. 118 119 ### `block` spec blocks 120 121 The `block` spec type applies one nested spec block to the contents of a 122 block within the current body and returns the result of that spec. It also 123 creates validation constraints for the given block type name. 124 125 ```hcl 126 block { 127 block_type = "logging" 128 129 object { 130 attr "level" { 131 type = string 132 } 133 attr "file" { 134 type = string 135 } 136 } 137 } 138 ``` 139 140 `block` spec blocks accept the following arguments: 141 142 * `block_type` (required) - The block type name to expect within the HCL 143 input file. This may be omitted when a default name selector is created 144 by a parent `object` spec, if the input block type name should match the 145 output JSON object property name. 146 147 * `required` (optional) - If set to `true`, `hcldec` will produce an error 148 if a block of the specified type is not present in the current body. 149 150 `block` creates a validation constraint that there must be zero or one blocks 151 of the given type name, or exactly one if `required` is set. 152 153 `block` expects a single nested spec block, which is applied to the body of 154 the block of the given type when it is present. 155 156 ### `block_list` spec blocks 157 158 The `block_list` spec type is similar to `block`, but it accepts zero or 159 more blocks of a specified type rather than requiring zero or one. The 160 result is a JSON array with one entry per block of the given type. 161 162 ```hcl 163 block_list { 164 block_type = "log_file" 165 166 object { 167 attr "level" { 168 type = string 169 } 170 attr "filename" { 171 type = string 172 required = true 173 } 174 } 175 } 176 ``` 177 178 `block_list` spec blocks accept the following arguments: 179 180 * `block_type` (required) - The block type name to expect within the HCL 181 input file. This may be omitted when a default name selector is created 182 by a parent `object` spec, if the input block type name should match the 183 output JSON object property name. 184 185 * `min_items` (optional) - If set to a number greater than zero, `hcldec` will 186 produce an error if fewer than the given number of blocks are present. 187 188 * `max_items` (optional) - If set to a number greater than zero, `hcldec` will 189 produce an error if more than the given number of blocks are present. This 190 attribute must be greater than or equal to `min_items` if both are set. 191 192 `block` creates a validation constraint on the number of blocks of the given 193 type that must be present. 194 195 `block` expects a single nested spec block, which is applied to the body of 196 each matching block to produce the resulting list items. 197 198 ### `block_set` spec blocks 199 200 The `block_set` spec type behaves the same as `block_list` except that 201 the result is in no specific order and any duplicate items are removed. 202 203 ```hcl 204 block_set { 205 block_type = "log_file" 206 207 object { 208 attr "level" { 209 type = string 210 } 211 attr "filename" { 212 type = string 213 required = true 214 } 215 } 216 } 217 ``` 218 219 The contents of `block_set` are the same as for `block_list`. 220 221 ### `block_map` spec blocks 222 223 The `block_map` spec type is similar to `block`, but it accepts zero or 224 more blocks of a specified type rather than requiring zero or one. The 225 result is a JSON object, or possibly multiple nested JSON objects, whose 226 properties are derived from the labels set on each matching block. 227 228 ```hcl 229 block_map { 230 block_type = "log_file" 231 labels = ["filename"] 232 233 object { 234 attr "level" { 235 type = string 236 required = true 237 } 238 } 239 } 240 ``` 241 242 `block_map` spec blocks accept the following arguments: 243 244 * `block_type` (required) - The block type name to expect within the HCL 245 input file. This may be omitted when a default name selector is created 246 by a parent `object` spec, if the input block type name should match the 247 output JSON object property name. 248 249 * `labels` (required) - A list of user-oriented block label names. Each entry 250 in this list creates one level of object within the output value, and 251 requires one additional block header label on any child block of this type. 252 Block header labels are the quoted strings that appear after the block type 253 name but before the opening `{`. 254 255 `block` creates a validation constraint on the number of labels that blocks 256 of the given type must have. 257 258 `block` expects a single nested spec block, which is applied to the body of 259 each matching block to produce the resulting map items. 260 261 ## `block_attrs` spec blocks 262 263 The `block_attrs` spec type is similar to an `attr` spec block of a map type, 264 but it produces a map from the attributes of a block rather than from an 265 attribute's expression. 266 267 ```hcl 268 block_attrs { 269 block_type = "variables" 270 element_type = string 271 required = false 272 } 273 ``` 274 275 This allows a map with user-defined keys to be produced within block syntax, 276 but due to the constraints of that syntax it also means that the user will 277 be unable to dynamically-generate either individual key names using key 278 expressions or the entire map value using a `for` expression. 279 280 `block_attrs` spec blocks accept the following arguments: 281 282 * `block_type` (required) - The block type name to expect within the HCL 283 input file. This may be omitted when a default name selector is created 284 by a parent `object` spec, if the input block type name should match the 285 output JSON object property name. 286 287 * `element_type` (required) - The value type to require for each of the 288 attributes within a matched block. The resulting value will be a JSON 289 object whose property values are of this type. 290 291 * `required` (optional) - If `true`, an error will be produced if a block 292 of the given type is not present. If `false` -- the default -- an absent 293 block will be indicated by producing `null`. 294 295 ## `literal` spec blocks 296 297 The `literal` spec type returns a given literal value, and creates no 298 validation constraints. It is most commonly used with the `default` spec 299 type to create a fallback value, but can also be used e.g. to fill out 300 required properties in an `object` spec that do not correspond to any 301 construct in the input configuration. 302 303 ```hcl 304 literal { 305 value = "hello world" 306 } 307 ``` 308 309 `literal` spec blocks accept the following argument: 310 311 * `value` (required) - The value to return. This attribute may be an expression 312 that uses [functions](#spec-definition-functions). 313 314 `literal` is a leaf spec type, so no nested spec blocks are permitted. 315 316 ## `default` spec blocks 317 318 The `default` spec type evaluates a sequence of nested specs in turn and 319 returns the result of the first one that produces a non-null value. 320 It creates no validation constraints of its own, but passes on the validation 321 constraints from its first nested block. 322 323 ```hcl 324 default { 325 attr { 326 name = "private" 327 type = bool 328 } 329 literal { 330 value = false 331 } 332 } 333 ``` 334 335 A `default` spec block must have at least one nested spec block, and should 336 generally have at least two since otherwise the `default` wrapper is a no-op. 337 338 The second and any subsequent spec blocks are _fallback_ specs. These exhibit 339 their usual behavior but are not able to impose validation constraints on the 340 current body since they are not evaluated unless all prior specs produce 341 `null` as their result. 342 343 ## `transform` spec blocks 344 345 The `transform` spec type evaluates one nested spec and then evaluates a given 346 expression with that nested spec result to produce a final value. 347 It creates no validation constraints of its own, but passes on the validation 348 constraints from its nested block. 349 350 ```hcl 351 transform { 352 attr { 353 name = "size_in_mb" 354 type = number 355 } 356 357 # Convert result to a size in bytes 358 result = nested * 1024 * 1024 359 } 360 ``` 361 362 `transform` spec blocks accept the following argument: 363 364 * `result` (required) - The expression to evaluate on the result of the nested 365 spec. The variable `nested` is defined when evaluating this expression, with 366 the result value of the nested spec. 367 368 The `result` expression may use [functions](#spec-definition-functions). 369 370 ## Predefined Variables 371 372 `hcldec` accepts values for variables to expose into the input file's 373 expression scope as CLI options, and this is the most common way to pass 374 values since it allows them to be dynamically populated by the calling 375 application. 376 377 However, it's also possible to pre-define variables with constant values 378 within a spec file, using the top-level `variables` block type: 379 380 ```hcl 381 variables { 382 name = "Stephen" 383 } 384 ``` 385 386 Variables of the same name defined via the `hcldec` command line with override 387 predefined variables of the same name, so this mechanism can also be used to 388 provide defaults for variables that are overridden only in certain contexts. 389 390 ## Custom Functions 391 392 The spec can make arbitrary HCL functions available in the input file's 393 expression scope, and thus allow simple computation within the input file, 394 in addition to HCL's built-in operators. 395 396 Custom functions are defined in the spec file with the top-level `function` 397 block type: 398 399 ``` 400 function "add_one" { 401 params = [n] 402 result = n + 1 403 } 404 ``` 405 406 Functions behave in a similar way to the `transform` spec type in that the 407 given `result` attribute expression is evaluated with additional variables 408 defined with the same names as the defined `params`. 409 410 The [spec definition functions](#spec-definition-functions) can be used within 411 custom function expressions, allowing them to be optionally exposed into the 412 input file: 413 414 ``` 415 function "upper" { 416 params = [str] 417 result = upper(str) 418 } 419 420 function "min" { 421 params = [] 422 variadic_param = nums 423 result = min(nums...) 424 } 425 ``` 426 427 Custom functions defined in the spec cannot be called from the spec itself. 428 429 ## Spec Definition Functions 430 431 Certain expressions within a specification may use the following functions. 432 The documentation for each spec type above specifies where functions may 433 be used. 434 435 * `abs(number)` returns the absolute (positive) value of the given number. 436 * `coalesce(vals...)` returns the first non-null value given. 437 * `concat(lists...)` concatenates together all of the given lists to produce a new list. 438 * `hasindex(val, idx)` returns true if the expression `val[idx]` could succeed. 439 * `int(number)` returns the integer portion of the given number, rounding towards zero. 440 * `jsondecode(str)` interprets the given string as JSON and returns the resulting data structure. 441 * `jsonencode(val)` returns a JSON-serialized version of the given value. 442 * `length(collection)` returns the number of elements in the given collection (list, set, map, object, or tuple). 443 * `lower(string)` returns the given string with all uppercase letters converted to lowercase. 444 * `max(numbers...)` returns the greatest of the given numbers. 445 * `min(numbers...)` returns the smallest of the given numbers. 446 * `reverse(string)` returns the given string with all of the characters in reverse order. 447 * `strlen(string)` returns the number of characters in the given string. 448 * `substr(string, offset, length)` returns the requested substring of the given string. 449 * `upper(string)` returns the given string with all lowercase letters converted to uppercase. 450 451 Note that these expressions are valid in the context of the _spec_ file, not 452 the _input_. Functions can be exposed into the input file using 453 [Custom Functions](#custom-functions) within the spec, which may in turn 454 refer to these spec definition functions. 455 456 ## Type Expressions 457 458 Type expressions are used to describe the expected type of an attribute, as 459 an additional validation constraint. 460 461 A type expression uses primitive type names and compound type constructors. 462 A type constructor builds a new type based on one or more type expression 463 arguments. 464 465 The following type names and type constructors are supported: 466 467 * `any` is a wildcard that accepts a value of any type. (In HCL terms, this 468 is the _dynamic pseudo-type_.) 469 * `string` is a Unicode string. 470 * `number` is an arbitrary-precision floating point number. 471 * `bool` is a boolean value (`true` or `false`) 472 * `list(element_type)` constructs a list type with the given element type 473 * `set(element_type)` constructs a set type with the given element type 474 * `map(element_type)` constructs a map type with the given element type 475 * `object({name1 = element_type, name2 = element_type, ...})` constructs 476 an object type with the given attribute types. 477 * `tuple([element_type, element_type, ...])` constructs a tuple type with 478 the given element types. This can be used, for example, to require an 479 array with a particular number of elements, or with elements of different 480 types. 481 482 The above types are as defined by 483 [the HCL syntax-agnostic information model](../../spec.md). After 484 validation, values are lowered to JSON's type system, which is a subset 485 of the HCL type system. 486 487 `null` is a valid value of any type, and not a type itself.