HashiCorp Configuration Language

repository·main·Indexed 26 days ago

https://github.com/hashicorp/hcl

A toolkit for creating structured, human-readable, and machine-parseable configuration languages designed for DevOps and server-side tools. It includes the hcldec CLI for transforming HCL to JSON and various extensions for dynamic blocks (dynblock), custom decoding (customdecode), type expressions (typeexpr), and conditional functions like try and can (tryfunc).

Tokens
34.1K
Snippets
71
Records
201
Agent score
90%

What's inside HCL

  1. Overview of HCL Extensions

    main
    HCL Extensions are optional packages that build on the core HCL API to add additional features and expressiveness to the language. These extensions are intended for specific use-cases where increased dynamic behavior is acceptable. Note that using extensions may make the language less rigid compared to the core HCL implementation, which might be undesirable for applications requiring strict configuration structures.
  2. Understand the HCL toolkit capabilities

    main

    HCL (HashiCorp Configuration Language) is a toolkit designed to help developers create structured configuration languages that serve both humans and machines.

    Key features include:

    • Dual Syntax: Supports a native syntax optimized for human readability/writability and a JSON-based variant optimized for machine generation and parsing.
    • Expression Syntax: Enables basic inline computation.
    • Dynamic Configuration: Supports variables and functions when integrated with a calling application.
    • Schema Validation: Allows applications to define expected argument names and nested block types. HCL parses the configuration, verifies it conforms to the defined structure, and returns high-level objects for processing.

    Note: HCL is primarily intended for use in Go applications via its library API.

  3. Understand HCL core constructs: arguments and blocks

    main

    HCL configuration is composed of two primary building blocks: arguments (also called attributes) and blocks.

    • Arguments: Key-value pairs assigned within a body (e.g., io_mode = "async").
    • Blocks: Named structures that can contain nested arguments and blocks. Blocks can optionally include labels (quoted names following the block type).
    • Body: The collection of arguments and blocks at a specific nesting level. Every HCL file has a root body, and every block has its own body.

    Unlike JSON or YAML, HCL is a structured configuration language that is always decoded using an application-defined schema.

    io_mode = "async"
    
    service "http" "web_proxy" {
      listen_addr = "127.0.0.1:8080"
    
      process "main" {
        command = ["/usr/local/bin/awesome-app", "server"]
      }
    }
  4. Understand the `hcldec` spec format

    main

    The hcldec spec format is used to instruct the hcldec tool on how to validate HCL configuration files and translate them into JSON.

    Key concepts:

    • Spec Files: Must contain a single top-level spec block that describes the root JSON value. This block can contain nested spec blocks to create nested JSON structures.
    • Spec Blocks: Each block serves as a mapping action and often a validation constraint. Each block produces exactly one JSON value.
    • Context (Body): Specs are evaluated within an HCL body. Some spec types (like block, block_list, etc.) change the context to the body of the matched HCL element, allowing for deep decoding of nested structures.
  5. Understand the HCL language structure

    main

    HCL is composed of three integrated sub-languages used together in configuration files:

    • Structural language: Defines the hierarchical configuration structure using bodies, blocks, and attributes.
    • Expression language: Used to express attribute values as literals or derivations of other values.
    • Template language: Used to compose values together into strings via interpolation.

    While typically used together, the expression and template languages can be used in isolation for tools like REPLs or debuggers.

  6. HCL JSON Syntax Specification Overview

    main

    HCL provides a JSON-based serialization format designed for machine-generated configuration. While the native HCL syntax is optimized for human readability, the JSON syntax is intended to be easily produced by standard JSON implementations in various programming languages.

    To correctly parse HCL JSON, a parser must be able to:

    • Preserve the relative ordering of properties in an object.
    • Preserve multiple definitions of the same property name.
    • Preserve numeric values with the precision required by the HCL information model.
    • Retain source location information for tokens to provide accurate error messages.
  7. Understand the HCL Information Model

    main

    HCL (HashiCorp Configuration Language) is a system for defining configuration languages. It uses an abstract information model that allows multiple concrete syntaxes (such as the HCL native syntax and JSON syntax) to map to a common set of semantic types and structures.

    Core Structural Elements

    • Body: The primary container representing a set of zero or more attributes and zero or more blocks.
    • Configuration File: The top-level object, which is a body representing the root attributes and blocks.
    • Attribute: A unique name and value pair within a body. Values are provided as expressions.
    • Block: A nested structure containing a type name, zero or more string labels (identifiers), and a nested body.
  8. Understand HCL Information Model: Attributes and Blocks

    main

    HCL is built around two primary constructs:

    1. Attributes: Key-value pairs (e.g., io_mode = "async").
    2. Blocks: Hierarchical structures that can contain attributes or nested blocks (e.g., service "http" "web_proxy" { ... }).

    This model allows for both human-readable native syntax and machine-friendly JSON representation. The API remains consistent regardless of whether the source is HCL native syntax or JSON.

  9. Use HCL Templates to combine strings and values

    main

    HCL Templates are a sub-language used to concisely combine strings and other values into a single string. A template behaves like an expression that always returns a string value. If any element produces an unknown string or a dynamic pseudo-type, the entire result becomes an unknown string.

    Templates consist of:

    • Template Literals: Literal sequences of characters.
    • Template Interpolations: ${expression} syntax to evaluate and insert values.
    • Template Directives: Control flow like if and for.
  10. Install file2fuzz to prepare seed corpus

    main

    If you want to add additional seed inputs to the fuzzing corpus, files must be in the Go 1.18 corpus file format. You can use the file2fuzz tool to convert files to this format.

    $ go install golang.org/x/tools/cmd/file2fuzz@latest
    $ file2fuzz -help
  11. Use HCL in a Go application

    main

    HCL is primarily intended to be used as a library within Go programs. It provides several ways to define and process configuration languages depending on the complexity of your requirements:

    • Simple decoding: For straightforward configurations, HCL can decode directly into Go struct values, behaving similarly to the encoding/json or encoding/xml packages.
    • Complex processing: For languages with complex structures or portions where the schema cannot be determined until runtime, the HCL Go API offers alternative approaches.

    Available integration patterns include parsing, diagnostics, decoding via gohcl or hcldec, expression evaluation, and low-level decoding.

  12. Use JSON syntax for HCL configuration

    main

    HCL provides a JSON-based alternative syntax. This allows developers to generate HCL configuration programmatically using standard JSON serializers. The calling application can choose to support both HCL and JSON syntaxes. When using JSON, the application's schema is used to resolve ambiguities (such as whether a JSON object represents a nested block or an object expression).

    {
      "io_mode": "async",
      "service": {
        "http": {
          "web_proxy": {
            "listen_addr": "127.0.0.1:8080",
            "process": {
              "main": {
                "command": ["/usr/local/bin/awesome-app", "server"]
              },
              "mgmt": {
                "command": ["/usr/local/bin/awesome-app", "mgmt"]
              }
            }
          }
        }
      }
    }