execgraph

package
v0.7.0 Latest Latest
Warning

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

Go to latest
Published: Sep 1, 2026 License: MPL-2.0 Imports: 24 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type AnyResultRef

type AnyResultRef interface {
	// contains filtered or unexported methods
}

AnyResultRef is a type-erased ResultRef, for data structures that only need to represent the relationships between results and not the types of those results.

type Builder

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

Builder is a helper for gradually constructing an execution graph.

Builder is not concurrency-safe, and so it's the caller's responsibility that at most one method of this type is running at a time across all goroutines.

The methods of this type each add exactly one item to the execution graph, returning an opaque reference representing its resulting value which can then be used as an argument to other methods. These opaque reference values are specific to the builder that returned them; using a reference returned by some other builder will at best cause a nonsense graph and at worse could cause panics.

func NewBuilder

func NewBuilder() *Builder

func (*Builder) ConstantDeposedKey

func (b *Builder) ConstantDeposedKey(key states.DeposedKey) ResultRef[states.DeposedKey]

ConstantDeposedKey adds a constant states.DeposedKey as a source node. The result can be used as an operand to a subsequent operation.

func (*Builder) ConstantProviderInstAddr

ConstantProviderInstAddr adds a constant addrs.AbsProviderInstanceCorrect address as a source node. The result can be used as an operand to a subsequent operation.

func (*Builder) ConstantResourceInstAddr

func (b *Builder) ConstantResourceInstAddr(addr addrs.AbsResourceInstance) ResultRef[addrs.AbsResourceInstance]

ConstantResourceInstAddr adds a constant addrs.AbsResourceInstance address as a source node. The result can be used as an operand to a subsequent operation.

func (*Builder) ConstantValue

func (b *Builder) ConstantValue(v cty.Value) ResultRef[cty.Value]

ConstantValue adds a constant cty.Value as a source node. The result can be used as an operand to a subsequent operation.

func (*Builder) DataRead

func (*Builder) Finish

func (b *Builder) Finish() *Graph

Finish returns the graph that has been built, which is then immutable.

After calling this function the Builder is invalid and must not be used anymore.

func (*Builder) ManagedAlreadyDeposed

func (b *Builder) ManagedAlreadyDeposed(
	instAddr ResultRef[addrs.AbsResourceInstance],
	deposedKey ResultRef[states.DeposedKey],
) ResourceInstanceResultRef

func (*Builder) ManagedApply

ManagedApply registers an operation to apply a "final plan" for a managed resource instance object.

The finalPlan argument should typically be something returned by a previous call to Builder.ManagedFinalPlan with the same provider client.

fallbackObj is usually a NilResultRef, but should be set for the "create" leg of a "create then destroy" replace operation to be the result of a call to Builder.ManagedPerformDepose so that the deposed object can be restored to current if the create call completely fails to create a new object.

func (*Builder) ManagedChangeAddr

func (b *Builder) ManagedChangeAddr(
	currentObj ResourceInstanceResultRef,
	newAddr ResultRef[addrs.AbsResourceInstance],
) ResourceInstanceResultRef

func (*Builder) ManagedFinalPlan

ManagedFinalPlan registers an operation to decide the "final plan" for a managed resource instance object, which may or may not be "desired".

If the object is not "desired" then the desiredInst result is a nil pointer. The underlying provider API represents that situation by setting the "configuration value" to null.

Similarly, if the object did not previously exist but is now desired then the priorState result is a nil pointer, which should be represented in the provider API by setting the prior state value to null.

If the planning phase learned that the provider needs to handle a change as a "replace" then in the execution graph there should be two separate "final plan" and "apply changes" chains, where one has a nil desiredInst and the other has a nil priorState. desiredInst and priorState should only both be set when handling an in-place update.

func (*Builder) ManagedPerformDepose

func (b *Builder) ManagedPerformDepose(
	currentObj ResourceInstanceResultRef,
	finalDeletePlan ResultRef[*exec.ManagedResourceObjectFinalPlan],
	waitFor AnyResultRef,
) ResourceInstanceResultRef

func (*Builder) ManagedPrepareDepose

ManagedPrepareDepose performs the first half of the work to "depose" a resource instance object as part of a create-before-destroy replace operation.

The final plan given as input must be a plan to destroy a "current" object. The result is an equivalent plan whose only difference is that it's set up to destroy the deposed object which has the given deposed key.

The result of this operation should then be sent to both Builder.ManagedPerformDepose and Builder.ManagedApply as part of the overall subgraph handling the replace operation.

This operation is an intrinsic, meaning that its behavior lives directly in the execution graph runner rather than being delegated to an external exec.Operations implementation.

func (*Builder) MutableWaiter

func (b *Builder) MutableWaiter() (AnyResultRef, func(AnyResultRef))

MutableWaiter is like Builder.Waiter except that the returned waiter initially has no dependencies and then dependencies can be added to it separately by calling the returned function.

