hcllight

module
v0.1.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 9, 2024 License: Apache-2.0

README

HCL Light

This hcllight package removes position and location tags in hclsyntax , the official AST parsing package for HCL (HashiCorp Configuration Language).

  • It allows for dynamic manipulation of attributes, variables, expressions and blocks, after which the tree can be output back to HCL data.
  • The output can be made with or without the evaluation of logic expressions in HCL.

Two applications are packed together:

  • jsm, to parse JSON Schema document, draft-04, in HCL
  • hcl, to parse OpenAPI description, version 3.0 and 3.1, in HCL

We obtain OpenAPI and JSON Schema files that are of 50% in size of the corresponding JSON files.

Here is a Medium article on JSON Schema.

To install,

go install github.com/genelet/hcllight

See the reference to use hcllight, JSON Schema and OpenAPI packages,

GoDoc

Example

Here is a HCL sample:

TEST_FOLDER = "__test__"
EXECUTION_ID = random(6)
version = 2
say = {
    for k, v in {hello: "world"}: k => v if k == "hello"
}

job check "this is a temporal job" {
  python "run.py" {}
}

job e2e "running integration tests" {

  python "app-e2e.py" {
    root_dir = var.TEST_FOLDER
    python_version = version + 6
  }

  slack {
    channel  = "slack-my-channel"
    message = "Job execution ${EXECUTION_ID} completed successfully"
  }
}

This program parses the HCL data into the document node, Body, and outputs it in HCL format, with and without evaluation.

package main

import (
	"fmt"
	"math/rand"
	"os"

	"github.com/genelet/hcllight/light"

	"github.com/zclconf/go-cty/cty"
	"github.com/zclconf/go-cty/cty/function"
)

func main() {
	body, err := parseFile("random.hcl")
	if err != nil {
		panic(err)
	}
	hcl, err := body.Hcl()
	if err != nil {
		panic(err)
	}

	ref := getRef()
	eval, err := body.Evaluate(ref)
	if err != nil {
		panic(err)
	}

	fmt.Printf("hcl: %s\n", hcl)
	fmt.Printf("evaluated: %s\n", eval)
}

func parseFile(filename string) (*light.Body, error) {
	dat, err := os.ReadFile(filename)
	if err != nil {
		return nil, err
	}
	return light.Parse(dat)
}

func getRef() map[string]interface{} {
	return map[string]interface{}{
		"functions": map[string]function.Function{
			"random": function.New(&function.Spec{
				VarParam: nil,
				Params: []function.Parameter{
					{Type: cty.Number},
				},
				Type: func(args []cty.Value) (cty.Type, error) {
					return cty.String, nil
				},
				Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
					var letterRunes = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
					n, _ := args[0].AsBigFloat().Int64()
					b := make([]rune, n)
					for i := range b {
						b[i] = letterRunes[rand.Intn(len(letterRunes))]
					}
					return cty.StringVal(string(b)), nil
				},
			}),
		},
	}
}

The result is

hcl: 
  TEST_FOLDER = "__test__"
  EXECUTION_ID = random(6)
  version = 2
  say = {
    for k, v in {hello:"world"}: k => v if k == "hello"
  }
  job "check" "this is a temporal job" {
    python "run.py" {}
  }
  job "e2e" "running integration tests" {
    python "app-e2e.py" {
      root_dir = var.TEST_FOLDER
      python_version = version + 6
    }
    slack {
      message = "Job execution ${EXECUTION_ID} completed successfully"
      channel = "slack-my-channel"
    }
  }

evaluated: 
  say = {
    hello = "world"
  }
  TEST_FOLDER = "__test__"
  EXECUTION_ID = "nOVqNf"
  version = 2
  job "check" "this is a temporal job" {
    python "run.py" {}
  }
  job "e2e" "running integration tests" {
    python "app-e2e.py" {
      root_dir = "__test__"
      python_version = 8
    }
    slack {
      message = "Job execution nOVqNf completed successfully"
      channel = "slack-my-channel"
    }
  }

Directories

Path Synopsis
internal
ast
kin
loa

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL