hclparse

package
v1.0.6 Latest Latest
Warning

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

Go to latest
Published: May 22, 2026 License: MIT Imports: 20 Imported by: 0

Documentation

Overview

Package hclparse parses terragrunt.stack.hcl in four phases: skeleton, locals, includes, unit/stack decode + autoinclude.

Index

Constants

View Source
const (
	// AutoIncludeFile is the filename for generated unit-level autoinclude files.
	AutoIncludeFile = "terragrunt.autoinclude.hcl"
	// AutoIncludeStackFile is the filename for generated stack-level autoinclude files.
	AutoIncludeStackFile = "terragrunt.autoinclude.stack.hcl"
)
View Source
const (
	// StackDir is the directory name where generated stack components are placed.
	StackDir = ".terragrunt-stack"
)

Variables

This section is empty.

Functions

func AutoIncludeDependencyPaths

func AutoIncludeDependencyPaths(fs vfs.FS, unitDir string) ([]string, error)

AutoIncludeDependencyPaths reads the autoinclude file in unitDir and returns resolved dependency config_path values. Returns EmptyArgError when unitDir is empty so callers can distinguish bad input from a missing file.

func AutoIncludeFileNameForKind added in v1.0.4

func AutoIncludeFileNameForKind(kind AutoIncludeKind) string

AutoIncludeFileNameForKind returns the autoinclude filename to generate for the given kind. Panics on unknown kinds (programmer error) so a misspelled or missing kind cannot silently produce the wrong filename.

func AutoIncludeKey

func AutoIncludeKey(kind AutoIncludeKind, name string) string

AutoIncludeKey returns the map key for an autoinclude entry, namespaced by component kind to prevent collisions between same-name units and stacks.

func BuildComponentRefMap

func BuildComponentRefMap(refs []ComponentRef) cty.Value

BuildComponentRefMap converts component refs into an HCL object injected as the `unit` or `stack` variable in the eval context. Empty input returns EmptyObjectVal so typos surface as "Unsupported attribute" diagnostics.

Output shape for units:

{
  "unit_name": { "name": "unit_name", "path": "../relative/path" }
}

Output shape for stacks with discovered children:

{
  "stack_name": {
    "name": "stack_name",
    "path": "/abs/path",
    "unit_name": { "name": "unit_name", "path": "/abs/path/to/unit" }
  }
}

func CommentTokens

func CommentTokens(text string) hclwrite.Tokens

CommentTokens creates a comment token for hclwrite.

func FindBlock

func FindBlock(body *hclsyntax.Body, blockType, label string) *hclsyntax.Block

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.

Requires non-nil fs and non-empty targetDir (panics otherwise). resolved may be nil (no-op). srcBytes must be the bytes of the file resolved.RawBody was parsed from; for includes pass resolved.SourceBytes. evalCtx may be nil.

func HCLStringContent

func HCLStringContent(s string) []byte

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, error)

PartialEval walks an hclsyntax.Expression tree and returns HCL source text; pure parts evaluate to literals, deferred parts stay verbatim, error signals pathological inputs.

func RangeBytes

func RangeBytes(src []byte, r hcl.Range) []byte

RangeBytes extracts the source bytes for the given range.

func RawTokens

func RawTokens(b []byte) hclwrite.Tokens

RawTokens wraps raw bytes as a single hclwrite token; hclwrite.Format handles 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

func UnitPathsFromStackDir(fs vfs.FS, stackDir string) ([]string, error)

UnitPathsFromStackDir returns generated unit paths from discovery parsing.

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

type AutoIncludeHCL struct {
	Remain hcl.Body `hcl:",remain"`
}

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

Resolve evaluates the autoinclude body using the provided eval context, which must contain unit.* and stack.* variables for path resolution.

Callers that need to record the originating file's bytes on the returned AutoIncludeResolved (so generation can slice expressions from the correct source after include merging) should set SourceBytes on the result.

The resolution follows three levels:

  1. First parse: autoinclude body captured as Remain (unit.*.path not yet available)
  2. This method (second parse): dependency.config_path evaluated using unit/stack context. All other dependency attributes (mock_outputs, etc.) are preserved as raw HCL.
  3. 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 AutoIncludeKind added in v1.0.4

type AutoIncludeKind string