This is intended for situations where an item with dependencies must be added to the graph before its dependencies are known, and then the caller gradually discovers all of the dependencies in later work.

The registration function is not concurrency safe, so callers are responsible for ensuring that there is only at most one call to each returned distinct registration function across all goroutines.

func (*Builder) ResourceInstanceCurrentMeta

ResourceInstanceCurrentMeta asks the evaluator for the configured metadata for the current object of the identified resource instance and then combines it with the prior state of that object (if any) to produce the effective metadata for that resource instance object.

For objects that exist in the prior state, set "prior" to the result of a call to Builder.ResourceInstancePrior. Otherwise leave it set to nil to indicate that there is no prior state available.

func (*Builder) ResourceInstanceDesired

func (b *Builder) ResourceInstanceDesired(
	meta ResultRef[*exec.ResourceInstanceObjectMeta],
) ResultRef[*eval.DesiredResourceInstance]

ResourceInstanceDesired asks the evaluator for the desired state of the resource instance object whose metadata is provided.

This operation automatically blocks awaiting the results of any upstream resource instances that the requested instance's configuration depends on, and prevents execution of anything that depends on its result if there are any evaluation errors, even if those errors originate upstream in one of the configuration's dependencies and thus would get reported separately by another return path.

Only current (i.e. not "deposed") objects can be "desired", so this operation must not be sent a result from Builder.ManagedDeposedMeta.

func (*Builder) ResourceInstanceFinalStateResult

func (b *Builder) ResourceInstanceFinalStateResult(addr addrs.AbsResourceInstance) AnyResultRef

ResourceInstanceFinalStateResult returns the result reference for the given resource instance that should previously have been registered using Builder.SetResourceInstanceFinalStateResult.

The return type is AnyResultRef because this is intended for use as an argument to Builder.Waiter or to a function returned by Builder.MutableWaiter when explicitly representing the dependencies between different resource and provider instances. The actual final state result for the source instance travels indirectly through the evaluator rather than directly within the execution graph.

This function panics if a result reference for the given resource instance was not previously registered, because that suggests a bug elsewhere in the system that caused the construction of subgraphs for different resource instances to happen in the wrong order.

func (*Builder) ResourceInstancePrior

func (b *Builder) ResourceInstancePrior(
	addr ResultRef[addrs.AbsResourceInstance],
) ResourceInstanceResultRef

ResourceInstancePrior returns the prior state of the resource instance that has the given address.

If the instance has no current object in the prior state then this returns an object whose value is null, but not that such an object is not an acceptable input to all operations that accept resource instance results, and we expect that the planning engine would just skip including this operation completely for any resource instance which is known during planning to have no prior state because it's being created.

Because this operation just reads static values directly from the state, it does not automatically block for the completion of changes for other resource instances recorded as dependencies in the prior state. Instead we expect that the planning engine would record those as explicit dependencies on a subsequent call to Builder.ManagedApply or Builder.ManagedPerformDepose so that we constrain the ordering only of the externally-visible changes and not of internal-only work.

func (*Builder) SetResourceInstanceFinalStateResult

func (b *Builder) SetResourceInstanceFinalStateResult(addr addrs.AbsResourceInstance, result ResourceInstanceResultRef)

SetResourceInstanceFinalStateResult records which result should be treated as the "final state" for the given resource instance, for purposes such as propagating the result value back into the evaluation system to allow downstream expressions to derive from it.

Only one call is allowed per distinct addrs.AbsResourceInstance value. If two callers try to register for the same address then the second call will panic.

func (*Builder) Waiter

func (b *Builder) Waiter(dependencies ...AnyResultRef) AnyResultRef

Waiter creates a "fan-in" node where a single result depends on the completion of an arbitrary number of other results.

The values produced by the dependencies are discarded; this only creates a "must happen after" relationship with the given dependencies.

type CompiledGraph

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

func (*CompiledGraph) Execute

Execute performs all of the work described in the execution graph in a suitable order, returning any diagnostics that operations might return along the way.

If there are resource instance operations in the graph (which is typical for any useful execution graph) then typically the evaluation system should be running concurrently and be taking resource instance results from calls to CompiledGraph.ResourceInstanceValue so that the graph execution and evaluation system can collaborate to drive the execution process forward together.

func (*CompiledGraph) ResourceInstanceValue

func (c *CompiledGraph) ResourceInstanceValue(ctx context.Context, addr addrs.AbsResourceInstance) cty.Value

ResourceInstanceValue returns the final resource instance value corrsponding with the given address. It expects that for any address requested, the corresponding resource graph node has already executed and recorded a value.

Calls to this method should run concurrently with a call to CompiledGraph.Execute because otherwise the operations that generate the final state for resource instances will not run and thus this will block indefinitely waiting for results that will never arrive.

