View Source HXL (hxl v0.2.1)

HXL


CI Hex.pm Version

An Elixir implementation of HCL

features

Features

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

example-usage

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

From file

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

as-ast

As ast

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

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

installation

Installation

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

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

hcl-syntax-specification

HCL Syntax Specification

lexical-elements

Lexical Elements

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

structural-language

Structural Language

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

expression-language

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

Template Language

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

representations

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

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

Link to this section Functions

Link to this function

decode(binary, opts \\ [])

View Source
@spec 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

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

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
@spec decode!(binary(), opts()) :: map() | no_return()

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

See from_binary/1

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

Decode a binary to a HXL document AST.

examples

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
@spec decode_file(Path.t(), opts()) :: {:ok, map()} | {:error, term()}

Reads a HCL document from file.

Uses same options as decode/2

examples

Examples

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

decode_file!(path, opts \\ [])

View Source
@spec 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