Documentation
¶
Overview ¶
Package hclparse provides two-phase HCL parsing for stack files with support for autoinclude blocks and deferred evaluation.
Index ¶
- Constants
- func AutoIncludeDependencyPaths(fs vfs.FS, unitDir string) ([]string, error)
- func AutoIncludeKey(kind, name string) string
- func BuildAutoIncludeEvalContext(unitRefs, stackRefs []ComponentRef) *hcl.EvalContext
- func BuildComponentRefMap(refs []ComponentRef) cty.Value
- func CommentTokens(text string) hclwrite.Tokens
- func FindBlock(body *hclsyntax.Body, blockType, label string) *hclsyntax.Block
- func GenerateAutoIncludeFile(fs vfs.FS, resolved *AutoIncludeResolved, targetDir string, srcBytes []byte, ...) error
- func HCLStringContent(s string) []byte
- func IsPure(expr hclsyntax.Expression, deferred map[string]bool) bool
- func PartialEval(expr hclsyntax.Expression, args *EvalArgs) []byte
- func RangeBytes(src []byte, r hcl.Range) []byte
- func RawTokens(b []byte) hclwrite.Tokens
- func SortedAttributes(attrs hclsyntax.Attributes) []*hclsyntax.Attribute
- func UnitPathsFromStackDir(fs vfs.FS, stackDir string) []string
- func ValueToHCLBytes(val cty.Value) []byte
- type AutoIncludeDependency
- type AutoIncludeHCL
- type AutoIncludeResolved
- type ComponentRef
- type Copier
- type DirCreateError
- type DuplicateStackNameError
- type DuplicateUnitNameError
- type EvalArgs
- type FileDecodeError
- type FileParseError
- type FileReadError
- type FileWriteError
- type IncludeValidationError
- type LocalEvalError
- type LocalsCycleError
- type LocalsHCL
- type LocalsMaxIterError
- type ParseResult
- type ParseStackFileInput
- type StackBlockHCL
- type StackFileHCL
- type StackIncludeHCL
- type UnexpectedBodyTypeError
- type UnitBlockHCL
Constants ¶
const (
// AutoIncludeFile is the filename for generated autoinclude files.
AutoIncludeFile = "terragrunt.autoinclude.hcl"
)
const (
// StackDir is the directory name where generated stack components are placed.
StackDir = ".terragrunt-stack"
)
Variables ¶
This section is empty.
Functions ¶
func AutoIncludeDependencyPaths ¶
AutoIncludeDependencyPaths reads the terragrunt.autoinclude.hcl file in unitDir and returns resolved dependency config_path values. Returns (nil, nil) if the file does not exist or has no dependencies.
func AutoIncludeKey ¶
AutoIncludeKey returns the map key for an autoinclude entry, namespaced by component kind to prevent collisions between same-name units and stacks.
func BuildAutoIncludeEvalContext ¶
func BuildAutoIncludeEvalContext(unitRefs, stackRefs []ComponentRef) *hcl.EvalContext
BuildAutoIncludeEvalContext creates an HCL evaluation context with unit and stack path references for resolving autoinclude blocks.
The context provides:
- unit.<name>.path - resolved path of each unit in the stack
- unit.<name>.name - name label of each unit
- stack.<name>.path - resolved path of each stack in the stack
- stack.<name>.name - name label of each stack
Additional variables (locals, values) can be merged into the returned context by the caller.
func BuildComponentRefMap ¶
func BuildComponentRefMap(refs []ComponentRef) cty.Value
BuildComponentRefMap creates a cty.Value map from a slice of ComponentRef. The resulting value is an object like:
{
"unit_name": { "path": "../relative/path", "name": "unit_name" }
}
For stack refs with children, it also includes nested unit refs:
{
"stack_name": {
"path": "/abs/path",
"name": "stack_name",
"unit_name": { "path": "/abs/path/to/unit", "name": "unit_name" }
}
}
This is injected into the HCL eval context as the `unit` or `stack` variable.
func CommentTokens ¶
CommentTokens creates a comment token for hclwrite.
func FindBlock ¶
FindBlock finds a block by type and first label in the AST body. Exported for reuse by callers that need to locate specific blocks in parsed HCL bodies.
func GenerateAutoIncludeFile ¶
func GenerateAutoIncludeFile(fs vfs.FS, resolved *AutoIncludeResolved, targetDir string, srcBytes []byte, evalCtx *hcl.EvalContext) error
GenerateAutoIncludeFile writes a terragrunt.autoinclude.hcl file in the given directory from a resolved autoinclude.
The generated file contains:
- dependency blocks with resolved config_path and all other attributes (mock_outputs, mock_outputs_allowed_terraform_commands, etc.) copied from the original AST source bytes.
- All non-dependency content (inputs, retry blocks, etc.) copied verbatim from the original AST source bytes: dependency.*.outputs.* references are preserved without evaluation.
srcBytes is the original terragrunt.stack.hcl file content, used to extract source text for expressions via byte ranges.
func HCLStringContent ¶
HCLStringContent returns the inner content of an HCL-escaped string (without surrounding quotes). Uses hclwrite.TokensForValue for correct escaping of all HCL special characters.
func IsPure ¶
func IsPure(expr hclsyntax.Expression, deferred map[string]bool) bool
IsPure returns true if the expression has no references to deferred root names.
func PartialEval ¶
func PartialEval(expr hclsyntax.Expression, args *EvalArgs) []byte
PartialEval walks an hclsyntax.Expression tree and returns HCL source text. Pure expressions (no deferred refs) are fully evaluated to literals. Mixed expressions get per-child treatment: evaluable parts become literals, deferred parts keep their original source text.
func RangeBytes ¶
RangeBytes extracts the source bytes for the given range.
func RawTokens ¶
RawTokens wraps raw bytes as a single hclwrite token. hclwrite.Format will handle the final formatting of the output.
func SortedAttributes ¶
func SortedAttributes(attrs hclsyntax.Attributes) []*hclsyntax.Attribute
SortedAttributes returns attributes in a deterministic order by source position.
func UnitPathsFromStackDir ¶
UnitPathsFromStackDir parses the stack file in stackDir and returns absolute paths to each unit's generated directory under .terragrunt-stack/. Returns nil if the file does not exist or cannot be parsed.
func ValueToHCLBytes ¶
ValueToHCLBytes converts a cty.Value to HCL source text bytes.
Types ¶
type AutoIncludeDependency ¶
type AutoIncludeDependency struct {
// Block is the original HCL block, preserved for serialization.
Block *hcl.Block
Name string
ConfigPath string
}
AutoIncludeDependency represents a resolved dependency block from autoinclude. config_path has been evaluated (e.g. unit.vpc.path → "/abs/path/to/.terragrunt-stack/vpc"). The original HCL block is preserved for writing all attributes (mock_outputs, etc.) into the generated file.
type AutoIncludeHCL ¶
AutoIncludeHCL represents the first-phase parse of an autoinclude block. The entire body is captured as remain because it may contain references to unit.*.path / stack.*.path variables that are only available after the first parsing pass extracts all unit/stack names and paths.
Example HCL:
autoinclude {
dependency "vpc" {
config_path = unit.vpc.path
}
inputs = {
vpc_id = dependency.vpc.outputs.vpc_id
}
}
func (*AutoIncludeHCL) Resolve ¶
func (a *AutoIncludeHCL) Resolve(evalCtx *hcl.EvalContext) (*AutoIncludeResolved, hcl.Diagnostics)
Resolve evaluates the autoinclude body using the provided eval context, which must contain unit.* and stack.* variables for path resolution.
The resolution follows three levels:
- First parse: autoinclude body captured as Remain (unit.*.path not yet available)
- This method (second parse): dependency.config_path evaluated using unit/stack context. All other dependency attributes (mock_outputs, etc.) are preserved as raw HCL.
- inputs and other non-dependency content: NOT evaluated here. They contain dependency.*.outputs.* which is runtime-only. The RawBody is preserved so the generator can copy these from the AST.
type AutoIncludeResolved ¶
type AutoIncludeResolved struct {
// EvalCtx is the HCL evaluation context used during resolution,
// preserved so the generator can evaluate non-deferred expressions.
EvalCtx *hcl.EvalContext
// RawBody is the original autoinclude HCL body, preserved so
// the generator can write non-dependency content (inputs, etc.)
// directly from the AST without evaluating dependency.* references.
RawBody hcl.Body
Dependencies []AutoIncludeDependency
}
AutoIncludeResolved represents the second-phase resolved autoinclude content.
After the first parse extracts unit/stack names and paths, the autoinclude body is partially evaluated:
- dependency.config_path is resolved (references unit.*.path)
- dependency remain (mock_outputs etc) is preserved for generation
- inputs and other blocks are partially evaluated (local.* resolved, dependency.* preserved)
The RawBody is preserved for serializing the generated terragrunt.autoinclude.hcl file.
type ComponentRef ¶
type ComponentRef struct {
Name string
Path string
// ChildRefs holds nested unit refs for stack components.
// When a stack block references a source with a terragrunt.stack.hcl,
// the child units within that stack are parsed and stored here.
// This enables stack.stack_name.unit_name.path references.
ChildRefs []ComponentRef
}
ComponentRef holds the path and name metadata for a unit or stack block, used to build the evaluation context for the second parsing phase.
func DiscoverStackChildUnits ¶
func DiscoverStackChildUnits(fs vfs.FS, stackSourceDir, stackGenDir string) []ComponentRef
DiscoverStackChildUnits parses a stack's source directory to find the terragrunt.stack.hcl within it and extracts unit paths. This enables stack.stack_name.unit_name.path references in autoinclude blocks.
stackSourceDir is the directory where the stack's source files live (or will be generated). stackGenDir is the absolute path where this stack's units will be generated (.terragrunt-stack/stack_path/).
func ExtractStackRefs ¶
func ExtractStackRefs(stacks []*StackBlockHCL) []ComponentRef
ExtractStackRefs extracts ComponentRef values from parsed StackBlockHCL slices.
func ExtractUnitRefs ¶
func ExtractUnitRefs(units []*UnitBlockHCL) []ComponentRef
ExtractUnitRefs extracts ComponentRef values from parsed UnitBlockHCL slices.
type Copier ¶
type Copier struct {
// contains filtered or unexported fields
}
Copier copies HCL blocks from AST source to hclwrite output. When an eval context is set, attributes are partially evaluated (local.* resolved, dependency.* preserved). Without it, attributes are copied verbatim from source bytes.
func (*Copier) WithEvalCtx ¶
func (c *Copier) WithEvalCtx(evalCtx *hcl.EvalContext) *Copier
WithEvalCtx returns the Copier with partial evaluation enabled.
type DirCreateError ¶
DirCreateError indicates a failure to create a directory.
func (DirCreateError) Error ¶
func (e DirCreateError) Error() string
func (DirCreateError) Unwrap ¶
func (e DirCreateError) Unwrap() error
type DuplicateStackNameError ¶
type DuplicateStackNameError struct {
Name string
}
DuplicateStackNameError indicates that multiple stacks with the same name were found after merging include blocks.
func (DuplicateStackNameError) Error ¶
func (e DuplicateStackNameError) Error() string
type DuplicateUnitNameError ¶
type DuplicateUnitNameError struct {
Name string
}
DuplicateUnitNameError indicates that multiple units with the same name were found after merging include blocks.
func (DuplicateUnitNameError) Error ¶
func (e DuplicateUnitNameError) Error() string
type EvalArgs ¶
type EvalArgs struct {
EvalCtx *hcl.EvalContext
Deferred map[string]bool
SrcBytes []byte
}
EvalArgs bundles the shared arguments for partial evaluation functions.
type FileDecodeError ¶
FileDecodeError indicates a failure to decode an HCL file into a struct.
func (FileDecodeError) Error ¶
func (e FileDecodeError) Error() string
type FileParseError ¶
FileParseError indicates a failure to parse an HCL file.
func (FileParseError) Error ¶
func (e FileParseError) Error() string
type FileReadError ¶
FileReadError indicates a failure to read a file from the filesystem.
func (FileReadError) Error ¶
func (e FileReadError) Error() string
func (FileReadError) Unwrap ¶
func (e FileReadError) Unwrap() error
type FileWriteError ¶
FileWriteError indicates a failure to write a file to the filesystem.
func (FileWriteError) Error ¶
func (e FileWriteError) Error() string
func (FileWriteError) Unwrap ¶
func (e FileWriteError) Unwrap() error
type IncludeValidationError ¶
IncludeValidationError indicates that an included stack file violates constraints (e.g. defines locals or nested includes).
func (IncludeValidationError) Error ¶
func (e IncludeValidationError) Error() string
type LocalEvalError ¶
LocalEvalError indicates a failure to evaluate a local variable.
func (LocalEvalError) Error ¶
func (e LocalEvalError) Error() string
type LocalsCycleError ¶
type LocalsCycleError struct {
Names []string
}
LocalsCycleError indicates that locals have circular dependencies.
func (LocalsCycleError) Error ¶
func (e LocalsCycleError) Error() string
type LocalsMaxIterError ¶
LocalsMaxIterError indicates that locals evaluation exceeded the maximum iterations.
func (LocalsMaxIterError) Error ¶
func (e LocalsMaxIterError) Error() string
type ParseResult ¶
type ParseResult struct {
// AutoIncludes maps component name → resolved autoinclude (only for units/stacks
// that had an autoinclude block). Dependencies have config_path resolved.
AutoIncludes map[string]*AutoIncludeResolved
// Units from the first-pass parse (name, source, path, values decoded).
Units []*UnitBlockHCL
// Stacks from the first-pass parse.
Stacks []*StackBlockHCL
}
ParseResult holds the output of a two-pass parse of a terragrunt.stack.hcl file.
func ParseStackFile ¶
func ParseStackFile(fs vfs.FS, input *ParseStackFileInput) (*ParseResult, error)
ParseStackFile performs a two-pass parse of a terragrunt.stack.hcl file.
Pass 1: Parse unit/stack blocks to extract names, sources, and paths. The autoinclude body is captured as hcl.Body via remain (not evaluated).
Between passes: Build eval context with unit.<name>.path and stack.<name>.path variables. Paths are resolved to absolute paths under .terragrunt-stack/.
Pass 2: For each unit/stack with an autoinclude block, resolve the autoinclude body using the eval context. dependency.config_path is evaluated (references unit.*.path), while inputs are left unevaluated (contain dependency.*.outputs.*).
func ParseStackFileFromPath ¶
func ParseStackFileFromPath(fs vfs.FS, stackDir string) (*ParseResult, error)
ParseStackFileFromPath reads stackDir/terragrunt.stack.hcl from disk and performs a two-pass parse. Returns nil, nil if the file does not exist.
type ParseStackFileInput ¶
ParseStackFileInput holds the input for ParseStackFile.
type StackBlockHCL ¶
type StackBlockHCL struct {
AutoInclude *AutoIncludeHCL `hcl:"autoinclude,block"`
NoStack *bool `hcl:"no_dot_terragrunt_stack,attr"`
NoValidation *bool `hcl:"no_validation,attr"`
Values *cty.Value `hcl:"values,attr"`
Name string `hcl:",label"`
Source string `hcl:"source,attr"`
Path string `hcl:"path,attr"`
}
StackBlockHCL represents the first-phase parse of a stack block. Same remain pattern as UnitBlockHCL.
type StackFileHCL ¶
type StackFileHCL struct {
Locals *LocalsHCL `hcl:"locals,block"`
Includes []*StackIncludeHCL `hcl:"include,block"`
Stacks []*StackBlockHCL `hcl:"stack,block"`
Units []*UnitBlockHCL `hcl:"unit,block"`
}
StackFileHCL represents the first-phase parse of a terragrunt.stack.hcl file. The autoinclude body inside each unit/stack block is captured as hcl.Body via remain, allowing deferred evaluation once unit/stack path variables are available.
type StackIncludeHCL ¶
StackIncludeHCL represents an include block in a terragrunt.stack.hcl file. The path is evaluated immediately during the first parse pass.
type UnexpectedBodyTypeError ¶
type UnexpectedBodyTypeError struct {
FilePath string
}
UnexpectedBodyTypeError indicates that an HCL file body was not the expected *hclsyntax.Body type. This typically occurs with JSON-format HCL files.
func (UnexpectedBodyTypeError) Error ¶
func (e UnexpectedBodyTypeError) Error() string
type UnitBlockHCL ¶
type UnitBlockHCL struct {
AutoInclude *AutoIncludeHCL `hcl:"autoinclude,block"`
NoStack *bool `hcl:"no_dot_terragrunt_stack,attr"`
NoValidation *bool `hcl:"no_validation,attr"`
Values *cty.Value `hcl:"values,attr"`
Name string `hcl:",label"`
Source string `hcl:"source,attr"`
Path string `hcl:"path,attr"`
}
UnitBlockHCL represents the first-phase parse of a unit block. Known attributes are decoded directly. The autoinclude block body is captured in Remain for second-phase evaluation.