hclutil

package module
v0.5.3 Latest Latest
Warning

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

Go to latest
Published: Sep 19, 2023 License: MIT Imports: 24 Imported by: 5

README

hclutil

HCL utility for Golang

GoDoc Go Report Card License

Overview

This package provides middleware and utility functions for easy logging management. It enables color-coded display for different log levels and automatically collects attributes set in the context. This allows developers to have flexible logging recording and analysis capabilities.

Installation

go get github.com/mashiike/hclutil

Usage

sample code

package main

import (
	"fmt"
	"log"

	"github.com/hashicorp/hcl/v2/gohcl"
	"github.com/mashiike/hclutil"
	"github.com/zclconf/go-cty/cty"
)

type Config struct {
	App struct {
		RequiredVresion cty.Value `hcl:"required_version"`
		Name            string    `hcl:"name"`
		Description     string    `hcl:"description"`
	} `hcl:"app,block"`
}

func main() {
	var v Config
	body, writer, diags := hclutil.Parse("./")
	if diags.HasErrors() {
		writer.WriteDiagnostics(diags)
		log.Fatal("parse failed")
	}
	evalCtx := hclutil.NewEvalContext()
	body, evalCtx, diags = hclutil.DecodeLocals(body, evalCtx)
	if diags.HasErrors() {
		writer.WriteDiagnostics(diags)
		log.Fatal("parse failed")
	}
	diags = gohcl.DecodeBody(body, evalCtx, &v)
	if diags.HasErrors() {
		writer.WriteDiagnostics(diags)
		log.Fatal("parse failed")
	}
	fmt.Println("name:", v.App.Name)
	fmt.Println("description:", v.App.Description)

	var vc hclutil.VersionConstraints
	if err := hclutil.UnmarshalCTYValue(v.App.RequiredVresion, &vc); err != nil {
		log.Fatal(err)
	}
	fmt.Println("required_version:", vc.String())
	fmt.Println("v1.2.3 is satisfied:", vc.ValidateVersion("v1.2.3") == nil)
}
NewEvalContext

this function is create new EvalContext with helpful functions.

DecodeLocals

this function is decode locals block and return new body and EvalContext.

UnmarshalCTYValue

this function is unmarshal cty.Value to Any.

License

This project is licensed under the MIT License - see the LICENSE(./LICENCE) file for details.

Contribution

Contributions, bug reports, and feature requests are welcome. Pull requests are also highly appreciated. For more details, please

Documentation

Overview

Example
package main

import (
	"fmt"
	"log"
	"testing/fstest"
	"time"

	"github.com/hashicorp/hcl/v2/gohcl"
	"github.com/mashiike/hclutil"
)

func main() {
	var sysValue int
	config := `

locals {
	value = "hoge"
}

app {
	name = upper(local.value)
	description = templatefile("description.txt", { value = local.value })
}
	`
	testFs := fstest.MapFS{
		"description.txt": {
			Data:    []byte("hello, ${value}"),
			Mode:    0,
			ModTime: time.Now(),
			Sys:     &sysValue,
		},
		"config.hcl": {
			Data:    []byte(config),
			Mode:    0,
			ModTime: time.Now(),
			Sys:     &sysValue,
		},
	}

	body, writer, diags := hclutil.ParseFS(testFs)
	if diags.HasErrors() {
		writer.WriteDiagnostics(diags)
		log.Fatal("parse failed")
	}
	evalCtx := hclutil.NewEvalContext(hclutil.WithFS(testFs))
	body, evalCtx, diags = hclutil.DecodeLocals(body, evalCtx)
	if diags.HasErrors() {
		writer.WriteDiagnostics(diags)
		log.Fatal("parse failed")
	}

	var v struct {
		App struct {
			Name        string `hcl:"name"`
			Description string `hcl:"description"`
		} `hcl:"app,block"`
	}
	diags = gohcl.DecodeBody(body, evalCtx, &v)
	if diags.HasErrors() {
		writer.WriteDiagnostics(diags)
		log.Fatal("parse failed")
	}
	fmt.Println("name:", v.App.Name)
	fmt.Println("description:", v.App.Description)
}
Output:

name: HOGE
description: hello, hoge

Index

Examples

Constants

This section is empty.

Variables

