configgraph

package
v0.5.0 Latest Latest
Warning

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

Go to latest
Published: Aug 31, 2026 License: MPL-2.0 Imports: 25 Imported by: 0

Documentation

Overview

Copyright (c) The OpenTofu Authors SPDX-License-Identifier: MPL-2.0 Copyright (c) 2023 HashiCorp, Inc. SPDX-License-Identifier: MPL-2.0

Package configgraph contains the unexported implementation details of package eval.

Package eval offers an API focused on what external callers need to implement specific operations like the plan and apply phases, while hiding the handling of language features that get treated equivalently regardless of phase. This package is the main place that such handling is hidden.

All functions in this package which take context.Context objects as their first argument require a context that's derived from a call to grapheval.ContextWithWorker, and in non-test situations _also_ one derived from a call to grapheval.ContextWithRequestTracker to allow identifying failed evaluation requests in error messages.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func CheckAllRules

func CheckAllRules(ctx context.Context, rules iter.Seq[*CheckRule], handleResult func(ruleDeclRange tfdiags.SourceRange, status checks.Status, errMsg string) tfdiags.Diagnostics) (cty.ValueMarks, tfdiags.Diagnostics)

CheckAllRules deals with the boilerplate of evaluating a series of CheckRule objects and reacting to their results.

Evaluates each rule in turn and then calls handleResult for each one, passing the final status, and the error message if and only if the status is checks.StatusFail.

handleResult may choose to return diagnostics to add to the final aggregate set of diagnostics, but should typically add error diagnostics only if the status is checks.StatusFail because check rules generate their own error diagnostics for totally-invalid cases that yield checks.StatusError.

The results are a set of all of the cty marks on the condition results of the rules and an aggregate set of diagnostics mixing any automatically-generated usage errors with failure-related diagonstics returned by handleResult. A caller should typically transfer all of the returned marks to whatever values were being checked to reflect that the final value was effectively "derived from" the check results.

func ContributingResourceInstances

func ContributingResourceInstances(v cty.Value) iter.Seq[*ResourceInstance]

ContributingResourceInstances returns an iterable sequence of all of the resource instances whose result values may have contributed to the given value.

The results are not guaranteed to be unique: if different nested parts of the same value were derived from the same resource instance then it may or may not appear twice in the sequence. Deduplicating, if needed, is the caller's responsibility.

If sending the result somewhere outside of the evaluation system, which therefore shouldn't be aware of the ResourceInstance type, consider passing the result to ResourceInstanceAddrs to provide a sequence of absolute resource instance addresses instead.

func IsDependencyMark

func IsDependencyMark(mark any) bool

IsDependencyMark returns true if the given value is something that could be used to mark a cty.Value to represent a "dependency".

"Dependency" here means that some sort of externally-visible change must be made before the associated value could be used during the apply phase.

Currently only values of type ResourceInstanceMark are considered to be dependency-related, but that might change in future if we begin tracking other information about how values relate to changes that will happen during the apply phase.

func IsProviderInstanceRefType

func IsProviderInstanceRefType(ty cty.Type) bool

IsProviderInstanceRefValue returns true if the given type represents a reference to an instance of any provider.

func MaybeHCLSourceRange

func MaybeHCLSourceRange(maybeRng *tfdiags.SourceRange) *hcl.Range

func PrepareOutgoingValue

func PrepareOutgoingValue(v cty.Value) cty.Value

PrepareOutgoingValue returns a modified version of the given value that has been stripped of all of the marks we use internally to the evaluation system, and so is ready to be sent to other parts of OpenTofu that aren't aware of these details.

func ProviderInstanceFromValue

func ProviderInstanceFromValue(v cty.Value, forProvider addrs.Provider) (exprs.FromValue[*ProviderInstance], error)

ProviderInstanceFromValue attempts to extract an instance of the given provider from the given value, returning it if successful or returning an error if not.

func ProviderInstanceRefType

func ProviderInstanceRefType(provider addrs.Provider) cty.Type

ProviderInstanceType returns the cty capsule type representing references to instances of a particular provider.

func ProviderInstanceRefTypeProvider

func ProviderInstanceRefTypeProvider(ty cty.Type) (addrs.Provider, bool)

ProviderInstanceRefTypeProvider returns the provider that the given type represents instances of, or sets the second result to false if the given type is not a provider instance reference type.

func ProviderInstanceRefValue

func ProviderInstanceRefValue(inst *ProviderInstance) cty.Value

ProviderInstanceRefValue returns a cty.Value of a capsule type produced by ProviderInstanceRefType that acts as a reference to the given provider instance which can then be used to send provider instance references through our normal expression evaluation mechanisms.

func RemoveNonDependencyMarks

func RemoveNonDependencyMarks(from cty.ValueMarks)

RemoveNonDependencyMarks modifies the given mark set in-place to remove any marks for which IsDependencyMark returns true.

func ResourceInstanceAddrs

func ResourceInstanceAddrs(insts iter.Seq[*ResourceInstance]) iter.Seq[addrs.AbsResourceInstance]

ResourceInstanceAddrs maps a sequence of ResourceInstance pointers into a sequence of their addrs.AbsResourceInstance addresses.

func WithoutResourceInstanceDependency

func WithoutResourceInstanceDependency(v cty.Value, addr addrs.AbsResourceInstance) cty.Value

WithoutResourceInstanceDependency returns a copy of the given value with any ResourceInstanceMark marks removed which match the given addrs.AbsResourceInstance, but with all other marks left intact.

This is primarilly used when dealing with "self" dependencies

func WithoutResourceInstanceMarks

func WithoutResourceInstanceMarks(v cty.Value) cty.Value

WithoutResourceInstanceMarks returns a copy of the given value with any ResourceInstanceMark marks removed from it, but with all other marks left intact.

This MUST be used at any boundary between the eval system and the rest of the OpenTofu codebase, because ResourceInstanceMark is an implementation detail of our evaluation strategy that the rest of the system does not expect to encounter.

