Documentation
¶
Index ¶
- Constants
- Variables
- func Functions() map[string]function.Function
- func MarkSensitive(vars map[string]cty.Value, names map[string]bool) map[string]cty.Value
- func ResolveVariableType(v *VariableBlock) (cty.Type, error)
- func ValidateComponentInputs(comp *ParsedComponent) error
- func VariableDefault(v *VariableBlock) (hcl.Expression, error)
- func VariableSensitive(v *VariableBlock) (bool, error)
- type ActionBlock
- type ComponentDefBlock
- type ComponentFile
- type ComponentRef
- type Instance
- type Option
- type OutputBlock
- type ParsedComponent
- type ParsedScenario
- type ProviderConfigBlock
- type RequiredProviderSpec
- type RequiredProvidersBlock
- type ScenarioBlock
- type ScenarioFile
- type VariableBlock
Constants ¶
const SensitiveMark = "sensitive"
SensitiveMark is the cty mark on values that come from a sensitive variable. HCL carries it through expressions and function calls, so anything computed from such a value is marked too. The engine marks values only where it looks for the mark (plan output, component inputs) and unmarks them before they reach a provider.
Variables ¶
var RepetitionSchema = &hcl.BodySchema{ Attributes: []hcl.AttributeSchema{{Name: "count"}, {Name: "for_each"}}, }
RepetitionSchema names the attributes ExpandInstances consumes.
Functions ¶
func Functions ¶
Functions returns the complete set of HCL functions Orchard exposes to expressions. Delegates to language.Map() which builds the function map from the unified registry — the single source of truth for function implementations and metadata.
All callers (parser, engine, plan-time validators, teardown) use this function to populate EvalContext.Functions.
func MarkSensitive ¶ added in v0.2.0
MarkSensitive returns vars with the variables names marks sensitive carrying SensitiveMark. vars itself is left alone.
func ResolveVariableType ¶
func ResolveVariableType(v *VariableBlock) (cty.Type, error)
ResolveVariableType parses the variable's `type` HCL expression (e.g. `string`, `list(number)`, `object({id=number})`) into a cty.Type. A variable with no declared type is treated as cty.DynamicPseudoType — any value shape is accepted.
func ValidateComponentInputs ¶
func ValidateComponentInputs(comp *ParsedComponent) error
ValidateComponentInputs runs plan-time checks on a component ref against its declared variables. Two invariants:
- Every input key must correspond to a declared variable on the component. A typo like `inputs = { naem = var.x }` is caught here, not at execution time.
- Every required variable (no declared default) must be present as an input key.
The value expressions themselves are NOT evaluated — they may reference action outputs that only exist at runtime. Type coercion of input values stays with the engine's runtime pass.
When the inputs expression is not a literal object (e.g. a function call producing a map), key-set inspection is skipped gracefully and the engine's runtime pass covers it. Required- variable checks still run if the inputs body has no `inputs` attribute at all.
func VariableDefault ¶
func VariableDefault(v *VariableBlock) (hcl.Expression, error)
VariableDefault returns the variable's default-value expression, or nil if the variable declared no default. A variable that explicitly sets `default = null` is treated as having a default (typed null); only genuinely-absent defaults return nil.
func VariableSensitive ¶ added in v0.2.0
func VariableSensitive(v *VariableBlock) (bool, error)
VariableSensitive reports whether v is declared `sensitive = true`.
Types ¶
type ActionBlock ¶
type ActionBlock struct {
Type string `hcl:"type,label"`
Name string `hcl:"name,label"`
Remain hcl.Body `hcl:",remain"`
}
ActionBlock represents: action "<type>" "<name>" { ... }
type ComponentDefBlock ¶
type ComponentDefBlock struct {
Name string `hcl:"name,label"`
Description string `hcl:"description,optional"`
Tags []string `hcl:"tags,optional"`
Variables []*VariableBlock `hcl:"variable,block"`
Actions []*ActionBlock `hcl:"action,block"`
Outputs []*OutputBlock `hcl:"output,block"`
}
ComponentDefBlock defines a reusable component: component "name" { ... }
Description and Tags mirror the scenario-level fields: free-form metadata surfaced by tooling, ignored by the engine.
type ComponentFile ¶
type ComponentFile struct {
Component *ComponentDefBlock `hcl:"component,block"`
}
ComponentFile is the top-level HCL structure for a component definition file.
type ComponentRef ¶
type ComponentRef struct {
Type string `hcl:"type,label"`
Name string `hcl:"name,label"`
Source string `hcl:"source,attr"`
Inputs hcl.Body `hcl:",remain"`
}
ComponentRef is a component instance within a scenario. component "<type>" "<name>" { source = "..." inputs = { ... } }
type Instance ¶
Instance identifies one copy of an action or component expanded by `count` or `for_each`. Key is a number index for count and a string key for for_each; Value is for_each's element (unset for count).
func ExpandInstances ¶
func ExpandInstances(body hcl.Body, vars map[string]cty.Value, seed uint64, scope string) ([]*Instance, hcl.Body, error)
ExpandInstances pulls `count` / `for_each` off body, evaluates it against the scenario's variables, and returns one Instance per copy plus the body with those attributes hidden.
A body with neither attribute returns []*Instance{nil}: a single, unexpanded block. count = 0 or an empty for_each returns an empty slice.
Both attributes must be known before anything runs, so they may only reference var.* and functions — never action or component outputs.
seed and scope (the block's address) seed any random functions the expression calls.
type Option ¶
type Option func(*loadConfig)
Option changes how a scenario loads.
func WithOverrides ¶ added in v0.2.0
WithOverrides layers --var style overrides over the values LoadScenarioValues is given; teardown uses it to take sensitive variables, which records leave out.
type OutputBlock ¶
type OutputBlock struct {
Name string `hcl:"name,label"`
Value hcl.Expression `hcl:"value"`
}
OutputBlock represents: output "name" { value = <expr> }
type ParsedComponent ¶
type ParsedComponent struct {
Ref *ComponentRef
Def *ComponentDefBlock
// Instance is set when the ref uses count / for_each; nil for a
// plain single component. Its count.* / each.* namespace is in
// scope for the ref's inputs.
Instance *Instance
}
ParsedComponent holds a resolved component definition alongside its instance ref.
type ParsedScenario ¶
type ParsedScenario struct {
Scenario *ScenarioBlock
Components map[string]*ParsedComponent // keyed by "type.name"
Variables map[string]cty.Value
// RequiredProviders maps a provider name to its declared source,
// e.g. "postgres" → {Source: "builtin/postgres"}. Populated from
// the scenario's required_providers block. Empty when absent.
RequiredProviders map[string]RequiredProviderSpec
// ProviderConfigs maps a provider name to the evaluated attribute
// values from its `provider "<name>" {}` block. These are passed
// to provider.Registry.Configure. Providers without a config
// block receive an empty map rather than being absent, matching
// the Configure contract that lets providers start up with
// default or zero configuration.
ProviderConfigs map[string]map[string]cty.Value
// ScenarioDir is the absolute directory containing the scenario
// file. The engine uses it to resolve `file` attributes on
// action bodies to absolute paths before dispatching to
// providers — the same convention as component source paths and
// exec: provider sources, extended to any action that reads a
// file.
ScenarioDir string
// Sensitive names the scenario variables declared
// `sensitive = true`. Run records keep a hash of each, not its
// value.
Sensitive map[string]bool
// Seed drives every random function in the run: --seed, else the
// scenario's seed attribute, else a fresh random one. The run
// record keeps it so a run can be repeated.
Seed uint64
}
ParsedScenario holds the structurally-decoded scenario with deferred expressions.
func LoadScenario ¶
func LoadScenario(path, name string, vars map[string]string, opts ...Option) (*ParsedScenario, error)
LoadScenario parses a scenario HCL file, picks the scenario block matching name, resolves component sources, and merges CLI variable overrides with defaults.
An empty name selects the sole scenario when the file contains exactly one — a convenience that keeps `orchard run foo.hcl` ergonomic for the single-scenario case. When a file has multiple scenarios and name is empty, the error lists the available names so the caller can retry with --scenario.
func LoadScenarioValues ¶
func LoadScenarioValues(path, name string, values map[string]cty.Value, opts ...Option) (*ParsedScenario, error)
LoadScenarioValues is LoadScenario with typed variable values in place of CLI override strings: the resolved variables a run record holds. Teardown reloads a scenario this way so count / for_each expansion, provider configs and variables without a default all see what the recorded run saw. Variables the scenario declares but values lacks fall back to their defaults.
type ProviderConfigBlock ¶
ProviderConfigBlock represents: provider "<name>" { <config attributes> }. The body is captured for deferred evaluation against the scenario's variable context.
type RequiredProviderSpec ¶
type RequiredProviderSpec struct {
Source string
}
RequiredProviderSpec captures the declared source of a provider. Version and explicit configuration-alias fields land here when we add them; the struct form lets us evolve without breaking callers.
type RequiredProvidersBlock ¶
RequiredProvidersBlock declares the providers a scenario needs. The body is a flat attribute set where each attribute is a provider name assigned to an object describing the source:
required_providers {
postgres = { source = "builtin/postgres" }
http = { source = "builtin/http" }
}
The body is captured as hcl.Body so each entry's object can be decoded dynamically — gohcl cannot flatten a "remaining-attribute- set-of-objects" shape into a typed struct.
type ScenarioBlock ¶
type ScenarioBlock struct {
Name string `hcl:"name,label"`
Description string `hcl:"description,optional"`
Tags []string `hcl:"tags,optional"`
Seed *uint64 `hcl:"seed,optional"`
RequiredProviders *RequiredProvidersBlock `hcl:"required_providers,block"`
Providers []*ProviderConfigBlock `hcl:"provider,block"`
Variables []*VariableBlock `hcl:"variable,block"`
Components []*ComponentRef `hcl:"component,block"`
Actions []*ActionBlock `hcl:"action,block"`
Outputs []*OutputBlock `hcl:"output,block"`
}
ScenarioBlock represents: scenario "name" { ... }
Description and Tags are optional metadata surfaced by `orchard list` and reserved for future search / categorisation tooling. They have no effect on execution and are ignored by the engine.
type ScenarioFile ¶
type ScenarioFile struct {
Scenarios []*ScenarioBlock `hcl:"scenario,block"`
}
ScenarioFile is the top-level HCL structure for a scenario file.
Scenarios is a slice so a single file can hold multiple scenario blocks — useful for grouping related scenarios (e.g. all UAT cases for a feature) without proliferating files. Callers pick one by name via LoadScenario's scenario parameter; a file containing a single scenario can still pass "" and have it auto-selected.
type VariableBlock ¶
VariableBlock represents: variable "name" { type = <typeexpr>, default = <value>, description = "..." }.
Body captures the block's attributes as-is (via gohcl's `,remain`). We decode type/default/description manually in the parser rather than relying on gohcl's optional hcl.Expression handling, which synthesizes a cty.NullVal placeholder for absent optional fields — making "absent default" and "default = null" indistinguishable.