View Source
var DurationFunc = function.New(&function.Spec{
	Params: []function.Parameter{
		{
			Name:        "d",
			Type:        cty.String,
			AllowMarked: true,
		},
	},
	Type: function.StaticReturnType(cty.Number),
	Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
		durationArg, durationMarks := args[0].Unmark()
		durationStr := durationArg.AsString()
		d, err := time.ParseDuration(durationStr)
		if err != nil {
			return cty.UnknownVal(cty.Number), err
		}
		return cty.NumberFloatVal(float64(d) / float64(time.Second)).WithMarks(durationMarks), nil
	},
})

DurationFunc は指定された文字列をパースして、秒数に変換します。 DurationFunc parses the specified string and converts it to seconds.

View Source
var EnvFunc = function.New(&function.Spec{
	Params: []function.Parameter{
		{
			Name:        "key",
			Type:        cty.String,
			AllowMarked: true,
		},
		{
			Name:         "default",
			Type:         cty.String,
			AllowNull:    true,
			AllowUnknown: true,
		},
	},
	Type: function.StaticReturnType(cty.String),
	Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
		keyArg, keyMarks := args[0].Unmark()
		key := keyArg.AsString()
		if value := os.Getenv(key); value != "" {
			return cty.StringVal(value).WithMarks(keyMarks), nil
		}
		if args[1].IsNull() {
			return cty.StringVal("").WithMarks(keyMarks), nil
		}
		return cty.StringVal(args[1].AsString()).WithMarks(keyMarks), nil
	},
})
View Source
var MustEnvFunc = function.New(&function.Spec{
	Params: []function.Parameter{
		{
			Name:        "key",
			Type:        cty.String,
			AllowMarked: true,
		},
	},
	Type: function.StaticReturnType(cty.String),
	Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
		keyArg, keyMarks := args[0].Unmark()
		key := keyArg.AsString()
		value := os.Getenv(key)
		if value == "" {
			err := function.NewArgError(0, fmt.Errorf("env `%s` is not set", key))
			return cty.UnknownVal(cty.String), err
		}
		return cty.StringVal(value).WithMarks(keyMarks), nil
	},
})
View Source
var NowFunc = function.New(&function.Spec{
	Params: []function.Parameter{},
	Type:   function.StaticReturnType(cty.Number),
	Impl: func(_ []cty.Value, retType cty.Type) (cty.Value, error) {
		return cty.NumberFloatVal(nowUnixSeconds()), nil
	},
})

NowFunc は現在時刻を返すHCLの関数です。 NowFunc is a HCL function that returns the current time.

View Source
var StrftimeFunc = function.New(&function.Spec{
	Params: []function.Parameter{
		{
			Name:        "layout",
			Type:        cty.String,
			AllowMarked: true,
		},
		{
			Name:        "unixSeconds",
			Type:        cty.Number,
			AllowMarked: true,
			AllowNull:   true,
		},
	},
	Type: function.StaticReturnType(cty.String),
	Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
		layoutArg, layoutMarks := args[0].Unmark()
		layout := layoutArg.AsString()

		unixSecondsArg, unixSeconcsMarks := args[1].Unmark()
		var unixSeconds float64
		if unixSecondsArg.IsNull() {
			unixSeconds = nowUnixSeconds()
		} else {
			f := unixSecondsArg.AsBigFloat()
			unixSeconds, _ = f.Float64()
		}

		t, err := Strftime(layout, time.Local, unixSecondsToTime(unixSeconds))
		if err != nil {
			return cty.UnknownVal(cty.String), err
		}
		return cty.StringVal(t).WithMarks(layoutMarks, unixSeconcsMarks), nil
	},
})

StrftimeFunc は指定されたフォーマットで現在時刻を返すHCLの関数です。 StrftimeFunc is a HCL function that returns the current time in the specified format.

View Source
var StrftimeInZoneFunc = function.New(&function.Spec{
	Params: []function.Parameter{
		{
			Name:        "layout",
			Type:        cty.String,
			AllowMarked: true,
		},
		{
			Name:        "timeZone",
			Type:        cty.String,
			AllowMarked: true,
		},
		{
			Name:        "unixSeconds",
			Type:        cty.Number,
			AllowMarked: true,
			AllowNull:   true,
		},
	},
	Type: function.StaticReturnType(cty.String),
	Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
		layoutArg, layoutMarks := args[0].Unmark()
		layout := layoutArg.AsString()

		zoneArg, zoneMarks := args[1].Unmark()
		zone := zoneArg.AsString()

		unixSecondsArg, unixSeconcsMarks := args[2].Unmark()
		var unixSeconds float64
		if unixSecondsArg.IsNull() {
			unixSeconds = nowUnixSeconds()
		} else {
			f := unixSecondsArg.AsBigFloat()
			unixSeconds, _ = f.Float64()
		}

		t, err := StrftimeInZone(layout, zone, unixSecondsToTime(unixSeconds))
		if err != nil {
			return cty.UnknownVal(cty.String), err
		}
		return cty.StringVal(t).WithMarks(layoutMarks, zoneMarks, unixSeconcsMarks), nil
	},
})