Types

type CheckGroup

type CheckGroup struct {
	// contains filtered or unexported fields
}

CheckGroup has a similar purpose to sync.WaitGroup, but specialized for ergonomic implementation of the "CheckAll" methods we use for our tree walks to collect all results.

It uses the workgraph facilities so we can detect if multiple check requests would end up blocking on one another and return error diagnostics in that case.

The expected pattern is something like this:

var cg CheckGroup
cg.CheckValuer(ctx, thisObject.SomeValuer)
cg.CheckChild(ctx, thisObject.SomeChildObject)
return cg.Complete(ctx)

The Complete method then waits for all of the requested checks to complete and returns all of the diagnostics collected across them all.

func (*CheckGroup) Await

func (g *CheckGroup) Await(ctx context.Context, cb func(ctx context.Context))

Await is for situations where we must wait for some other worker-blocking operation to complete to decide what other Check* calls to make. The given callback can block on arbitrary workgraph-coordinated operations but should eventually make zero or more calls to Check* methods on the same [checkGroup] before it returns.

func (*CheckGroup) CheckChild

func (g *CheckGroup) CheckChild(ctx context.Context, child allChecker)

func (*CheckGroup) CheckDiagsFunc

func (g *CheckGroup) CheckDiagsFunc(ctx context.Context, f func(ctx context.Context) tfdiags.Diagnostics)

func (*CheckGroup) CheckValuer

func (g *CheckGroup) CheckValuer(ctx context.Context, v exprs.Valuer)

func (*CheckGroup) Complete

func (g *CheckGroup) Complete(_ context.Context) tfdiags.Diagnostics

Complete blocks until all previous calls to Check* methods have completed and then returns all of the aggregated diagnostics.

After calling Complete the [checkGroup] is closed and must not be used anymore.

type CheckRule

type CheckRule struct {
	// ConditionValuer produces the boolean result which determines whether
	// the check passes. The result should be of type [cty.Bool] and should
	// be [cty.True] if the condition is satisfied or [cty.False] if it is
	// not.
	//
	// The valuer is also allowed to return an unknown value if it isn't
	// yet possible to decide whether the condition is satisfied. Null
	// values are not allowed and will cause the check to fail with "error"
	// status.
	ConditionValuer exprs.Valuer

	// ErrorMessageValuer returns a string value containing an error message
	// that should be used when the condition is not satified.
	//
	// The result is required to be known and non-null. If this valuer
	// fails to evaluate with error diagnostics then those error diagnostics
	// will be returned along with a generic error message and the check
	// will fail with the "error" status.
	//
	// This valuer is used only when [ConditionValuer] returns [cty.False].
	ErrorMessageValuer exprs.Valuer

	// DeclSourceRange is a source range that the module author would consider
	// to represent the declaration of this check rule, for use in error
	// messages that describe which rule was responsible for detecting a
	// failure.
	DeclSourceRange tfdiags.SourceRange
}

CheckRule represents an author-defined condition that must be true and an error message to return if it isn't true.

In many cases the result of a check rule depends on some other value in a local scope, in which case the type that the check rules belong to must include a callback function that returns check rules based on that result rather than predefined inline check rules. The exprs.Valuer objects in a CheckRule must be pre-bound to whatever local scope is appropriate for the context where they are declared.

If you have an iter.Seq of *CheckRule, or something that you can conveniently use as one, [checkAllRules] is a useful way to visit all of them and react consistently to their results.

func (*CheckRule) Check

func (*CheckRule) ConditionRange

func (r *CheckRule) ConditionRange() tfdiags.SourceRange

ConditionRange returns the source range where the condition expression was declared.

func (*CheckRule) DeclRange

func (r *CheckRule) DeclRange() tfdiags.SourceRange

DeclRange returns the source range where this check was declared.

func (*CheckRule) ErrorMessage

func (r *CheckRule) ErrorMessage(ctx context.Context) (string, tfdiags.Diagnostics)

type CompileProviderConfigRef

type CompileProviderConfigRef func(ctx context.Context, providerInstAddr addrs.LocalProviderConfig) exprs.Valuer

CompileProviderConfigRef represents the lookup of a local provider config within a given "scope". This is a side channel given the legacy inheritence of providers between modules

Each valuer returned is expected to evaluate to a value of a type returned by ProviderInstanceRefType.

type InputVariable

type InputVariable struct {
	// Addr is the absolute address of this input variable.
	Addr addrs.AbsInputVariableInstance

	// RawValue produces the "raw" value, as chosen by the caller of the
	// module, which has not yet been type-converted or validated.
	RawValue *OnceValuer

	// TargetType and targetDefaults together represent the type conversion
	// and default object attribute value insertions that must be applied
	// to rawValue to produce the final result.
	TargetType     cty.Type
	TargetDefaults *typeexpr.Defaults

	// FinalizeValue is an optional callback which, if provided, is called
	// during [InputVariable.Value] returns to allow
	// language-edition-specific code to apply any final checks or
	// transformations to the value. The provided value has already been
	// subjected to type conversion, but has not yet had the validation
	// rules applied to it. The result of this function is passed to the
	// validation checks.
	//
	// For example, this is used by package tofu2024 to deal with the various
	// arguments in a variable declaration that affect the interpretation of
	// the value, such as marking it as sensitive.
	//
	// The given context has the values needed to support potentially evaluating
	// other expressions inside the callback.
	FinalizeValue func(context.Context, cty.Value) (cty.Value, tfdiags.Diagnostics)

	// Validation rules are user-defined checks that must succeed for the
	// final value to be considered valid for use in downstream expressions.
	//
	// CompileValidationRules takes the value of the variable after
	// type conversion and built-in validation rules have been applied to
	// it, and returns a sequence of compiled [CheckRule] objects that
	// test whether the author's configured conditions have been met
	// for the given value.
	CompileValidationRules func(ctx context.Context, value cty.Value) iter.Seq[*CheckRule]
}