If the resource's value is not available for any reason, a cty.DynamicVal will be returned, marked with ResourceInstanceDependencyMissingMark. This allows the "unplanned reference" mark to propogate through the rest of the system and be handled in locations where it can generate a detailed error diagnostic.

type Graph

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

func UnmarshalGraph

func UnmarshalGraph(src []byte) (*Graph, error)

UnmarshalGraph takes some bytes previously returned by Graph.Marshal and returns a graph that is functionally-equivalent to (but not necessarily identical to) the original graph.

Because this is working with data loaded from outside OpenTofu it returns errors when encountering problems, but if it fails when unmarshaling an unmodified result from Graph.Marshal then that represents a bug in either this or that function: they should always be updated together so they are implementing the same file format.

func (*Graph) Compile

func (g *Graph) Compile(ops exec.Operations) (*CompiledGraph, tfdiags.Diagnostics)

Compile produces a compiled version of the graph which will, once executed, use the given arguments to interact with other parts of the broader system.

The Graph.Compile function is guaranteed not call any methods on the given exec.Operations during compilation: it will be used only once the returned CompiledGraph is executed. In particular this means that it's okay for there to be a cyclic dependency between the Operations and the CompiledGraph so that the caller can use CompiledGraph.ResourceInstanceValue to satisfy requests from the evaluation system for final resource instance values, as long as the Operations object is updated with a pointer to the returned CompiledGraph object before executing the graph.

func (*Graph) DebugRepr

func (g *Graph) DebugRepr() string

DebugRepr returns a relatively-concise string representation of the graph which includes all of the registered operations and their operands, along with any constant values they rely on.

The result is intended primarily for human consumption when testing or debugging. It's not an executable or parseable representation and details about how it's formatted might change over time.

func (*Graph) Marshal

func (g *Graph) Marshal() []byte

Marshal produces an opaque byte slice representing the given graph, which can then be passed to UnmarshalGraph to produce a functionally-equivalent graph.

func (*Graph) PromiseDrivenRequestInfo

func (g *Graph) PromiseDrivenRequestInfo(key PromiseDrivenResultKey) grapheval.RequestInfo

PromiseDrivenRequestInfo is part of our somewhat-roundabout means of gathering additional context about promise-based requests only when we enounter an error that makes it worth gathering this information.

Given a PromiseDrivenResultKey previously advertised to a RequestTrackerWithNotify implementation used with CompiledGraph.Execute on a compiled version of the same graph, this returns a grapheval.RequestInfo value summarizing what that request was intending to achieve in terms that are suitable to include in an error message that someone will presmuably submit in an OpenTofu bug report, because promise-related errors should only crop up during processing of incorrectly-constructed execution graphs.

type PromiseDrivenResultKey

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

PromiseDrivenResultKey is an opaque representation of a ResultRef whose result is produced using grapheval and workgraph mechanisms, which we use in [RequsetTrackerWithNotify] to give a caller just enough information to selectively request more detail from a source graph only if necessary to report an error.

type RequestTrackerWithNotify

type RequestTrackerWithNotify interface {
	grapheval.RequestTracker
	TrackExecutionGraphRequest(ctx context.Context, key PromiseDrivenResultKey, reqID workgraph.RequestID)
}

RequestTrackerWithNotify is an optional extension of grapheval.RequestTracker which must be implemented by the request tracker passed in CompiledGraph.Execute's context.Context argument if the request tracker needs to be aware of workgraph requests made as part of resolving results during execution graph processing.

If the given context has no request tracker at all, or if the request tracker does not implement this extension interface, then no notifications will be delivered but execution is otherwise unaffected.

type ResourceInstanceDependencyMissingMark

type ResourceInstanceDependencyMissingMark struct {
	Target string // addrs.AbsResourceInstance
}

type ResourceInstanceResultRef

type ResourceInstanceResultRef = ResultRef[*exec.ResourceInstanceObject]

ResourceInstanceResultRef is an alias for the ResultRef type used when reporting the final result of applying changes to a resource instance object.

We give this its own name just because this particular result type tends to be named in function signatures elsewhere in the system and the simple name is (subjectively) easier to read than the generic name.

type ResultRef

type ResultRef[T any] interface {
	AnyResultRef
	// contains filtered or unexported methods
}

ResultRef represents a result of type T that will be produced by some other operation that is opaque to the recipients of the result.

func NilResultRef

func NilResultRef[T any]() ResultRef[T]

NilResultRef returns a special result ref which just always produces the zero value of type T, without doing any other work or referring to any other data.

This should typically only be used for types whose zero value is considered to be the "nil" value for the type, such as pointer types, since otherwise the recipient cannot distinguish it from a valid result that just happens to be the zero value.

Directories

Path Synopsis
Package execgraphproto contains just the protocol buffers models we use for marshaling and unmarshaling execution graphs.
Package execgraphproto contains just the protocol buffers models we use for marshaling and unmarshaling execution graphs.

Jump to

Keyboard shortcuts

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