HXL (hxl v0.2.0) View Source

HXL


CI Hex.pm Version

An Elixir implementation of HCL

Features

  • Decode from string or file
  • Aims to be fully compliant with the HCL specification
  • Function & variables support during evaluation

Example Usage

hcl = """
resource "upcloud_server" "server1" {
  hostname = "terraform.example.com"

  zone = "nl-ams1"

  plan = "1xCPU-1GB"

  template {
    size = 25
    storage = "01000000-0000-4000-8000-000030200200"
  }

  network_interface {
    type = "public"
  }

  login {
    user = "root"
    keys = [
      "ssh-rsa public key",
    ]
    create_password = true
    password_delivery = "email"
  }

  connection {
    host        = "127.0.0.2"
    type        = "ssh"
    user        = "root"
    private_key = file("~/.ssh/rsa_private_key")
  }

  provisioner "remote-exec" {
    inline = [
      "echo 'Hello world!'"
    ]
  }
}
"""

{:ok, config_file} = HXL.decode(hcl, functions: %{"file" => &File.read/1})

From file

{:ok, config_file} = HXL.decode_file("/path/to/file")

As ast

hcl = """
service "http" {
  a = 1
  b = 2
}
"""

{:ok %HXL.Body{}} = HXL.decode_as_ast(hcl)

Installation

Add hxl to your list of dependencies in mix.exs:

def deps do
  [
    {:hxl, "~> 0.1.0"}
  ]
end

HCL Syntax Specification

Lexical Elements

  • [x] Comments
  • [x] Identifiers
  • [x] Operators & delimiters
  • [x] Numeric literals

Structural Language

  • [x] Body
  • [x] Attributes
  • [x] Blocks
  • [x] One-line blocks

Expression language

  • [x] Expressions
    • [x] Expr term
      • [x] Literal Value
      • [x] Collection Value
      • [x] Template Expr
      • [x] Variable Expr
      • [x] Function Call
      • [x] For Expr
      • [x] ExprTerm Index
      • [x] ExprTerm GetAttr
      • [x] ExprTerm Splat
      • [x] "(" Expression ")"
    • [x] Operation
    • [x] Conditional

Template Language

  • [] TemplateLiteral
  • [] TemplateInterpolation
  • [] TemplateDirective

Representations

  • [x] HCL Native syntax
  • [ ] JSON

Link to this section Summary

Functions

Decode a binary to a HCL document.

Reads a HCL document from a binary. Returns the document or raises HXL.Error.

Decode a binary to a HXL document AST.

Reads a HCL document from file.

Reads a HCL document from file, returns the document directly or raises HXL.Error.

Link to this section Types

Specs

opt() ::
  {:variables, map()}
  | {:functions, map()}
  | {:keys, :atoms | :string | (binary() -> term())}
  | {:evaluator, HXL.Evaluator.t()}

Specs

opts() :: [opt()]

Link to this section Functions

Link to this function

decode(binary, opts \\ [])

View Source

Specs

decode(binary(), opts()) :: {:ok, map()} | {:error, term()}

Decode a binary to a HCL document.

decode/2 parses and evaluates the AST before returning the HCL docuement. If the document is using functions in it's definition, these needs to be passed in the opts part of this functions. See bellow for an example

Options

The following options can be passed to configure evaluation of the document:

  • :evaluator - A HXL.Evaluator module to interpret the AST during evaluation. See HXL.Evaluator for more information.
  • :functions - A map of (<function_name> -> <function>) to make available in document evaluation.
  • :variables - A map of Top level variables that should be injected into the context when evaluating the document.
  • :keys - controls how keys in the parsed AST are evaluated. Possible values are:
    • :strings (default) - evaluates keys as strings
    • :atoms - converts keys to atoms with String.to_atom/1
    • :atoms! - converts keys to atoms with String.to_existing_atom/1
    • (key -> term) - converts keys using the provided function

Examples

Using functions:

iex> hcl = "a = upper(trim("   a  "))"
"a = upper(trim("   a  "))"
iex> HXL.decode(hcl, functions: %{"upper" => &String.capitalize/1, "trim" => &String.trim/1})
{:ok, %{"a" => "A"}}

Using variables:

iex> hcl = "a = b"
"a = b"
iex> HXL.decode(hcl, variables: %{"b" => "B"})
{:ok, %{"a" => "B"}}
Link to this function

decode!(bin, opts \\ [])

View Source

Specs

decode!(binary(), opts()) :: map() | no_return()

Reads a HCL document from a binary. Returns the document or raises HXL.Error.

See from_binary/1

Specs

decode_as_ast(binary()) :: {:ok, HXL.Ast.t()} | {:error, term()}

Decode a binary to a HXL document AST.

Examples

iex> HXL.decode_as_ast("a = 1")
{:ok, %HXL.Ast.Body{
  statements: [
    %HXL.Ast.Attr{
      expr: %HXL.Ast.Literal{value: {:int, 1}}, name: "a"}
  ]
}}
Link to this function

decode_file(path, opts \\ [])

View Source

Specs

decode_file(Path.t(), opts()) :: {:ok, map()} | {:error, term()}

Reads a HCL document from file.

Uses same options as decode/2

Examples

iex> HXL.decode_file("/path/to/file.hcl")
{:ok, %{"a" => "b"}}
Link to this function

decode_file!(path, opts \\ [])

View Source

Specs

decode_file!(Path.t(), opts()) :: map() | no_return()

Reads a HCL document from file, returns the document directly or raises HXL.Error.

See decode_file/1