Documentation ¶
Overview ¶
Package hcldec provides a higher-level API for unpacking the content of HCL bodies, implemented in terms of the low-level "Content" API exposed by the bodies themselves.
It allows decoding an entire nested configuration in a single operation by providing a description of the intended structure.
For some applications it may be more convenient to use the "gohcl" package, which has a similar purpose but decodes directly into native Go data types. hcldec instead targets the cty type system, and thus allows a cty-driven application to remain within that type system.
Index ¶
- func ChildBlockTypes(spec Spec) map[string]Spec
- func Decode(body hcl.Body, spec Spec, ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics)
- func ImpliedSchema(spec Spec) *hcl.BodySchema
- func ImpliedType(spec Spec) cty.Type
- func PartialDecode(body hcl.Body, spec Spec, ctx *hcl.EvalContext) (cty.Value, hcl.Body, hcl.Diagnostics)
- func SourceRange(body hcl.Body, spec Spec) hcl.Range
- func Variables(body hcl.Body, spec Spec) []hcl.Traversal
- type AttrSpec
- type BlockAttrsSpec
- type BlockLabelSpec
- type BlockListSpec
- type BlockMapSpec
- type BlockObjectSpec
- type BlockSetSpec
- type BlockSpec
- type BlockTupleSpec
- type DefaultSpec
- type ExprSpec
- type LiteralSpec
- type MarkedBody
- type ObjectSpec
- type RefineValueSpec
- type Spec
- type TransformExprSpec
- type TransformFuncSpec
- type TupleSpec
- type UnknownBody
- type ValidateSpec
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ChildBlockTypes ¶
ChildBlockTypes returns a map of all of the child block types declared by the given spec, with block type names as keys and the associated nested body specs as values.
func Decode ¶
Decode interprets the given body using the given specification and returns the resulting value. If the given body is not valid per the spec, error diagnostics are returned and the returned value is likely to be incomplete.
The ctx argument may be nil, in which case any references to variables or functions will produce error diagnostics.
func ImpliedSchema ¶
func ImpliedSchema(spec Spec) *hcl.BodySchema
ImpliedSchema returns the *hcl.BodySchema implied by the given specification. This is the schema that the Decode function will use internally to access the content of a given body.
func ImpliedType ¶
ImpliedType returns the value type that should result from decoding the given spec.
func PartialDecode ¶
func PartialDecode(body hcl.Body, spec Spec, ctx *hcl.EvalContext) (cty.Value, hcl.Body, hcl.Diagnostics)
PartialDecode is like Decode except that it permits "leftover" items in the top-level body, which are returned as a new body to allow for further processing.
Any descendent block bodies are _not_ decoded partially and thus must be fully described by the given specification.
func SourceRange ¶
func SourceRange(body hcl.Body, spec Spec) hcl.Range
SourceRange interprets the given body using the given specification and then returns the source range of the value that would be used to fulfill the spec.
This can be used if application-level validation detects value errors, to obtain a reasonable SourceRange to use for generated diagnostics. It works best when applied to specific body items (e.g. using AttrSpec, BlockSpec, ...) as opposed to entire bodies using ObjectSpec, TupleSpec. The result will be less useful the broader the specification, so e.g. a spec that returns the entirety of all of the blocks of a given type is likely to be _particularly_ arbitrary and useless.
If the given body is not valid per the given spec, the result is best-effort and may not actually be something ideal. It's expected that an application will already have used Decode or PartialDecode earlier and thus had an opportunity to detect and report spec violations.
func Variables ¶
func Variables(body hcl.Body, spec Spec) []hcl.Traversal
Variables processes the given body with the given spec and returns a list of the variable traversals that would be required to decode the same pairing of body and spec.
This can be used to conditionally populate the variables in the EvalContext passed to Decode, for applications where a static scope is insufficient.
If the given body is not compliant with the given schema, the result may be incomplete, but that's assumed to be okay because the eventual call to Decode will produce error diagnostics anyway.
Types ¶
type AttrSpec ¶
An AttrSpec is a Spec that evaluates a particular attribute expression in the body and returns its resulting value converted to the requested type, or produces a diagnostic if the type is incorrect.
type BlockAttrsSpec ¶
A BlockAttrsSpec is a Spec that interprets a single block as if it were a map of some element type. That is, each attribute within the block becomes a key in the resulting map and the attribute's value becomes the element value, after conversion to the given element type. The resulting value is a cty.Map of the given element type.
This spec imposes a validation constraint that there be exactly one block of the given type name and that this block may contain only attributes. The block does not accept any labels.
This is an alternative to an AttrSpec of a map type for situations where block syntax is desired. Note that block syntax does not permit dynamic keys, construction of the result via a "for" expression, etc. In most cases an AttrSpec is preferred if the desired result is a map whose keys are chosen by the user rather than by schema.
type BlockLabelSpec ¶
A BlockLabelSpec is a Spec that returns a cty.String representing the label of the block its given body belongs to, if indeed its given body belongs to a block. It is a programming error to use this in a non-block context, so this spec will panic in that case.
This spec only works in the nested spec within a BlockSpec, BlockListSpec, BlockSetSpec or BlockMapSpec.
The full set of label specs used against a particular block must have a consecutive set of indices starting at zero. The maximum index found defines how many labels the corresponding blocks must have in cty source.
type BlockListSpec ¶
A BlockListSpec is a Spec that produces a cty list of the results of decoding all of the nested blocks of a given type, using a nested spec.
type BlockMapSpec ¶
A BlockMapSpec is a Spec that produces a cty map of the results of decoding all of the nested blocks of a given type, using a nested spec.
One level of map structure is created for each of the given label names. There must be at least one given label name.
type BlockObjectSpec ¶
A BlockObjectSpec is a Spec that produces a cty object of the results of decoding all of the nested blocks of a given type, using a nested spec.
One level of object structure is created for each of the given label names. There must be at least one given label name.
This is similar to BlockMapSpec, but it permits the nested blocks to have different result types in situations where cty.DynamicPseudoType attributes are present.
type BlockSetSpec ¶
A BlockSetSpec is a Spec that produces a cty set of the results of decoding all of the nested blocks of a given type, using a nested spec.
type BlockSpec ¶
A BlockSpec is a Spec that produces a cty.Value by decoding the contents of a single nested block of a given type, using a nested spec.
If the Required flag is not set, the nested block may be omitted, in which case a null value is produced. If it _is_ set, an error diagnostic is produced if there are no nested blocks of the given type.
type BlockTupleSpec ¶
A BlockTupleSpec is a Spec that produces a cty tuple of the results of decoding all of the nested blocks of a given type, using a nested spec.
This is similar to BlockListSpec, but it permits the nested blocks to have different result types in situations where cty.DynamicPseudoType attributes are present.
type DefaultSpec ¶
DefaultSpec is a spec that wraps two specs, evaluating the primary first and then evaluating the default if the primary returns a null value.
The two specifications must have the same implied result type for correct operation. If not, the result is undefined.
Any requirements imposed by the "Default" spec apply even if "Primary" does not return null. For example, if the "Default" spec is for a required attribute then that attribute is always required, regardless of the result of the "Primary" spec.
The "Default" spec must not describe a nested block, since otherwise the result of ChildBlockTypes would not be decidable without evaluation. If the default spec _does_ describe a nested block then the result is undefined.
type ExprSpec ¶
type ExprSpec struct {
Expr hcl.Expression
}
An ExprSpec is a Spec that evaluates the given expression, ignoring the given body.
type LiteralSpec ¶
A LiteralSpec is a Spec that produces the given literal value, ignoring the given body.
type MarkedBody ¶
type MarkedBody interface {
BodyValueMarks() cty.ValueMarks
}
MarkedBody can be optionally implemented by an hcl.Body instance to indicate that a value created from it ought to be marked.
type ObjectSpec ¶
An ObjectSpec is a Spec that produces a cty.Value of an object type whose attributes correspond to the keys of the spec map.
type RefineValueSpec ¶
type RefineValueSpec struct { Wrapped Spec // Refine is a function which accepts a builder for a refinement in // progress and uses the builder pattern to add extra refinements to it, // finally returning the same builder with those modifications applied. Refine func(*cty.RefinementBuilder) *cty.RefinementBuilder }
RefineValueSpec is a spec that wraps another and applies a fixed set of cty value refinements to whatever value it produces.
Refinements serve to constrain the range of any unknown values, and act as assertions for known values by panicking if the final value does not meet the refinement. Therefore applications using this spec must guarantee that any value passing through the RefineValueSpec will always be consistent with the refinements; if not then that is a bug in the application.
The wrapped spec should typically be a ValidateSpec, a TransformFuncSpec, or some other adapter that guarantees that the inner result cannot possibly violate the refinements.
type Spec ¶
type Spec interface {
// contains filtered or unexported methods
}
A Spec is a description of how to decode a hcl.Body to a cty.Value.
The various other types in this package whose names end in "Spec" are the spec implementations. The most common top-level spec is ObjectSpec, which decodes body content into a cty.Value of an object type.
type TransformExprSpec ¶
type TransformExprSpec struct { Wrapped Spec Expr hcl.Expression TransformCtx *hcl.EvalContext VarName string }
TransformExprSpec is a spec that wraps another and then evaluates a given hcl.Expression on the result.
The implied type of this spec is determined by evaluating the expression with an unknown value of the nested spec's implied type, which may cause the result to be imprecise. This spec should not be used in situations where precise result type information is needed.
type TransformFuncSpec ¶
TransformFuncSpec is a spec that wraps another and then evaluates a given cty function with the result. The given function must expect exactly one argument, where the result of the wrapped spec will be passed.
The implied type of this spec is determined by type-checking the function with an unknown value of the nested spec's implied type, which may cause the result to be imprecise. This spec should not be used in situations where precise result type information is needed.
If the given function produces an error when run, this spec will produce a non-user-actionable diagnostic message. It's the caller's responsibility to ensure that the given function cannot fail for any non-error result of the wrapped spec.
type TupleSpec ¶
type TupleSpec []Spec
A TupleSpec is a Spec that produces a cty.Value of a tuple type whose elements correspond to the elements of the spec slice.
type UnknownBody ¶
type UnknownBody interface {
Unknown() bool
}
UnknownBody can be optionally implemented by an hcl.Body instance which may be entirely unknown.
type ValidateSpec ¶
ValidateSpec is a spec that allows for extended developer-defined validation. The validation function receives the result of the wrapped spec.
The Subject field of the returned Diagnostic is optional. If not specified, it is automatically populated with the range covered by the wrapped spec.