func (*InputVariable) AnnounceAllGraphevalRequests

func (i *InputVariable) AnnounceAllGraphevalRequests(announce func(workgraph.RequestID, grapheval.RequestInfo))

func (*InputVariable) CheckAll

func (i *InputVariable) CheckAll(ctx context.Context) tfdiags.Diagnostics

func (*InputVariable) StaticCheckTraversal

func (i *InputVariable) StaticCheckTraversal(traversal hcl.Traversal) tfdiags.Diagnostics

StaticCheckTraversal implements exprs.Valuer.

func (*InputVariable) Value

Value implements exprs.Valuer.

func (*InputVariable) ValueSourceRange

func (i *InputVariable) ValueSourceRange() *tfdiags.SourceRange

ValueSourceRange implements exprs.Valuer.

type InstanceSelector

type InstanceSelector interface {
	// InstanceKeyType returns the instance key type that all instances
	// produced by this selector will have.
	//
	// This is separated to allow for static validation of traversals
	// before actually selecting the instances. It also decides
	// between several different possible representations of an empty
	// set of instances.
	InstanceKeyType() addrs.InstanceKeyType

	// Instances returns a sequence of all of the instance keys, which
	// must must be of the same type returned from InstanceKeyType,
	// and the associated repetition data to use when compiling each
	// instance.
	//
	// If the decision about which instance keys to return was based
	// on evaluating expressions or otherwise interacting with cty values
	// then the result includes any marks that were present on the value used
	// to decide which instance keys exist. If there were no marks at all, or
	// the decision was not based on evaluating expressions, then the value
	// is not marked.
	//
	// If the returned diagnostics contains an error then the set of
	// instance keys is ignored but the returned marks will still be
	// retained and used for building a placeholder result.
	Instances(ctx context.Context) (exprs.FromValue[InstancesSeq], tfdiags.Diagnostics)

	// InstancesSourceRange optionally reports a source range for something in
	// the configuration that the author would consider as representing the
	// rule for deciding which instances exist.
	//
	// For example, this could be the source range of the expression
	// associated with a "for_each" argument, if that was what the
	// selector was based on.
	//
	// If there is no single obvious configuration construct to report
	// then prefer to return nil rather than returning something strange.
	InstancesSourceRange() *tfdiags.SourceRange
}

An InstanceSelector defines a rule for choosing which dynamic child instances exist for a particular object.

This package intentionally doesn't directly know directly about the "count", "for_each", and "enabled" meta arguments used in the current surface language because it's designed to be flexible for us to potentially change how these features work in later editions of the language, but the general idea here is that the "compiler" code for a specific edition of the language would have an implementation of this for each of the different repetition arguments and populate the appropriate one into the InstanceSelector field of each multi-instance container object.

type InstancesSeq

type InstancesSeq = func(yield func(addrs.InstanceKey, instances.RepetitionData) bool)

type LocalValue

type LocalValue struct {
	Addr     addrs.AbsLocalValue
	RawValue *OnceValuer
}

func (*LocalValue) AnnounceAllGraphevalRequests

func (l *LocalValue) AnnounceAllGraphevalRequests(announce func(workgraph.RequestID, grapheval.RequestInfo))

func (*LocalValue) CheckAll

func (l *LocalValue) CheckAll(ctx context.Context) tfdiags.Diagnostics

CheckAll implements allChecker.

func (*LocalValue) StaticCheckTraversal

func (l *LocalValue) StaticCheckTraversal(traversal hcl.Traversal) tfdiags.Diagnostics

StaticCheckTraversal implements exprs.Valuer.

func (*LocalValue) Value

Value implements exprs.Valuer.

func (*LocalValue) ValueSourceRange

func (l *LocalValue) ValueSourceRange() *tfdiags.SourceRange

ValueSourceRange implements exprs.Valuer.

type ModuleCall

type ModuleCall struct {
	Addr      addrs.AbsModuleCall
	DeclRange tfdiags.SourceRange

	// ParentSourceAddr is the source address of the module that contained
	// this module call, which is then used as the base for resolving
	// any relative addresses returned from SourceAddrValuer.
	ParentSourceAddr addrs.ModuleSource

	// InstanceSelector represents a rule for deciding which instances of
	// this resource have been declared.
	InstanceSelector InstanceSelector

	// SourceAddrValuer and VersionConstraintValuer together describe how
	// to select the module to be called.
	//
	// We currently require these to be equal for all instances of the
	// module call because although in principle this new evaluation model
	// could support entirely different declarations in each module, the
	// surface syntax of HCL would make that very hard to use (can't easily
	// set drastically different arguments for each instance) and this
	// also allows us to echo the design for resource instances where we've
	// effectively already baked in what schema we ought to be validating
	// against before we try to evaluate the config body inside
	// [ModuleCallInstance].
	SourceAddrValuer        *OnceValuer
	VersionConstraintValuer *OnceValuer

	// ValidateSourceArguments is a callback function provided by whatever
	// compiled this [ModuleCall] object that checks whether the source
	// arguments are resolvable in the current execution context, so that we
	// can report any problems just once at the call level rather than
	// re-reporting the same problems once for each instance.
	//
	// Depending on what phase we're in this could either try to find a
	// suitable module in a local cache directory or could even try to actually
	// fetch a remote module over the network, and so this function may take
	// a long time to return.
	ValidateSourceArguments func(ctx context.Context, sourceArgs ModuleSourceArguments) tfdiags.Diagnostics

	// CompileCallInstance is a callback function provided by whatever
	// compiled this [ModuleCall] object that knows how to produce a compiled
	// [ModuleCallInstance] object once we know of the instance key and
	// associated repetition data for it.
	//
	// This indirection allows the caller to take into account the same
	// context it had available when it built this [ModuleCall] object, while
	// incorporating the new information about this specific instance.
	//
	// This should only be called with a [ModuleSourceArguments] that was
	// accepted by [ModuleCall.ValidateSourceArguments] without returning any
	// errors.
	CompileCallInstance func(ctx context.Context, sourceArgs ModuleSourceArguments, key addrs.InstanceKey, repData instances.RepetitionData) *ModuleCallInstance
	// contains filtered or unexported fields
}