StrftimeInZoneFunc は指定されたタイムゾーンでの時間をフォーマットするHCLの関数です。 StrftimeInZoneFunc is a HCL function that formats the time in the specified time zone.

Functions

func ConvertCTYValue

func ConvertCTYValue(value cty.Value) (any, error)

func DecodeLocals

func DecodeLocals(body hcl.Body, ctx *hcl.EvalContext) (hcl.Body, *hcl.EvalContext, hcl.Diagnostics)

DecodeLocals is a helper function to decode locals block.

func DumpCTYValue added in v0.2.0

func DumpCTYValue(v cty.Value) (string, error)

DumpCTYValue は cty.Value をJSON文字列に変換します。

これは、ログ出力等を行うときのデバッグ用途を想定しています。

func ExtructAttributes

func ExtructAttributes(body hcl.Body) (hcl.Attributes, hcl.Diagnostics)

ExtractAttributes interprets the contents of the HCL body as attributes, allowing for the contents to be accessed without prior knowledge of the structure. This function ignores any blocks present in the body and focuses solely on extracting attributes.

func MakeFileFunc

func MakeFileFunc(baseFSs ...fs.FS) function.Function

MakeFileFunc は file 関数を作成して返します。これは、指定されたパスのファイルを読み込んで返すHCLの関数です。 HCL中での使用例としては以下となります。 ``` text = file("path/to/file") ```

MakeFileFunc return a function that reads the file at the specified path and returns it. This is a HCL function that reads the file at the specified path and returns it. An example of use in HCL is as follows. ``` text = file("path/to/file") ```

func MakeTemplateFileFunc

func MakeTemplateFileFunc(functions map[string]function.Function, baseFSs ...fs.FS) function.Function

MakeTemplateFileFunc は templatefile 関数を作成して返します。これは、指定されたパスのファイルを読み込んでテンプレートとして処理し、結果を返すHCLの関数です。 HCL中での使用例としては以下となります。 ``` text = templatefile("path/to/file", {key = "value"}) ``` MakeTemplateFileFunc returns a function that creates the templatefile function. This is a HCL function that reads the file at the specified path, processes it as a template, and returns the result. An example of use in HCL is as follows. ``` text = templatefile("path/to/file", {key = "value"}) ```

func MarshalCTYValue

func MarshalCTYValue(v any) (cty.Value, error)
Example
package main

import (
	"fmt"
	"log"

	"github.com/mashiike/hclutil"
)

func main() {
	var v struct {
		Name string `cty:"name"`
		Age  int    `cty:"age"`
	}
	v.Name = "Alice"
	v.Age = 12

	ctyValue, err := hclutil.MarshalCTYValue(v)
	if err != nil {
		log.Fatalf("failed to marshal cty value: %s", err)
	}
	fmt.Println(hclutil.MustDumpCtyValue(ctyValue))

}
Output:

{"age":12,"name":"Alice"}

func MergeVariables added in v0.3.0

func MergeVariables(vars ...map[string]cty.Value) map[string]cty.Value

MergeVariables merges multiple variables into one.

func MustDumpCtyValue added in v0.2.0

func MustDumpCtyValue(v cty.Value) string

MustDumpCtyValue は cty.Value をJSON文字列に変換します。

DumpCTYValue と異なり、エラーが発生した場合は panic します

func NewEvalContext

func NewEvalContext(optFns ...func(*utilFunctionOptions)) *hcl.EvalContext

NewEvalContext は よく使う基本的な関数を登録したEvalContextを作成します。 NewEvalContext creates an EvalContext with basic functions.

func ParseExpression added in v0.5.0

func ParseExpression(expr []byte) (hcl.Expression, hcl.Diagnostics)

ParseExpression は HCLの式をパースします。

func RestrictBlock added in v0.4.0

func RestrictBlock(content *hcl.BodyContent, schemas ...BlockRestrictionSchema) hcl.Diagnostics

RestrictBlock implements the restriction that block

func Strftime

func Strftime(layout string, loc *time.Location, t time.Time) (string, error)

Strftime は指定されたタイムゾーンでの時間をフォーマットします。 Strftime formats the time in the specified time zone.

func StrftimeInZone

func StrftimeInZone(layout string, zone string, t time.Time) (string, error)