AutoIncludeKind identifies whether a generated autoinclude file is unit-level or stack-level. The values intentionally match internal/component.{UnitKind,StackKind} but are defined here because internal/component -> pkg/config -> internal/hclparse is the established import direction; reusing the component constants would create a cycle.

const (
	// KindUnit selects the unit-level filename (terragrunt.autoinclude.hcl). Value matches component.UnitKind.
	KindUnit AutoIncludeKind = "unit"
	// KindStack selects the stack-level filename (terragrunt.autoinclude.stack.hcl). Value matches component.StackKind.
	KindStack AutoIncludeKind = "stack"
)

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
	// SourceBytes are the bytes of the file RawBody was parsed from. Generation slices expressions by HCL byte ranges and must use these bytes, not the root stack file's bytes, when the autoinclude originated in an included file.
	SourceBytes []byte
	// Kind is KindUnit or KindStack and drives the generated filename (terragrunt.autoinclude.hcl vs terragrunt.autoinclude.stack.hcl).
	Kind         AutoIncludeKind
	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 []ComponentRef
}

ComponentRef holds name, path, and child refs.

func DiscoverStackChildUnits

func DiscoverStackChildUnits(fs vfs.FS, stackSourceDir, stackGenDir string) []ComponentRef

DiscoverStackChildUnits enriches a stack ComponentRef with nested unit refs for stack.<name>.<unit>.path resolution; best-effort, returns nil ChildRefs on any read/parse failure.

type DirCreateError

type DirCreateError struct {
	Err     error
	DirPath string
}

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 EmptyArgError added in v1.0.4

type EmptyArgError struct {
	Func string
	Arg  string
}

EmptyArgError indicates that a required string argument was empty.

func (EmptyArgError) Error added in v1.0.4

func (e EmptyArgError) Error() string

type EvalArgs

type EvalArgs struct {
	EvalCtx  *hcl.EvalContext
	Deferred map[string]bool
	SrcBytes []byte
	// contains filtered or unexported fields
}

EvalArgs bundles the shared arguments for partial evaluation functions.

type FileDecodeError

type FileDecodeError struct {
	Err  error
	Name string
}

FileDecodeError indicates a failure to decode an HCL file into a struct; Err preserves the underlying diagnostics.

func (FileDecodeError) Error

func (e FileDecodeError) Error() string

func (FileDecodeError) Unwrap added in v1.0.6

func (e FileDecodeError) Unwrap() error

type FileParseError

type FileParseError struct {
	Err      error
	FilePath string
}

FileParseError indicates a failure to parse an HCL file; Err preserves the underlying diagnostics.

func (FileParseError) Error

func (e FileParseError) Error() string

func (FileParseError) Unwrap added in v1.0.6

func (e FileParseError) Unwrap() error

type FileReadError

type FileReadError struct {
	Err      error
	FilePath string
}

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

type FileWriteError struct {
	Err      error
	FilePath string
}

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

type IncludeValidationError struct {
	Err         error
	IncludeName string
	Reason      string
}

IncludeValidationError indicates that an included stack file violates constraints (e.g. defines locals or nested includes). Err preserves the underlying error (such as hcl.Diagnostics from include-path evaluation) so callers can extract it via errors.As.

func (IncludeValidationError) Error

func (e IncludeValidationError) Error() string

func (IncludeValidationError) Unwrap added in v1.0.6

func (e IncludeValidationError) Unwrap() error

type LocalEvalError

type LocalEvalError struct {
	Err  error
	Name string
}

LocalEvalError indicates a failure to evaluate a local variable; Err preserves the underlying diagnostics.

func (LocalEvalError) Error

func (e LocalEvalError) Error() string

func (LocalEvalError) Unwrap added in v1.0.6

func (e LocalEvalError) Unwrap() error

type LocalsCycleError

type LocalsCycleError struct {
	Names []string
}

LocalsCycleError indicates that locals have circular dependencies.

func (LocalsCycleError) Error

func (e LocalsCycleError) Error() string

type LocalsHCL

type LocalsHCL struct {
	Remain hcl.Body `hcl:",remain"`
}

LocalsHCL is the locals block shell.

type MalformedDependencyError added in v1.0.4

type MalformedDependencyError struct {
	Err      error
	FilePath string
	Name     string
	Reason   string
}