func (*ModuleCall) AnnounceAllGraphevalRequests

func (c *ModuleCall) AnnounceAllGraphevalRequests(announce func(workgraph.RequestID, grapheval.RequestInfo))

func (*ModuleCall) CheckAll

func (c *ModuleCall) CheckAll(ctx context.Context) tfdiags.Diagnostics

CheckAll implements allChecker.

func (*ModuleCall) Instances

Instances returns the instances that are selected for this module call in its configuration, without evaluating their configuration objects yet.

func (*ModuleCall) SourceArguments

func (*ModuleCall) StaticCheckTraversal

func (c *ModuleCall) StaticCheckTraversal(traversal hcl.Traversal) tfdiags.Diagnostics

StaticCheckTraversal implements exprs.Valuer.

func (*ModuleCall) Value

Value implements exprs.Valuer.

func (*ModuleCall) ValueSourceRange

func (c *ModuleCall) ValueSourceRange() *tfdiags.SourceRange

ValueSourceRange implements exprs.Valuer.

type ModuleCallInstance

type ModuleCallInstance struct {
	// ModuleInstanceAddr is the address of the module instance that this
	// call instance is establishing.
	//
	// The difference between an instance of a module call and an instance
	// of a module is a little fussy and pedantic: the call instance is
	// viewed from the perspective of the caller while the module instance
	// is viewed from the perspective of the callee. But outside of package
	// configgraph that is not a distinction we make and so we don't have
	// a separate address type for an "absolute module call instance".
	ModuleInstanceAddr addrs.ModuleInstance

	// Glue is provided by whatever compiled this object to allow us to learn
	// more about the module that is being called.
	Glue ModuleCallInstanceGlue

	// InputsValuer is a valuer for all of the input variable values taken
	// together as a single object. It's structured this way mainly for
	// consistency with how we deal with the objects representing arguments
	// in other blocks, but it also means that a future edition of the
	// language could potentially use different syntax for input variables
	// that allows constructing the entire map dynamically using expression
	// syntax.
	//
	// TODO: This should actually really be map[addrs.InputVariable]*OnceValuer
	// so that each input variable can be resolved independently, since the
	// "package tofu" implementation allows dependencies from a module
	// instance's output values to its own input variables as long as there
	// are no cycles in the dependency chain within the module.
	InputsValuer *OnceValuer

	// ProvidersFromParent is our representation of the weird
	// "side-channel" that allows providers to pass between modules, which
	// is separate from the concept of input variables despite being
	// conceptually similar.
	ProvidersFromParent CompileProviderConfigRef
	// contains filtered or unexported fields
}

func (*ModuleCallInstance) AnnounceAllGraphevalRequests

func (m *ModuleCallInstance) AnnounceAllGraphevalRequests(announce func(workgraph.RequestID, grapheval.RequestInfo))

func (*ModuleCallInstance) CheckAll

CheckAll implements allChecker.

func (*ModuleCallInstance) InputsValue

InputsValue returns the validated inputs value that should be passed when compiling the child module instance.

Whatever diagnostics this returns should eventually be returned through the ModuleCallInstanceGlue.OutputsValue method on the object in the Glue field, after indirection through whatever the compilation layer does to compile and evaluate the child module instance.

func (*ModuleCallInstance) StaticCheckTraversal

func (m *ModuleCallInstance) StaticCheckTraversal(traversal hcl.Traversal) tfdiags.Diagnostics

StaticCheckTraversal implements exprs.Valuer.

func (*ModuleCallInstance) Value

Value implements exprs.Valuer.

func (*ModuleCallInstance) ValueSourceRange

func (m *ModuleCallInstance) ValueSourceRange() *tfdiags.SourceRange

ValueSourceRange implements exprs.Valuer.

type ModuleCallInstanceGlue

type ModuleCallInstanceGlue interface {
	// ValidateInputs determines whether the given value is a valid
	// representation of the inputs to the target module, returning diagnostics
	// describing any problems.
	//
	// TODO: This probably also needs an argument for describing the
	// "sidechannel" provider instances, as would be specified in the "providers"
	// meta-argument in the current language, so the callee can also check
	// those.
	ValidateInputs(ctx context.Context, inputsVal cty.Value) tfdiags.Diagnostics

	// OutputsValue returns the value representing the outputs of this module
	// instance. This is what should be returned as the value of the module
	// instance.
	//
	// Real implementations of this will tend to indirectly depend on the
	// [ModuleCallInstance.InputsValue] method of the module call instance
	// that this glue object belongs to, but exactly what happens between
	// those two is outside of this package's scope of responsibility.
	OutputsValue(ctx context.Context) (cty.Value, tfdiags.Diagnostics)
}

ModuleCallInstanceGlue describes a callback API that ModuleCallInstance objects use to ask the caller questions about the module that's being called.

Real implementations of this interface will sometimes block on fetching a remote module package for inspection, or on operations caused by declarations in the child module. If that external work depends on information coming from any other part of this package's API then the implementation of that MUST use the mechanisms from package grapheval in order to cooperate with the self-dependency detection used by this package to prevent deadlocks.

type ModuleInstance

type ModuleInstance struct {
	Addr addrs.ModuleInstance

	// OutputValuers are the valuers for each of the output values declared
	// in the module. The result value of a module instance is an object
	// value with an attribute for each element in this map.
	OutputValuers map[addrs.OutputValue]*OnceValuer

	// callDeclRange is used for module instances that are produced because
	// of a "module" block in a parent module, or by some similar mechanism
	// like a .tftest.hcl "run" block, which can then be used as a source
	// range for the overall object value representing the module instance's
	// results.
	//
	// This is left as nil for module instances that are created implicitly,
	// such as a root module which is being "called" directly from OpenTofu CLI
	// in a command like "tofu plan".
	CallDeclRange *tfdiags.SourceRange
}