StrftimeInZone は指定されたタイムゾーンでの時間をフォーマットします。 StrftimeInZone formats the time in the specified time zone.

func TraversalToString added in v0.5.0

func TraversalToString(t hcl.Traversal) string

func UnmarshalCTYValue

func UnmarshalCTYValue(value cty.Value, v any) error

UnmarshalCTYValue decodes a cty.Value into the value pointed to by v.

Example
package main

import (
	"fmt"
	"log"

	"github.com/mashiike/hclutil"
	"github.com/zclconf/go-cty/cty"
)

func main() {
	var v struct {
		Name string `cty:"name"`
		Age  int    `cty:"age"`
	}

	ctyValue := cty.ObjectVal(map[string]cty.Value{
		"name": cty.StringVal("Alice"),
		"age":  cty.NumberIntVal(12),
	})

	if err := hclutil.UnmarshalCTYValue(ctyValue, &v); err != nil {
		log.Fatalf("failed to unmarshal cty value: %s", err)
	}
	fmt.Println("name:", v.Name)
	fmt.Println("age:", v.Age)

}
Output:

name: Alice
age: 12

func VariablesReffarances added in v0.5.0

func VariablesReffarances(expr hcl.Expression) []string

VariablesReffarances returns variables reffarance string list in expression

func WithFS added in v0.2.0

func WithFS(baseFS fs.FS) func(*utilFunctionOptions)

Withfsys は file関数やtemplatefile関数で参照するファイルシステムを追加します。

func WithFilePath added in v0.2.0

func WithFilePath(path string) func(*utilFunctionOptions)

WithFilePath は file関数やtemplatefile関数で参照するファイルのパスを追加します。

func WithUtilFunctions added in v0.3.0

func WithUtilFunctions(ctx *hcl.EvalContext, optFns ...func(*utilFunctionOptions)) *hcl.EvalContext

WithUtilFunctions は よく使う基本的な関数を登録したEvalContextを作成します。

func WithValue added in v0.3.0

func WithValue(ctx *hcl.EvalContext, path string, value cty.Value) *hcl.EvalContext

WithValue returns a new EvalContext with path's value set. ctx = WithValue(ctx, "a.b.c", cty.StringVal("hoge"))

func WithVariables added in v0.3.0

func WithVariables(ctx *hcl.EvalContext, variables map[string]cty.Value) *hcl.EvalContext

WithVariables returns a new EvalContext with parent's variables and variables merged.

Types

type BlockRestrictionSchema added in v0.4.0

type BlockRestrictionSchema struct {
	// Type is the block type
	Type string
	// Required is the block required
	Required bool
	// Unique is the block unique
	Unique bool
	// UniqueLabels is the block unique labels
	UniqueLabels bool
}

BlockRestrictionSchema is a schema for block restriction

type CTYValueMarshaler

type CTYValueMarshaler interface {
	MarshalCTYValue() (cty.Value, error)
}

CTYValueUnmarshaler is the interface implemented by types that can unmarshal

type CTYValueUnmarshaler

type CTYValueUnmarshaler interface {
	UnmarshalCTYValue(cty.Value) error
}

CTYValueUnmarshaler is an interface for types that can be decoded from a cty.Value.

type DiagnosticsWriter

type DiagnosticsWriter struct {
	// contains filtered or unexported fields
}

DiagnosticWriter は hcl.DiagnosticWriter のラッパーです。 通常のDiagnosticWriterに加えて以下の機能を追加します。

Output がターミナルであるのかどうかを検出し、色と幅を自動的に設定します。
Parse済みのファイル情報を保持します。

DiagnosticWriter is a wrapper for hcl.DiagnosticWriter. In addition to the normal DiagnosticWriter, it adds the following features.

Detects whether Output is a terminal and automatically sets color and width.
Holds parsed file information.

func Parse

func Parse(p string) (hcl.Body, *DiagnosticsWriter, hcl.Diagnostics)

Parse は与えられたPathをHCLとして解析します。 Parse parses the given Path as HCL.

func ParseFS added in v0.2.0

func ParseFS(fsys fs.FS) (hcl.Body, *DiagnosticsWriter, hcl.Diagnostics)

ParseFS は与えられたfs.ReadDirFSをHCLとして解析します。

func (*DiagnosticsWriter) Color

func (w *DiagnosticsWriter) Color() bool

Color をつけるかどうかを返します。 Returns whether to add Color.

func (*DiagnosticsWriter) Files

func (w *DiagnosticsWriter) Files() []string