MalformedDependencyError indicates a dependency block in an autoinclude file is malformed. Err optionally carries the original HCL diagnostics so callers can extract position info via errors.As/Is.

func (MalformedDependencyError) Error added in v1.0.4

func (e MalformedDependencyError) Error() string

func (MalformedDependencyError) Unwrap added in v1.0.4

func (e MalformedDependencyError) Unwrap() error

type ParseResult

type ParseResult struct {
	// AutoIncludes stores resolved autoincludes by component key.
	AutoIncludes map[string]*AutoIncludeResolved
	Units        []*UnitBlockHCL
	Stacks       []*StackBlockHCL
}

ParseResult holds the output of ParseStackFile.

func ParseStackFile

func ParseStackFile(fs vfs.FS, input *ParseStackFileInput) (*ParseResult, error)

ParseStackFile runs the phase flow and returns partial results when decode partially succeeds.

func ParseStackFileFromPath

func ParseStackFileFromPath(fs vfs.FS, stackDir string) (*ParseResult, error)

ParseStackFileFromPath reads a terragrunt.stack.hcl from disk and runs ParseStackFile; returns (nil, nil) when the file is absent.

type ParseStackFileInput

type ParseStackFileInput struct {
	// Values is passed as the `values` variable in the parse context.
	Values *cty.Value
	// Variables come from production parsing and are merged for parse.
	Variables map[string]cty.Value
	// Functions are copied from the production parser eval context.
	Functions map[string]function.Function
	// Filename is the basename (not full path) used for parse diagnostics.
	Filename string
	// StackDir is used to resolve include paths.
	StackDir string
	// Src is the raw stack file bytes.
	Src []byte
}

ParseStackFileInput holds the input for ParseStackFile.

type PartialEvalDepthExceededError added in v1.0.6

type PartialEvalDepthExceededError struct {
	MaxDepth int
}

PartialEvalDepthExceededError indicates that PartialEval hit its recursion guard.

func (PartialEvalDepthExceededError) Error added in v1.0.6

type PartialEvalUnresolvedError added in v1.0.6

type PartialEvalUnresolvedError struct {
	Err    error
	Reason string
}

PartialEvalUnresolvedError indicates that partial evaluation could not produce a final cty value.

func (PartialEvalUnresolvedError) Error added in v1.0.6

func (PartialEvalUnresolvedError) Unwrap added in v1.0.6

func (e PartialEvalUnresolvedError) Unwrap() error

type StackBlockHCL

type StackBlockHCL struct {
	Remain       hcl.Body        `hcl:",remain"`
	AutoInclude  *AutoIncludeHCL `hcl:"autoinclude,block"`
	NoStack      *bool           `hcl:"no_dot_terragrunt_stack,optional"`
	NoValidation *bool           `hcl:"no_validation,optional"`
	Values       *cty.Value      `hcl:"values,optional"`
	Source       string          `hcl:"source,attr"`
	Path         string          `hcl:"path,attr"`
	Name         string          `hcl:",label"`
}

StackBlockHCL is the eager stack block shape with deferred autoinclude content.

type StackFileHCL

type StackFileHCL struct {
	Remain   hcl.Body           `hcl:",remain"`
	Locals   *LocalsHCL         `hcl:"locals,block"`
	Includes []*StackIncludeHCL `hcl:"include,block"`
}

StackFileHCL is the parsed skeleton: locals, includes, and Remain.

type StackIncludeHCL

type StackIncludeHCL struct {
	Path hcl.Expression `hcl:"path,attr"`
	Name string         `hcl:",label"`
}

StackIncludeHCL stores include path as a lazy expression.

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 {
	Remain       hcl.Body        `hcl:",remain"`
	AutoInclude  *AutoIncludeHCL `hcl:"autoinclude,block"`
	NoStack      *bool           `hcl:"no_dot_terragrunt_stack,optional"`
	NoValidation *bool           `hcl:"no_validation,optional"`
	Values       *cty.Value      `hcl:"values,optional"`
	Source       string          `hcl:"source,attr"`
	Path         string          `hcl:"path,attr"`
	Name         string          `hcl:",label"`
}

UnitBlockHCL is the eager unit block shape with deferred autoinclude content.

Jump to

Keyboard shortcuts

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