func (*ModuleInstance) AnnounceAllGraphevalRequests

func (m *ModuleInstance) AnnounceAllGraphevalRequests(announce func(workgraph.RequestID, grapheval.RequestInfo))

AnnounceAllGraphevalRequests calls announce for each grapheval.Once, OnceValuer, or other workgraph.RequestID anywhere in the tree under this object.

This is used only when workgraph detects a self-dependency or failure to resolve and we want to find a nice human-friendly name and optional source range to use to describe each of the requests that were involved in the problem.

func (*ModuleInstance) CheckAll

CheckAll for a ModuleInstance doesn't actually really do anything at all because a module instance only acts as a place to aggregate some output value exprs.Valuers and so it doesn't actually have any "children" in the sense this package means that. ("children" in this package means, for example, the relationship between a resource and its instances where we think of the instances as being more tightly coupled to the resource they belong to, likely to all be sharing the same configuration etc.)

However, callers implementing [evalglue.CompiledModuleInstance.CheckAll] should still call this method for completeness, just in case it begins doing something in future.

func (*ModuleInstance) StaticCheckTraversal

func (m *ModuleInstance) StaticCheckTraversal(traversal hcl.Traversal) tfdiags.Diagnostics

StaticCheckTraversal implements exprs.Valuer.

func (*ModuleInstance) Value

Value implements exprs.Valuer.

func (*ModuleInstance) ValueSourceRange

func (m *ModuleInstance) ValueSourceRange() *tfdiags.SourceRange

ValueSourceRange implements exprs.Valuer.

type ModuleSourceArguments

type ModuleSourceArguments struct {
	// Source is the already-parsed-and-normalized module source address.
	Source addrs.ModuleSource

	// AllowedVersions describes what subset of the available versions are
	// accepted, if the source type is one that supports version constraints.
	//
	// It's the responsibility of the [ModuleCall] logic to reject attempts
	// to set a version constraint for a source type that doesn't support
	// it, so a [ModuleSourceArguments] object should not be constructed
	// with a nonzero value in this field when [Source] is not of a
	// version-aware source type.
	AllowedVersions versions.Set
}

type OnceValuer

type OnceValuer struct {
	// contains filtered or unexported fields
}

func ValuerOnce

func ValuerOnce(valuer exprs.Valuer) *OnceValuer

ValuerOnce wraps the given exprs.Valuer so that the underlying [Value] method will be called only once and reused for all future calls.

Calls to Value on the result must be made with a context derived from one produced by grapheval.ContextWithWorker, which is then used to track and report dependency cycles. If the given context is not so annotated then Value will immediately panic.

The StaticCheckTraversal method is _not_ wrapped and so should be a relatively cheap operation as usual and must not interact (directly or indirectly) with any grapheval helpers.

func (*OnceValuer) RequestID

func (v *OnceValuer) RequestID() workgraph.RequestID

RequestID returns the workgraph package's tracking identifier for the request to return the value, or workgraph.NoRequest if nobody has called the Value method yet.

func (*OnceValuer) StaticCheckTraversal

func (v *OnceValuer) StaticCheckTraversal(traversal hcl.Traversal) tfdiags.Diagnostics

StaticCheckTraversal implements exprs.Valuer.

func (*OnceValuer) Value

Value implements exprs.Valuer.

func (*OnceValuer) ValueSourceRange

func (v *OnceValuer) ValueSourceRange() *tfdiags.SourceRange

ValueSourceRange implements exprs.Valuer.

type OutputValue

type OutputValue struct {
	// Addr is the absolute address of this output value.
	Addr addrs.AbsOutputValue

	// Preconditions are user-defined checks that must succeed before OpenTofu
	// will evaluate the output value's expression.
	//
	// Unlike some other uses of [CheckRule], output value preconditions don't
	// have any special local symbols in scope and so are precompiled as part of
	// the [OutputValue] they belong to.
	Preconditions []*CheckRule

	// RawValue produces the "raw" value, as chosen by the caller of the
	// module, which has not yet been type-converted or validated.
	RawValue *OnceValuer

	// TargetType and TargetDefaults together represent the type conversion
	// and default object attribute value insertions that must be applied
	// to RawValue to produce the final result.
	TargetType     cty.Type
	TargetDefaults *typeexpr.Defaults

	// If ForceSensitive is true then the final value will be marked as
	// sensitive regardless of whether the associated raw value was sensitive.
	ForceSensitive bool

	// If ForceEphemeral is true then the final value will be marked as
	// ephemeral regardless of whether the associated raw value was ephemeral.
	ForceEphemeral bool
}

func (*OutputValue) AnnounceAllGraphevalRequests

func (o *OutputValue) AnnounceAllGraphevalRequests(announce func(workgraph.RequestID, grapheval.RequestInfo))

func (*OutputValue) CheckAll

func (o *OutputValue) CheckAll(ctx context.Context) tfdiags.Diagnostics

CheckAll implements allChecker.

func (*OutputValue) ResultTypeConstraint

func (o *OutputValue) ResultTypeConstraint() cty.Type

ResultTypeConstraint returns a type constraint that all possible results of this output value are guaranteed to conform to.

The result is cty.DynamicPseudoType for an output value which has no declared type constraint, meaning that there is no guarantee whatsoever about the result type.

func (*OutputValue) StaticCheckTraversal

func (o *OutputValue) StaticCheckTraversal(traversal hcl.Traversal) tfdiags.Diagnostics

StaticCheckTraversal implements exprs.Valuer.

func (*OutputValue) Value

Value implements exprs.Valuer.

func (*OutputValue) ValueSourceRange

func (o *OutputValue) ValueSourceRange() *tfdiags.SourceRange

ValueSourceRange implements exprs.Valuer.

type ProviderConfig