Files は Parse済みのファイルのPath名を返します。 Files returns the Path name of the parsed file.

func (*DiagnosticsWriter) Output

func (w *DiagnosticsWriter) Output() io.Writer

Output は出力先を返します。 Output returns the output destination.

func (*DiagnosticsWriter) SetColor

func (w *DiagnosticsWriter) SetColor(color bool)

SetColor は色を設定します。 SetColor sets the color.

func (*DiagnosticsWriter) SetOutput

func (w *DiagnosticsWriter) SetOutput(output io.Writer)

SetOutput は出力先を設定します。 SetOutput sets the output destination.

func (*DiagnosticsWriter) SetWidth

func (w *DiagnosticsWriter) SetWidth(width uint)

SetWidth は幅を設定します。 SetWidth sets the width.

func (*DiagnosticsWriter) Width

func (w *DiagnosticsWriter) Width() uint

Width は幅を返します。 Width returns the width.

func (*DiagnosticsWriter) WriteDiagnostics

func (w *DiagnosticsWriter) WriteDiagnostics(diags hcl.Diagnostics) error

WriteDiagnostics は診断情報を出力します。 WriteDiagnostics outputs diagnostic information.

type InvalidUnmarshalError

type InvalidUnmarshalError struct {
	Type reflect.Type
}

InvalidUnmarshalError describes an invalid argument passed to UnmarshalCTYValue.

func (*InvalidUnmarshalError) Error

func (e *InvalidUnmarshalError) Error() string

Error implements the error interface.

type InvalidVersionError

type InvalidVersionError struct {
	Version string
	// contains filtered or unexported fields
}

InvalidVersionError is an error type for invalid version.

func (*InvalidVersionError) Error

func (err *InvalidVersionError) Error() string

func (*InvalidVersionError) Unwrap

func (err *InvalidVersionError) Unwrap() error

type UnknownValueError

type UnknownValueError struct {
	Value cty.Value
}

func (*UnknownValueError) Error

func (e *UnknownValueError) Error() string

type UnmarshalTypeError

type UnmarshalTypeError struct {
	CTYType cty.Type
	Type    reflect.Type
	Path    string
	Detail  error
}

UnmarshalTypeError describes a type missmatch between the cty.Type and the target type.

func (*UnmarshalTypeError) Error

func (e *UnmarshalTypeError) Error() string

Error implements the error interface.

func (*UnmarshalTypeError) Unwrap added in v0.3.0

func (e *UnmarshalTypeError) Unwrap() error

type VersionConstraintNotSatisfiedError

type VersionConstraintNotSatisfiedError struct {
	Constraint *VersionConstraints
	Version    string
}

VersionConstraintNotSatisfiedError is an error type for version constraint not satisfied.

func (*VersionConstraintNotSatisfiedError) Error

type VersionConstraints

type VersionConstraints struct {
	goVersion.Constraints
}

VersionConstraints is a wrapper of goVersion.Constraints to implement CTYValueMarshaler and CTYValueUnmarshaler interface.

Example
var vc hclutil.VersionConstraints
expr, diags := hclsyntax.ParseExpression([]byte(`">= 1.0.0, < 2.0.0"`), "", hcl.Pos{Line: 1, Column: 1})
if diags.HasErrors() {
	log.Fatal("parse failed")
}
diags = vc.DecodeExpression(expr, hclutil.NewEvalContext())
if diags.HasErrors() {
	log.Fatal("parse failed")
}
fmt.Println(vc)
fmt.Println("v1.2.0 is satisfied:", vc.IsSutisfied("v1.2.0"))
Output:

{>= 1.0.0, < 2.0.0}
v1.2.0 is satisfied: true

func (*VersionConstraints) DecodeExpression added in v0.2.0

func (vc *VersionConstraints) DecodeExpression(expr hcl.Expression, ctx *hcl.EvalContext) hcl.Diagnostics

func (*VersionConstraints) IsSutisfied added in v0.2.0

func (vc *VersionConstraints) IsSutisfied(str string) bool

func (*VersionConstraints) MarshalCTYValue

func (vc *VersionConstraints) MarshalCTYValue() (cty.Value, error)

func (*VersionConstraints) String added in v0.2.0

func (vc *VersionConstraints) String() string

func (*VersionConstraints) UnmarshalCTYValue

func (vc *VersionConstraints) UnmarshalCTYValue(value cty.Value) error

func (*VersionConstraints) ValidateVersion

func (vc *VersionConstraints) ValidateVersion(str string) error

Jump to

Keyboard shortcuts

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