confighcl

package
v0.6.0 Latest Latest
Warning

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

Go to latest
Published: Jul 15, 2026 License: MIT Imports: 12 Imported by: 0

README

Config for HCL

This is based on gohcl. The primary difference is that this will instead handle partials by default to allow for more dynamic based configurations without all the top level schema defintions being required.

Additionally, this supports both hcl and config tags with the same values.

Template descriptions

AppendTemplate generates attributes and blocks from initialized Go values. Add a separate description tag to place comments above generated attributes and blocks:

type route struct {
	Name   string `config:"name,label"`
	Target string `config:"target" description:"Route destination"`
}

Non-pointer values, including zero values, are emitted as active defaults. A nil block pointer or empty repeated block collection produces one commented example block. Root map bindings are emitted in key order without comments.

Documentation

Overview

Package confighcl allows decoding HCL configurations into config data structures.

It provides a convenient and concise way of describing the schema for configuration and then accessing the resulting data via native Go types.

A struct field tag scheme is used, similar to other decoding and unmarshalling libraries. The tags are formatted as in the following example:

ThingType string `config:"thing_type,attr"`

Additionally, this package is compatible with github.com/hashicorp/hcl/v2/gohcl.

ThingType string `hcl:"thing_type,attr"`

Within each tag there are two comma-separated tokens. The first is the name of the corresponding construct in configuration, while the second is a keyword giving the kind of construct expected. The following kind keywords are supported:

attr (the default) indicates that the value is to be populated from an attribute
block indicates that the value is populated from a block
label indicates that the value is populated from a block label
optional is the same as attr, but the field is optional
remain indicates that the value is to be populated from the remaining body after populating other fields

"attr" fields may either be of type *hcl.Expression, in which case the raw expression is assigned, or of any type accepted by gocty, in which case gocty will be used to assign the value to a native Go type.

"block" fields may be of type *hcl.Block or hcl.Body, in which case the corresponding raw value is assigned, or may be a struct that recursively uses the same tags. Block fields may also be slices of any of these types, in which case multiple blocks of the corresponding type are decoded into the slice.

"label" fields are considered only in a struct used as the type of a field marked as "block", and are used sequentially to capture the labels of the blocks being decoded. In this case, the name token is used only as an identifier for the label in diagnostic messages.

"optional" fields behave like "attr" fields, but they are optional and will not give parsing errors if they are missing.

"remain" can be placed on a single field that may be either of type hcl.Body or hcl.Attributes, in which case any remaining body content is placed into this field for delayed processing. If no "remain" field is present then any attributes or blocks not matched by another valid tag will cause an error diagnostic.

Only a subset of this tagging/typing vocabulary is supported for the "Encode" family of functions. See the EncodeIntoBody docs for full details on the constraints there.

Broadly-speaking this package deals with two types of error. The first is errors in the configuration itself, which are returned as diagnostics written with the configuration author as the target audience. The second is bugs in the calling program, such as invalid struct tags, which are surfaced via panics since there can be no useful runtime handling of such errors and they should certainly not be returned to the user as diagnostics.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AppendTemplate added in v0.5.0

func AppendTemplate(val any, dst *hclwrite.Body) (err error)

AppendTemplate appends a comment-aware HCL template for val to dst. Val must be a non-nil pointer to a struct or map accepted by DecodeBody. Existing destination attributes or blocks with the same root name are rejected.

func DecodeBody

func DecodeBody(body hcl.Body, ctx *hcl.EvalContext, val any) hcl.Diagnostics

DecodeBody extracts the configuration within the given body into the given value. This value must be a non-nil pointer to either a struct or a map, where in the former case the configuration will be decoded using struct tags and in the latter case only attributes are allowed and their values are decoded into the map.

The given EvalContext is used to resolve any variables or functions in expressions encountered while decoding. This may be nil to require only constant values, for simple applications that do not support variables or functions.

The returned diagnostics should be inspected with its HasErrors method to determine if the populated value is valid and complete. If error diagnostics are returned then the given value may have been partially-populated but may still be accessed by a careful caller for static analysis and editor integration use-cases.

A nil target pointer produces an error diagnostic. Other target-shape or schema errors, such as a pointer to a non-struct or non-map value or invalid field tags, indicate caller bugs and cause a panic.

func DecodeExpression

func DecodeExpression(expr hcl.Expression, ctx *hcl.EvalContext, val any) hcl.Diagnostics

DecodeExpression extracts the value of the given expression into the given value. This value must be something that gocty is able to decode into, since the final decoding is delegated to that package.

The given EvalContext is used to resolve any variables or functions in expressions encountered while decoding. This may be nil to require only constant values, for simple applications that do not support variables or functions.

The returned diagnostics should be inspected with its HasErrors method to determine if the populated value is valid and complete. If error diagnostics are returned then the given value may have been partially-populated but may still be accessed by a careful caller for static analysis and editor integration use-cases.

Evaluation and conversion failures are returned as diagnostics. A target that gocty cannot describe is a caller error and causes a panic.

func DecodeLeftoverBody

func DecodeLeftoverBody(body hcl.Body, ctx *hcl.EvalContext, val any) (hcl.Body, hcl.Diagnostics)

DecodeLeftoverBody decodes the portion of body described by val and returns the unconsumed body. Struct targets use their implied schema for partial matching; map targets consume the remaining attributes and return an empty body.

Configuration problems are returned as diagnostics and may leave val partially populated. A nil target pointer produces a diagnostic, while other invalid target shapes or field schemas cause a panic.

func EncodeAsBlock

func EncodeAsBlock(val any, blockType string) *hclwrite.Block

EncodeAsBlock creates a new blockType block populated from val, which must be a struct or non-nil pointer to a struct using this package's field tags.

If the given struct type has fields tagged with "label" tags then they will be used in order to annotate the created block with labels.

EncodeAsBlock has the same field support and panic contract as EncodeIntoBody.

func EncodeIntoBody

func EncodeIntoBody(val any, dst *hclwrite.Body)

EncodeIntoBody replaces dst with attributes and blocks derived from val, which must be a struct or non-nil pointer to a struct using this package's field tags. Existing destination content is discarded.

This function can work only with fully-decoded data. It will ignore any fields tagged as "remain", any fields that decode attributes into either hcl.Attribute or hcl.Expression values, and any fields that decode blocks into hcl.Attributes values. This function does not have enough information to complete the decoding of these types.

Any fields tagged as "label" are ignored by this function. Use EncodeAsBlock to produce a whole hclwrite.Block including block labels.

EncodeIntoBody panics for caller or schema errors, including an inappropriate value, a nil destination, or a field that cannot be represented as a cty value.

The layout of the resulting HCL source is derived from the ordering of the struct fields, with blank lines around nested blocks of different types. Fields representing attributes should usually precede those representing blocks so that the attributes can group together in the result. For more control, use the hclwrite API directly.

func ImpliedBodySchema

func ImpliedBodySchema(val any) (schema *hcl.BodySchema, partial bool)

ImpliedBodySchema produces an hcl.BodySchema derived from the type of val, which must be a struct value or a non-nil pointer to one.

The second return argument indicates whether the given struct includes a "remain" field, and thus the returned schema is non-exhaustive.

Field tags determine the attributes, blocks, and block labels in the schema. Invalid values, malformed tags, duplicate remain fields, and block fields that do not resolve to structs are caller errors and cause a panic.

Types

This section is empty.

Directories

Path Synopsis
Package funcs provides the expression functions exposed by application HCL evaluation contexts.
Package funcs provides the expression functions exposed by application HCL evaluation contexts.

Jump to

Keyboard shortcuts

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