type ProviderConfig struct {
	// FIXME: The current form of AbsProviderConfig is weird and not quite
	// right, because the "Abs" prefix is supposed to represent something
	// belonging to an addrs.ModuleInstance while this models addrs.Module
	// instead. We'll probably need to introduce some temporary new types
	// alongside the existing ones for the sake of this experiment, and then
	// have the new ones replace the old ones if we decide to move forward
	// with something like this.
	Addr      addrs.AbsProviderConfigCorrect
	DeclRange tfdiags.SourceRange

	// InstanceSelector represents a rule for deciding which instances of
	// this resource have been declared.
	InstanceSelector InstanceSelector

	// ProviderAddr is the address of the provider that this is a configuration
	// for. This object can produce zero or more instances of this provider.
	ProviderAddr addrs.Provider

	// CompileProviderInstance is a callback function provided by whatever
	// compiled this [Provider] object that knows how to produce a compiled
	// [ProviderInstance] object once we know of the instance key and associated
	// repetition data for it.
	//
	// This indirection allows the caller to take into account the same
	// context it had available when it built this [Provider] object, while
	// incorporating the new information about this specific instance.
	CompileProviderInstance func(ctx context.Context, key addrs.InstanceKey, repData instances.RepetitionData) *ProviderInstance
	// contains filtered or unexported fields
}

func (*ProviderConfig) AnnounceAllGraphevalRequests

func (p *ProviderConfig) AnnounceAllGraphevalRequests(announce func(workgraph.RequestID, grapheval.RequestInfo))

func (*ProviderConfig) CheckAll

CheckAll implements allChecker.

func (*ProviderConfig) Instances

Instances returns the instances that are selected for this provider config in its configuration, without evaluating their configuration objects yet.

Use this when performing a tree walk to discover provider instances to make sure that it's possible to tell whatever process is running alongside that it needs to produce a result value for a particular provider instance before we actually request that value.

func (*ProviderConfig) StaticCheckTraversal

func (p *ProviderConfig) StaticCheckTraversal(traversal hcl.Traversal) tfdiags.Diagnostics

StaticCheckTraversal implements exprs.Valuer.

func (*ProviderConfig) Value

Value implements exprs.Valuer.

func (*ProviderConfig) ValueSourceRange

func (p *ProviderConfig) ValueSourceRange() *tfdiags.SourceRange

ValueSourceRange implements exprs.Valuer.

type ProviderInstance

type ProviderInstance struct {
	// Addr is the absolute address of this specific provider instance.
	Addr addrs.AbsProviderInstanceCorrect

	// ProviderAddr is the address of the provider this is an instance of.
	ProviderAddr addrs.Provider

	// ConfigValuer produces the object value representing the configuration
	// for this provider instance.
	ConfigValuer *OnceValuer

	// ValidateConfig is a function provided by whatever compiled this object
	// which takes the result of ConfigValuer and potentially returns additional
	// diagnostics typically based on validation logic built in to the provider
	// itself.
	ValidateConfig func(context.Context, cty.Value) tfdiags.Diagnostics
	// contains filtered or unexported fields
}

ProviderInstance represents the configuration for an instance of a provider.

Note that this type's name is slightly misleading because it does not represent an already-running provider that requests can be sent to, but rather the configuration that should be sent to a running instance of this provider in order to prepare it for use. This package does not deal with "configured" providers directly at all, instead expecting its caller (e.g. an implementation or the plan or apply phase) to handle the provider instance lifecycle.

func (*ProviderInstance) AnnounceAllGraphevalRequests

func (p *ProviderInstance) AnnounceAllGraphevalRequests(announce func(workgraph.RequestID, grapheval.RequestInfo))

func (*ProviderInstance) CheckAll

CheckAll implements allChecker.

func (*ProviderInstance) ConfigValue

func (p *ProviderInstance) ConfigValue(ctx context.Context) (cty.Value, tfdiags.Diagnostics)

ConfigValue returns an object representing the configuration that should be sent to a provider to make it behave as the configured provider instance.

This value should not bt exposed for references from expressions elsewhere in the configuration. The result is considered private to the provider process that is configured with it.

func (*ProviderInstance) ResourceInstanceDependencies

func (p *ProviderInstance) ResourceInstanceDependencies(ctx context.Context) iter.Seq[*ResourceInstance]

ResourceInstanceDependencies returns a sequence of any resource instances whose results the configuration of this provider instance depends on.

The result of this is trustworthy only if ProviderInstance.CheckAll returns without diagnostics. If errors are present then the result is best-effort but likely to be incomplete.

func (*ProviderInstance) StaticCheckTraversal

func (p *ProviderInstance) StaticCheckTraversal(traversal hcl.Traversal) tfdiags.Diagnostics

StaticCheckTraversal implements exprs.Valuer.

func (*ProviderInstance) Value

Value implements exprs.Valuer.

func (*ProviderInstance) ValueSourceRange

func (p *ProviderInstance) ValueSourceRange() *tfdiags.SourceRange

ValueSourceRange implements exprs.Valuer.

type Provisioner

type Provisioner struct {
	Type      string
	When      configs.ProvisionerWhen
	OnFailure configs.ProvisionerOnFailure

	// Config is the current instance value specific configuration function
	Config func(context.Context, cty.Value) (ProvisionerConfig, tfdiags.Diagnostics)

	// Dependencies of the configuration (excluding the self value)
	Dependencies iter.Seq[*ResourceInstance]
}

type ProvisionerConfig

type ProvisionerConfig struct {
	Value      cty.Value
	Connection cty.Value
}

type Resource

type Resource struct {
	// Addr is the absolute address of this resource, used as the basis of
	// the addresses used to track its instances between plan/apply rounds
	// and between the plan and apply phases in a single round.
	//
	// Placeholder addresses (where the IsPlaceholder method returns true) are
	// allowed here, representing that the containing object is actually
	// itself a placeholder for zero or more resources whose existence
	// and addresses we cannot determine yet.
	Addr addrs.AbsResource

	// InstanceSelector represents a rule for deciding which instances of
	// this resource have been declared.
	InstanceSelector InstanceSelector

	// CompileResourceInstance is a callback function provided by whatever
	// compiled this [Resource] object that knows how to produce a compiled
	// [ResourceInstance] object once we know of the instance key and associated
	// repetition data for it.
	//
	// This indirection allows the caller to take into account the same
	// context it had available when it built this [Resource] object, while
	// incorporating the new information about this specific instance.
	CompileResourceInstance func(ctx context.Context, key addrs.InstanceKey, repData instances.RepetitionData) *ResourceInstance

	DestroyProvisioners func(ctx context.Context, addr addrs.ResourceInstance) []Provisioner

	// PreventDestroyValuer is a valuer that returns the module author's
	// direction about if this resource instance can be destroyed.
	//
	// The valuer must return something that can be converted to [cty.Bool].
	PreventDestroyValuer *OnceValuer

	DeclRange tfdiags.SourceRange
	// contains filtered or unexported fields
}

func (*Resource) AnnounceAllGraphevalRequests

func (r *Resource) AnnounceAllGraphevalRequests(announce func(workgraph.RequestID, grapheval.RequestInfo))

func (*Resource) CheckAll

func (r *Resource) CheckAll(ctx context.Context) tfdiags.Diagnostics

CheckAll implements allChecker.

func (*Resource) Instances

func (r *Resource) Instances(ctx context.Context) map[addrs.InstanceKey]*ResourceInstance

Instances returns the instances that are selected for this resource in its configuration, without evaluating their configuration objects yet.

Use this when performing a tree walk to discover resource instances to make sure that it's possible to tell whatever process is running alongside that it needs to produce a result value for a particular resource instance before we actually request that value.

func (*Resource) IsExpansionPlaceholder

func (r *Resource) IsExpansionPlaceholder() bool

IsExpansionPlaceholder returns true if this object is acting as a placeholder for zero or more resources whose existence and addresses cannot be decided yet, because the expansion rule depends on information that isn't known yet.

Note that at the Resource level this means that one of the modules this resource is nested within has an unknown set of instances, rather than that this resource's own expansion is not known. Unknown expansion of the resource itself is represented by producing a single ResourceInstance which is a placeholder itself, as reported by ResourceInstance.IsExpansionPlaceholder.

func (*Resource) PreventDestroy

func (r *Resource) PreventDestroy(ctx context.Context) (cty.Value, *tfdiags.SourceRange, tfdiags.Diagnostics)

PreventDestroy returns a value-based representation of the "prevent destroy" setting for this resource.

The result is guaranteed to be a cty.Bool value, but it could potentially be unknown or marked and it's the caller's responsibility to handle those situations.

The different possible known boolean results have the following meaning:

  • cty.True means that this resource instance MUST not be destroyed.
  • cty.False means that this resource instance MAY be destroyed.
  • A null value is not accepted, see the comment below.

This was copied and modified from NodeAbstractResourceInstance.checkPreventDestroy

func (*Resource) StaticCheckTraversal

func (r *Resource) StaticCheckTraversal(traversal hcl.Traversal) tfdiags.Diagnostics

StaticCheckTraversal implements exprs.Valuer.

func (*Resource) Value

func (r *Resource) Value(ctx context.Context) (cty.Value, tfdiags.Diagnostics)

Value implements exprs.Valuer.

func (*Resource) ValueSourceRange

func (r *Resource) ValueSourceRange() *tfdiags.SourceRange

ValueSourceRange implements exprs.Valuer.

type ResourceInstance

type ResourceInstance struct {
	// Addr is the absolute address of this resource instance, which is used
	// to track the resource instance between plan/apply rounds and between
	// the plan and apply phases in a single round.
	//
	// Placeholder addresses (where the IsPlaceholder method returns true) are
	// allowed here, representing that the containing object is actually
	// itself a placeholder for zero or more resource instances whose existence
	// and addresses we cannot determine yet.
	Addr addrs.AbsResourceInstance

	// Provider is the provider that this resource's type belongs to. This
	// is the provider to use when asking for config validation, etc.
	Provider addrs.Provider

	// ConfigValuer is a valuer for producing the object value representing
	// the configuration for this object. How the final configuration value
	// is chosen is decided by whatever created this object, but most typically
	// it's by the instance-compilation logic in the parent [Resource].
	ConfigValuer *OnceValuer

	// ProviderInstanceValuer is a valuer for producing a value representing
	// the provider instance that this resource instance is associated with.
	//
	// This valuer should return a value of the capsule type produced by passing
	// the address from the Provider field into [ProviderInstanceRefType],
	// or else type mismatch errors will be reported during evaluation.
	ProviderInstanceValuer *OnceValuer

	// CreateProvisioners are the provisioners to run if the resource instance
	// is being created. These are distinct from Destroy provisioners, which
	// are handled in a different code path.
	CreateProvisioners []Provisioner

	// CreateBeforeDestroyValuer is a valuer that returns the module author's
	// direction about what "replace" order is required for this resource
	// instance.
	//
	// The valuer must return something that can be converted to [cty.Bool].
	CreateBeforeDestroyValuer *OnceValuer

	// IgnoreChangesPaths are paths for which the module author requested
	// that we "ignore changes".
	//
	// To "ignore changes" means to disregard what is configured for anything
	// under a matching path in ConfigVal and to instead treat the corresponding
	// value from the prior state as the effective desired state. This is
	// meaningful only when planning in-place updates to an object that is
	// already tracked in the prior state; it should be ignored when planning
	// to create or delete the object associated with a resource instance.
	//
	// Index steps within the path can potentially have unknown keys if the
	// decision about what to ignore is based on a value that won't be known
	// until the apply phase.
	//
	// This is meaningful only for resource modes that support the "update"
	// change action, and so is always empty for other modes.
	IgnoreChangesPaths []cty.Path

	// ReplaceTriggeredBy describes zero ore more attribute prefixes within
	// other resource instances for which the planning engine should force
	// replacement of this resource instance if any value beneath one of
	// the nominated paths has a change already planned for the current
	// plan/apply round.
	//
	// Index steps within the paths and instance keys within the resource
	// instance addresses can both potentially have unknown keys if the
	// decision about what to refer to is based on a value that won't be known
	// until the apply phase.
	//
	// This is meaningful only for resource modes that support the "update"
	// change action, and so is always false for other modes.
	//
	// Any resource instance mentioned in this collection will always also
	// appear in RequiredResourceInstances.
	ReplaceTriggeredBy []ResourceInstanceAttributePath

	// Glue is provided by the system that "compiled" this [ResourceInstance]
	// object to allow calling back into that system to ask further questions
	// that arise dynamically during evaluation but whose results vary based
	// on concerns that our outside this package's scope.
	Glue ResourceInstanceGlue
	// contains filtered or unexported fields
}

func (*ResourceInstance) AnnounceAllGraphevalRequests

func (ri *ResourceInstance) AnnounceAllGraphevalRequests(announce func(workgraph.RequestID, grapheval.RequestInfo))

func (*ResourceInstance) CheckAll

CheckAll implements allChecker.

func (*ResourceInstance) ConfigValue

func (ri *ResourceInstance) ConfigValue(ctx context.Context) (v cty.Value, diags tfdiags.Diagnostics)

ConfigValue returns the object value representing the for this resource instance, which should be used to represent the "desired state" when planning changes to this resource instance.

func (*ResourceInstance) CreateBeforeDestroy

func (ri *ResourceInstance) CreateBeforeDestroy(ctx context.Context) (cty.Value, *tfdiags.SourceRange, tfdiags.Diagnostics)

CreateBeforeDestroy returns a value-based representation of the "create before destroy" setting for this resource instance.

The result is guaranteed to be a cty.Bool value, but it could potentially be unknown or marked and it's the caller's responsibility to handle those situations.

The different possible known boolean results have the following meaning:

  • cty.True means that this resource instance MUST use the create-then-destroy replace order.
  • cty.False means that this resource instance MUST use the destroy-then-create replace order.
  • A null value means that either order is acceptable for this resource instance.

(Callers of this function may impose additional constraints on its result depending on the context where the resource instance is being used. This function only checks the basic validity rules.)

func (*ResourceInstance) IsExpansionPlaceholder

func (ri *ResourceInstance) IsExpansionPlaceholder() bool

IsExpansionPlaceholder returns true if this object is acting as a placeholder for zero or more instances whose existence and addresses cannot be decided yet, because the expansion rule depends on information that isn't known yet.

func (*ResourceInstance) ProviderInstance

func (*ResourceInstance) ResourceInstanceDependencies

func (ri *ResourceInstance) ResourceInstanceDependencies(ctx context.Context) iter.Seq[*ResourceInstance]

ResourceInstanceDependencies returns a sequence of any other resource instances whose results this resource instance depends on.

The result of this is trustworthy only if ResourceInstance.CheckAll returns without diagnostics. If errors are present then the result is best-effort but likely to be incomplete.

func (*ResourceInstance) StaticCheckTraversal

func (ri *ResourceInstance) StaticCheckTraversal(traversal hcl.Traversal) tfdiags.Diagnostics

StaticCheckTraversal implements exprs.Valuer.

func (*ResourceInstance) Value

func (ri *ResourceInstance) Value(ctx context.Context) (v cty.Value, diags tfdiags.Diagnostics)

Value implements exprs.Valuer.

func (*ResourceInstance) ValueSourceRange

func (ri *ResourceInstance) ValueSourceRange() *tfdiags.SourceRange

ValueSourceRange implements exprs.Valuer.

type ResourceInstanceAttributePath

type ResourceInstanceAttributePath struct {
	ResourceInstance addrs.AbsResourceInstance
	Path             cty.Path
}

ResourceInstanceAttributePath describes a (possibly empty) attribute path within a resource instance.

type ResourceInstanceGlue

type ResourceInstanceGlue interface {
	// ResultValue returns the results of whatever side-effects are happening
	// for this resource in the current phase, such as getting the "planned new
	// state" of the resource instance during the plan phase, while keeping this
	// package focused only on the general concern of evaluating expressions
	// in the configuration.
	//
	// If this returns error diagnostics then it MUST also return a suitable
	// placeholder unknown value to use when evaluating downstream expressions.
	// If there's not enough information to return anything more precise
	// then returning [cty.DynamicVal] is an acceptable last resort.
	ResultValue(ctx context.Context, configVal cty.Value, providerInst exprs.FromValue[*ProviderInstance], riDeps addrs.Set[addrs.AbsResourceInstance]) (cty.Value, tfdiags.Diagnostics)
}

ResourceInstanceGlue describes a callback API that ResourceInstance objects use to ask the caller questions about the resource instance whose answers vary based on what phase we're currently evaluating for, what provider plugins are available, or any other concern that lives outside of this package.

Real implementations of these methods are likely to block until some side-effects have occurred elsewhere, such as asking a provider to produce a planned new state. If that external work depends on information coming from any other part of this package's API then the implementation of that MUST use the mechanisms from package grapheval in order to cooperate with the self-dependency detection used by this package to prevent deadlocks.

type ResourceInstanceMark

type ResourceInstanceMark struct {
	// contains filtered or unexported fields
}

ResourceInstanceMark is a cty mark value used only internally within the evaluation system to track when a particular expression is derived from the result object for a resource instance.

func NewResourceInstanceMark

func NewResourceInstanceMark(inst *ResourceInstance) ResourceInstanceMark

NewResourceInstanceMark constructs a new ResourceInstanceMark referring to the given resource instance.

This is here so that code in other packages can describe dependencies caused by language features that this package is not aware of.

Jump to

Keyboard shortcuts

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