plans

package
v1.0.1 Latest Latest
Warning

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

Go to latest
Published: Oct 24, 2024 License: MPL-2.0 Imports: 11 Imported by: 0

Documentation

Overview

Package plans contains the types that are used to represent OpenTofu plans.

A plan describes a set of changes that OpenTofu will make to update remote objects to match with changes to the configuration.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Action

type Action rune
const (
	NoOp             Action = 0
	Create           Action = '+'
	Read             Action = '←'
	Update           Action = '~'
	DeleteThenCreate Action = '∓'
	CreateThenDelete Action = '±'
	Delete           Action = '-'
	Forget           Action = '.'
)

func (Action) IsReplace

func (a Action) IsReplace() bool

IsReplace returns true if the action is one of the two actions that represents replacing an existing object with a new object: DeleteThenCreate or CreateThenDelete.

func (Action) String

func (i Action) String() string

type Backend

type Backend struct {
	// Type is the type of backend that the plan will apply against.
	Type string

	// Config is the configuration of the backend, whose schema is decided by
	// the backend Type.
	Config DynamicValue

	// Workspace is the name of the workspace that was active when the plan
	// was created. It is illegal to apply a plan created for one workspace
	// to the state of another workspace.
	// (This constraint is already enforced by the statefile lineage mechanism,
	// but storing this explicitly allows us to return a better error message
	// in the situation where the user has the wrong workspace selected.)
	Workspace string
}

Backend represents the backend-related configuration and other data as it existed when a plan was created.

func NewBackend

func NewBackend(typeName string, config cty.Value, configSchema *configschema.Block, workspaceName string) (*Backend, error)

type Change

type Change struct {
	// Action defines what kind of change is being made.
	Action Action

	// Interpretation of Before and After depend on Action:
	//
	//     NoOp     Before and After are the same, unchanged value
	//     Create   Before is nil, and After is the expected value after create.
	//     Read     Before is any prior value (nil if no prior), and After is the
	//              value that was or will be read.
	//     Update   Before is the value prior to update, and After is the expected
	//              value after update.
	//     Replace  As with Update.
	//     Delete   Before is the value prior to delete, and After is always nil.
	//
	// Unknown values may appear anywhere within the Before and After values,
	// either as the values themselves or as nested elements within known
	// collections/structures.
	Before, After cty.Value

	// Importing is present if the resource is being imported as part of this
	// change.
	//
	// Use the simple presence of this field to detect if a ChangeSrc is to be
	// imported, the contents of this structure may be modified going forward.
	Importing *Importing

	// GeneratedConfig contains any HCL config generated for this resource
	// during planning, as a string. If GeneratedConfig is populated, Importing
	// should be true. However, not all Importing changes contain generated
	// config.
	GeneratedConfig string
}

Change describes a single change with a given action.

func (*Change) Encode

func (c *Change) Encode(ty cty.Type) (*ChangeSrc, error)

Encode produces a variant of the reciever that has its change values serialized so it can be written to a plan file. Pass the type constraint that the values are expected to conform to; to properly decode the values later an identical type constraint must be provided at that time.

Where a Change is embedded in some other struct, it's generally better to call the corresponding Encode method of that struct rather than working directly with its embedded Change.

type ChangeSrc

type ChangeSrc struct {
	// Action defines what kind of change is being made.
	Action Action

	// Before and After correspond to the fields of the same name in Change,
	// but have not yet been decoded from the serialized value used for
	// storage.
	Before, After DynamicValue

	// BeforeValMarks and AfterValMarks are stored path+mark combinations
	// that might be discovered when encoding a change. Marks are removed
	// to enable encoding (marked values cannot be marshalled), and so storing
	// the path+mark combinations allow us to re-mark the value later
	// when, for example, displaying the diff to the UI.
	BeforeValMarks, AfterValMarks []cty.PathValueMarks

	// Importing is present if the resource is being imported as part of this
	// change.
	//
	// Use the simple presence of this field to detect if a ChangeSrc is to be
	// imported, the contents of this structure may be modified going forward.
	Importing *ImportingSrc

	// GeneratedConfig contains any HCL config generated for this resource
	// during planning, as a string. If GeneratedConfig is populated, Importing
	// should be true. However, not all Importing changes contain generated
	// config.
	GeneratedConfig string
}

ChangeSrc is a not-yet-decoded Change.

func (*ChangeSrc) Decode

func (cs *ChangeSrc) Decode(ty cty.Type) (*Change, error)

Decode unmarshals the raw representations of the before and after values to produce a Change object. Pass the type constraint that the result must conform to.

Where a ChangeSrc is embedded in some other struct, it's generally better to call the corresponding Decode method of that struct rather than working directly with its embedded Change.

type Changes

type Changes struct {
	// Resources tracks planned changes to resource instance objects.
	Resources []*ResourceInstanceChangeSrc

	// Outputs tracks planned changes output values.
	//
	// Note that although an in-memory plan contains planned changes for
	// outputs throughout the configuration, a plan serialized
	// to disk retains only the root outputs because they are
	// externally-visible, while other outputs are implementation details and
	// can be easily re-calculated during the apply phase. Therefore only root
	// module outputs will survive a round-trip through a plan file.
	Outputs []*OutputChangeSrc
}

Changes describes various actions that OpenTofu will attempt to take if the corresponding plan is applied.

A Changes object can be rendered into a visual diff (by the caller, using code in another package) for display to the user.

func NewChanges

func NewChanges() *Changes

NewChanges returns a valid Changes object that describes no changes.

func (*Changes) Empty

func (c *Changes) Empty() bool

func (*Changes) InstancesForAbsResource

func (c *Changes) InstancesForAbsResource(addr addrs.AbsResource) []*ResourceInstanceChangeSrc

InstancesForAbsResource returns the planned change for the current objects of the resource instances of the given address, if any. Returns nil if no changes are planned.

func (*Changes) InstancesForConfigResource

func (c *Changes) InstancesForConfigResource(addr addrs.ConfigResource) []*ResourceInstanceChangeSrc

InstancesForConfigResource returns the planned change for the current objects of the resource instances of the given address, if any. Returns nil if no changes are planned.

func (*Changes) OutputValue

func (c *Changes) OutputValue(addr addrs.AbsOutputValue) *OutputChangeSrc

OutputValue returns the planned change for the output value with the

given address, if any. Returns nil if no change is planned.

func (*Changes) OutputValues

func (c *Changes) OutputValues(parent addrs.ModuleInstance, module addrs.ModuleCall) []*OutputChangeSrc

OutputValues returns planned changes for all outputs for all module instances that reside in the parent path. Returns nil if no changes are planned.

func (*Changes) PlannedState

func (c *Changes) PlannedState(prior *states.State) (*states.State, error)

PlannedState merges the set of changes described by the receiver into the given prior state to produce the planned result state.

The result is an approximation of the state as it would exist after applying these changes, omitting any values that cannot be determined until the changes are actually applied.

func (*Changes) ResourceInstance

func (c *Changes) ResourceInstance(addr addrs.AbsResourceInstance) *ResourceInstanceChangeSrc

ResourceInstance returns the planned change for the current object of the resource instance of the given address, if any. Returns nil if no change is planned.

func (*Changes) ResourceInstanceDeposed

func (c *Changes) ResourceInstanceDeposed(addr addrs.AbsResourceInstance, key states.DeposedKey) *ResourceInstanceChangeSrc

ResourceInstanceDeposed returns the plan change of a deposed object of the resource instance of the given address, if any. Returns nil if no change is planned.

func (*Changes) RootOutputValues

func (c *Changes) RootOutputValues() []*OutputChangeSrc

RootOutputValues returns planned changes for all outputs of the root module.

func (*Changes) SyncWrapper

func (c *Changes) SyncWrapper() *ChangesSync

SyncWrapper returns a wrapper object around the receiver that can be used to make certain changes to the receiver in a concurrency-safe way, as long as all callers share the same wrapper object.

type ChangesSync

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

ChangesSync is a wrapper around a Changes that provides a concurrency-safe interface to insert new changes and retrieve copies of existing changes.

Each ChangesSync is independent of all others, so all concurrent writers to a particular Changes must share a single ChangesSync. Behavior is undefined if any other caller makes changes to the underlying Changes object or its nested objects concurrently with any of the methods of a particular ChangesSync.

func (*ChangesSync) AppendOutputChange

func (cs *ChangesSync) AppendOutputChange(changeSrc *OutputChangeSrc)

AppendOutputChange records the given output value change in the set of planned value changes.

The caller must ensure that there are no concurrent writes to the given change while this method is running, but it is safe to resume mutating it after this method returns without affecting the saved change.

func (*ChangesSync) AppendResourceInstanceChange

func (cs *ChangesSync) AppendResourceInstanceChange(changeSrc *ResourceInstanceChangeSrc)

AppendResourceInstanceChange records the given resource instance change in the set of planned resource changes.

The caller must ensure that there are no concurrent writes to the given change while this method is running, but it is safe to resume mutating it after this method returns without affecting the saved change.

func (*ChangesSync) GetChangesForAbsResource

func (cs *ChangesSync) GetChangesForAbsResource(addr addrs.AbsResource) []*ResourceInstanceChangeSrc

GetChangesForAbsResource searches the set of resource instance changes and returns all changes related to a given configuration address.

If no such changes exist, nil is returned.

The returned objects are a deep copy of the change recorded in the plan, so callers may mutate them although it's generally better (less confusing) to treat planned changes as immutable after they've been initially constructed.

func (*ChangesSync) GetChangesForConfigResource

func (cs *ChangesSync) GetChangesForConfigResource(addr addrs.ConfigResource) []*ResourceInstanceChangeSrc

GetChangesForConfigResource searches the set of resource instance changes and returns all changes related to a given configuration address. This is be used to find possible changes related to a configuration reference.

If no such changes exist, nil is returned.

The returned objects are a deep copy of the change recorded in the plan, so callers may mutate them although it's generally better (less confusing) to treat planned changes as immutable after they've been initially constructed.

func (*ChangesSync) GetOutputChange

func (cs *ChangesSync) GetOutputChange(addr addrs.AbsOutputValue) *OutputChangeSrc

GetOutputChange searches the set of output value changes for one matching the given address, returning it if it exists.

If no such change exists, nil is returned.

The returned object is a deep copy of the change recorded in the plan, so callers may mutate it although it's generally better (less confusing) to treat planned changes as immutable after they've been initially constructed.

func (*ChangesSync) GetOutputChanges

func (cs *ChangesSync) GetOutputChanges(parent addrs.ModuleInstance, module addrs.ModuleCall) []*OutputChangeSrc

GetOutputChanges searches the set of output changes for any that reside in module instances beneath the given module. If no changes exist, nil is returned.

The returned objects are a deep copy of the change recorded in the plan, so callers may mutate them although it's generally better (less confusing) to treat planned changes as immutable after they've been initially constructed.

func (*ChangesSync) GetResourceInstanceChange

func (cs *ChangesSync) GetResourceInstanceChange(addr addrs.AbsResourceInstance, gen states.Generation) *ResourceInstanceChangeSrc

GetResourceInstanceChange searches the set of resource instance changes for one matching the given address and generation, returning it if it exists.

If no such change exists, nil is returned.

The returned object is a deep copy of the change recorded in the plan, so callers may mutate it although it's generally better (less confusing) to treat planned changes as immutable after they've been initially constructed.

func (*ChangesSync) GetRootOutputChanges

func (cs *ChangesSync) GetRootOutputChanges() []*OutputChangeSrc

GetRootOutputChanges searches the set of output changes for any that reside the root module. If no such changes exist, nil is returned.

The returned objects are a deep copy of the change recorded in the plan, so callers may mutate them although it's generally better (less confusing) to treat planned changes as immutable after they've been initially constructed.

func (*ChangesSync) RemoveOutputChange

func (cs *ChangesSync) RemoveOutputChange(addr addrs.AbsOutputValue)

RemoveOutputChange searches the set of output value changes for one matching the given address, and removes it from the set if it exists.

func (*ChangesSync) RemoveResourceInstanceChange

func (cs *ChangesSync) RemoveResourceInstanceChange(addr addrs.AbsResourceInstance, gen states.Generation)

RemoveResourceInstanceChange searches the set of resource instance changes for one matching the given address and generation, and removes it from the set if it exists.

type DynamicValue

type DynamicValue []byte

DynamicValue is the representation in the plan of a value whose type cannot be determined at compile time, such as because it comes from a schema defined in a plugin.

This type is used as an indirection so that the overall plan structure can be decoded without schema available, and then the dynamic values accessed at a later time once the appropriate schema has been determined.

Internally, DynamicValue is a serialized version of a cty.Value created against a particular type constraint. Callers should not access directly the serialized form, whose format may change in future. Values of this type must always be created by calling NewDynamicValue.

The zero value of DynamicValue is nil, and represents the absence of a value within the Go type system. This is distinct from a cty.NullVal result, which represents the absence of a value within the cty type system.

func NewDynamicValue

func NewDynamicValue(val cty.Value, ty cty.Type) (DynamicValue, error)

NewDynamicValue creates a DynamicValue by serializing the given value against the given type constraint. The value must conform to the type constraint, or the result is undefined.

If the value to be encoded has no predefined schema (for example, for module output values and input variables), set the type constraint to cty.DynamicPseudoType in order to save type information as part of the value, and then also pass cty.DynamicPseudoType to method Decode to recover the original value.

cty.NilVal can be used to represent the absence of a value, but callers must be careful to distinguish values that are absent at the Go layer (cty.NilVal) vs. values that are absent at the cty layer (cty.NullVal results).

func (DynamicValue) Copy

func (v DynamicValue) Copy() DynamicValue

Copy produces a copy of the receiver with a distinct backing array.

func (DynamicValue) Decode

func (v DynamicValue) Decode(ty cty.Type) (cty.Value, error)

Decode retrieves the effective value from the receiever by interpreting the serialized form against the given type constraint. For correct results, the type constraint must match (or be consistent with) the one that was used to create the receiver.

A nil DynamicValue decodes to cty.NilVal, which is not a valid value and instead represents the absense of a value.

func (DynamicValue) ImpliedType

func (v DynamicValue) ImpliedType() (cty.Type, error)

ImpliedType returns the type implied by the serialized structure of the receiving value.

This will not necessarily be exactly the type that was given when the value was encoded, and in particular must not be used for values that were encoded with their static type given as cty.DynamicPseudoType. It is however safe to use this method for values that were encoded using their runtime type as the conforming type, with the result being semantically equivalent but with all lists and sets represented as tuples, and maps as objects, due to ambiguities of the serialization.

type Importing

type Importing struct {
	// ID is the original ID of the imported resource.
	ID string
}

Importing is the part of a ChangeSrc that describes the embedded import action.

The fields in here are subject to change, so downstream consumers should be prepared for backwards compatibility in case the contents changes.

type ImportingSrc

type ImportingSrc struct {
	// ID is the original ID of the imported resource.
	ID string
}

ImportingSrc is the part of a ChangeSrc that describes the embedded import action.

The fields in here are subject to change, so downstream consumers should be prepared for backwards compatibility in case the contents changes.

type Mode

type Mode rune

Mode represents the various mutually-exclusive modes for creating a plan.

const (
	// NormalMode is the default planning mode, which aims to synchronize the
	// prior state with remote objects and plan a set of actions intended to
	// make those remote objects better match the current configuration.
	NormalMode Mode = 0

	// DestroyMode is a special planning mode for situations where the goal
	// is to destroy all remote objects that are bound to instances in the
	// prior state, even if the configuration for those instances is still
	// present.
	//
	// This mode corresponds with the "-destroy" option to "tofu plan",
	// and with the plan created by the "tofu destroy" command.
	DestroyMode Mode = 'D'

	// RefreshOnlyMode is a special planning mode which only performs the
	// synchronization of prior state with remote objects, and skips any
	// effort to generate any change actions for resource instances even if
	// the configuration has changed relative to the state.
	//
	// This mode corresponds with the "-refresh-only" option to
	// "tofu plan".
	RefreshOnlyMode Mode = 'R'
)

func (Mode) String

func (i Mode) String() string

type OutputChange

type OutputChange struct {
	// Addr is the absolute address of the output value that the change
	// will apply to.
	Addr addrs.AbsOutputValue

	// Change is an embedded description of the change.
	//
	// For output value changes, the type constraint for the DynamicValue
	// instances is always cty.DynamicPseudoType.
	Change

	// Sensitive, if true, indicates that either the old or new value in the
	// change is sensitive and so a rendered version of the plan in the UI
	// should elide the actual values while still indicating the action of the
	// change.
	Sensitive bool
}

OutputChange describes a change to an output value.

func (*OutputChange) Encode

func (oc *OutputChange) Encode() (*OutputChangeSrc, error)

Encode produces a variant of the reciever that has its change values serialized so it can be written to a plan file.

type OutputChangeSrc

type OutputChangeSrc struct {
	// Addr is the absolute address of the output value that the change
	// will apply to.
	Addr addrs.AbsOutputValue

	// ChangeSrc is an embedded description of the not-yet-decoded change.
	//
	// For output value changes, the type constraint for the DynamicValue
	// instances is always cty.DynamicPseudoType.
	ChangeSrc

	// Sensitive, if true, indicates that either the old or new value in the
	// change is sensitive and so a rendered version of the plan in the UI
	// should elide the actual values while still indicating the action of the
	// change.
	Sensitive bool
}

OutputChangeSrc describes a change to an output value.

func (*OutputChangeSrc) Decode

func (ocs *OutputChangeSrc) Decode() (*OutputChange, error)

Decode unmarshals the raw representation of the output value being changed.

func (*OutputChangeSrc) DeepCopy

func (ocs *OutputChangeSrc) DeepCopy() *OutputChangeSrc

DeepCopy creates a copy of the receiver where any pointers to nested mutable values are also copied, thus ensuring that future mutations of the receiver will not affect the copy.

Some types used within a resource change are immutable by convention even though the Go language allows them to be mutated, such as the types from the addrs package. These are _not_ copied by this method, under the assumption that callers will behave themselves.

type Plan

type Plan struct {
	// Mode is the mode under which this plan was created.
	//
	// This is only recorded to allow for UI differences when presenting plans
	// to the end-user, and so it must not be used to influence apply-time
	// behavior. The actions during apply must be described entirely by
	// the Changes field, regardless of how the plan was created.
	//
	// FIXME: destroy operations still rely on DestroyMode being set, because
	// there is no other source of this information in the plan. New behavior
	// should not be added based on this flag, and changing the flag should be
	// checked carefully against existing destroy behaviors.
	UIMode Mode

	VariableValues    map[string]DynamicValue
	Changes           *Changes
	DriftedResources  []*ResourceInstanceChangeSrc
	TargetAddrs       []addrs.Targetable
	ForceReplaceAddrs []addrs.AbsResourceInstance
	Backend           Backend

	// Errored is true if the Changes information is incomplete because
	// the planning operation failed. An errored plan cannot be applied,
	// but can be cautiously inspected for debugging purposes.
	Errored bool

	// Checks captures a snapshot of the (probably-incomplete) check results
	// at the end of the planning process.
	//
	// If this plan is applyable (that is, if the planning process completed
	// without errors) then the set of checks here should be complete even
	// though some of them will likely have StatusUnknown where the check
	// condition depends on values we won't know until the apply step.
	Checks *states.CheckResults

	// RelevantAttributes is a set of resource instance addresses and
	// attributes that are either directly affected by proposed changes or may
	// have indirectly contributed to them via references in expressions.
	//
	// This is the result of a heuristic and is intended only as a hint to
	// the UI layer in case it wants to emphasize or de-emphasize certain
	// resources. Don't use this to drive any non-cosmetic behavior, especially
	// including anything that would be subject to compatibility constraints.
	RelevantAttributes []globalref.ResourceAttr

	// PrevRunState and PriorState both describe the situation that the plan
	// was derived from:
	//
	// PrevRunState is a representation of the outcome of the previous
	// OpenTofu operation, without any updates from the remote system but
	// potentially including some changes that resulted from state upgrade
	// actions.
	//
	// PriorState is a representation of the current state of remote objects,
	// which will differ from PrevRunState if the "refresh" step returned
	// different data, which might reflect drift.
	//
	// PriorState is the main snapshot we use for actions during apply.
	// PrevRunState is only here so that we can diff PriorState against it in
	// order to report to the user any out-of-band changes we've detected.
	PrevRunState *states.State
	PriorState   *states.State

	// PlannedState is the temporary planned state that was created during the
	// graph walk that generated this plan.
	//
	// This is required by the testing framework when evaluating run blocks
	// executing in plan mode. The graph updates the state with certain values
	// that are difficult to retrieve later, such as local values that reference
	// updated resources. It is easier to build the testing scope with access
	// to same temporary state the plan used/built.
	//
	// This is never recorded outside of OpenTofu. It is not written into the
	// binary plan file, and it is not written into the JSON structured outputs.
	// The testing framework never writes the plans out but holds everything in
	// memory as it executes, so there is no need to add any kind of
	// serialization for this field. This does mean that you shouldn't rely on
	// this field existing unless you have just generated the plan.
	PlannedState *states.State

	// ExternalReferences are references that are being made to resources within
	// the plan from external sources. As with PlannedState this is used by the
	// OpenTofu testing framework, and so isn't written into any external
	// representation of the plan.
	ExternalReferences []*addrs.Reference

	// Timestamp is the record of truth for when the plan happened.
	Timestamp time.Time
}

Plan is the top-level type representing a planned set of changes.

A plan is a summary of the set of changes required to move from a current state to a goal state derived from configuration. The described changes are not applied directly, but contain an approximation of the final result that will be completed during apply by resolving any values that cannot be predicted.

A plan must always be accompanied by the configuration it was built from, since the plan does not itself include all of the information required to make the changes indicated.

func (*Plan) CanApply

func (p *Plan) CanApply() bool

CanApply returns true if and only if the recieving plan includes content that would make sense to apply. If it returns false, the plan operation should indicate that there's nothing to do and OpenTofu should exit without prompting the user to confirm the changes.

This function represents our main business logic for making the decision about whether a given plan represents meaningful "changes", and so its exact definition may change over time; the intent is just to centralize the rules for that rather than duplicating different versions of it at various locations in the UI code.

func (*Plan) ProviderAddrs

func (p *Plan) ProviderAddrs() []addrs.AbsProviderConfig

ProviderAddrs returns a list of all of the provider configuration addresses referenced throughout the receiving plan.

The result is de-duplicated so that each distinct address appears only once.

type Quality

type Quality int

Quality represents facts about the nature of a plan that might be relevant when rendering it, like whether it errored or contains no changes. A plan can have multiple qualities.

const (
	// Errored plans did not successfully complete, and cannot be applied.
	Errored Quality = iota
	// NoChanges plans won't result in any actions on infrastructure, or any
	// semantically meaningful updates to state. They can sometimes still affect
	// the format of state if applied.
	NoChanges
)

func (Quality) String

func (i Quality) String() string

type ResourceInstanceChange

type ResourceInstanceChange struct {
	// Addr is the absolute address of the resource instance that the change
	// will apply to.
	Addr addrs.AbsResourceInstance

	// PrevRunAddr is the absolute address that this resource instance had at
	// the conclusion of a previous run.
	//
	// This will typically be the same as Addr, but can be different if the
	// previous resource instance was subject to a "moved" block that we
	// handled in the process of creating this plan.
	//
	// For the initial creation of a resource instance there isn't really any
	// meaningful "previous run address", but PrevRunAddr will still be set
	// equal to Addr in that case in order to simplify logic elsewhere which
	// aims to detect and react to the movement of instances between addresses.
	PrevRunAddr addrs.AbsResourceInstance

	// DeposedKey is the identifier for a deposed object associated with the
	// given instance, or states.NotDeposed if this change applies to the
	// current object.
	//
	// A Replace change for a resource with create_before_destroy set will
	// create a new DeposedKey temporarily during replacement. In that case,
	// DeposedKey in the plan is always states.NotDeposed, representing that
	// the current object is being replaced with the deposed.
	DeposedKey states.DeposedKey

	// Provider is the address of the provider configuration that was used
	// to plan this change, and thus the configuration that must also be
	// used to apply it.
	ProviderAddr addrs.AbsProviderConfig

	// Change is an embedded description of the change.
	Change

	// ActionReason is an optional extra indication of why we chose the
	// action recorded in Change.Action for this particular resource instance.
	//
	// This is an approximate mechanism only for the purpose of explaining the
	// plan to end-users in the UI and is not to be used for any
	// decision-making during the apply step; if apply behavior needs to vary
	// depending on the "action reason" then the information for that decision
	// must be recorded more precisely elsewhere for that purpose.
	//
	// Sometimes there might be more than one reason for choosing a particular
	// action. In that case, it's up to the codepath making that decision to
	// decide which value would provide the most relevant explanation to the
	// end-user and return that. It's not a goal of this field to represent
	// fine details about the planning process.
	ActionReason ResourceInstanceChangeActionReason

	// RequiredReplace is a set of paths that caused the change action to be
	// Replace rather than Update. Always nil if the change action is not
	// Replace.
	//
	// This is retained only for UI-plan-rendering purposes and so it does not
	// currently survive a round-trip through a saved plan file.
	RequiredReplace cty.PathSet

	// Private allows a provider to stash any extra data that is opaque to
	// OpenTofu that relates to this change. OpenTofu will save this
	// byte-for-byte and return it to the provider in the apply call.
	Private []byte
}

ResourceInstanceChange describes a change to a particular resource instance object.

func (*ResourceInstanceChange) Encode

Encode produces a variant of the reciever that has its change values serialized so it can be written to a plan file. Pass the implied type of the corresponding resource type schema for correct operation.

func (*ResourceInstanceChange) Moved

func (rc *ResourceInstanceChange) Moved() bool

func (*ResourceInstanceChange) Simplify

func (rc *ResourceInstanceChange) Simplify(destroying bool) *ResourceInstanceChange

Simplify will, where possible, produce a change with a simpler action than the receiever given a flag indicating whether the caller is dealing with a normal apply or a destroy. This flag deals with the fact that OpenTofu Core uses a specialized graph node type for destroying; only that specialized node should set "destroying" to true.

The following table shows the simplification behavior:

Action    Destroying?   New Action
--------+-------------+-----------
Create    true          NoOp
Delete    false         NoOp
Replace   true          Delete
Replace   false         Create

For any combination not in the above table, the Simplify just returns the receiver as-is.

type ResourceInstanceChangeActionReason

type ResourceInstanceChangeActionReason rune

ResourceInstanceChangeActionReason allows for some extra user-facing reasoning for why a particular change action was chosen for a particular resource instance.

This only represents sufficient detail to give a suitable explanation to an end-user, and mustn't be used for any real decision-making during the apply step.

const (
	// In most cases there's no special reason for choosing a particular
	// action, which is represented by ResourceInstanceChangeNoReason.
	ResourceInstanceChangeNoReason ResourceInstanceChangeActionReason = 0

	// ResourceInstanceReplaceBecauseTainted indicates that the resource
	// instance must be replaced because its existing current object is
	// marked as "tainted".
	ResourceInstanceReplaceBecauseTainted ResourceInstanceChangeActionReason = 'T'

	// ResourceInstanceReplaceByRequest indicates that the resource instance
	// is planned to be replaced because a caller specifically asked for it
	// to be using ReplaceAddrs. (On the command line, the -replace=...
	// planning option.)
	ResourceInstanceReplaceByRequest ResourceInstanceChangeActionReason = 'R'

	// ResourceInstanceReplaceByTriggers indicates that the resource instance
	// is planned to be replaced because of a corresponding change in a
	// replace_triggered_by reference.
	ResourceInstanceReplaceByTriggers ResourceInstanceChangeActionReason = 'D'

	// ResourceInstanceReplaceBecauseCannotUpdate indicates that the resource
	// instance is planned to be replaced because the provider has indicated
	// that a requested change cannot be applied as an update.
	//
	// In this case, the RequiredReplace field will typically be populated on
	// the ResourceInstanceChange object to give information about specifically
	// which arguments changed in a non-updatable way.
	ResourceInstanceReplaceBecauseCannotUpdate ResourceInstanceChangeActionReason = 'F'

	// ResourceInstanceDeleteBecauseNoResourceConfig indicates that the
	// resource instance is planned to be deleted because there's no
	// corresponding resource configuration block in the configuration.
	ResourceInstanceDeleteBecauseNoResourceConfig ResourceInstanceChangeActionReason = 'N'

	// ResourceInstanceDeleteBecauseWrongRepetition indicates that the
	// resource instance is planned to be deleted because the instance key
	// type isn't consistent with the repetition mode selected in the
	// resource configuration.
	ResourceInstanceDeleteBecauseWrongRepetition ResourceInstanceChangeActionReason = 'W'

	// ResourceInstanceDeleteBecauseCountIndex indicates that the resource
	// instance is planned to be deleted because its integer instance key
	// is out of range for the current configured resource "count" value.
	ResourceInstanceDeleteBecauseCountIndex ResourceInstanceChangeActionReason = 'C'

	// ResourceInstanceDeleteBecauseEachKey indicates that the resource
	// instance is planned to be deleted because its string instance key
	// isn't one of the keys included in the current configured resource
	// "for_each" value.
	ResourceInstanceDeleteBecauseEachKey ResourceInstanceChangeActionReason = 'E'

	// ResourceInstanceDeleteBecauseNoModule indicates that the resource
	// instance is planned to be deleted because it belongs to a module
	// instance that's no longer declared in the configuration.
	//
	// This is less specific than the reasons we return for the various ways
	// a resource instance itself can be no longer declared, including both
	// the total removal of a module block and changes to its count/for_each
	// arguments. This difference in detail is out of pragmatism, because
	// potentially multiple nested modules could all contribute conflicting
	// specific reasons for a particular instance to no longer be declared.
	ResourceInstanceDeleteBecauseNoModule ResourceInstanceChangeActionReason = 'M'

	// ResourceInstanceDeleteBecauseNoMoveTarget indicates that the resource
	// address appears as the target ("to") in a moved block, but no
	// configuration exists for that resource. According to our move rules,
	// this combination evaluates to a deletion of the "new" resource.
	ResourceInstanceDeleteBecauseNoMoveTarget ResourceInstanceChangeActionReason = 'A'

	// ResourceInstanceReadBecauseConfigUnknown indicates that the resource
	// must be read during apply (rather than during planning) because its
	// configuration contains unknown values. This reason applies only to
	// data resources.
	ResourceInstanceReadBecauseConfigUnknown ResourceInstanceChangeActionReason = '?'

	// ResourceInstanceReadBecauseDependencyPending indicates that the resource
	// must be read during apply (rather than during planning) because it
	// depends on a managed resource instance which has its own changes
	// pending.
	ResourceInstanceReadBecauseDependencyPending ResourceInstanceChangeActionReason = '!'

	// ResourceInstanceReadBecauseCheckNested indicates that the resource must
	// be read during apply (as well as during planning) because it is inside
	// a check block and when the check assertions execute we want them to use
	// the most up-to-date data.
	ResourceInstanceReadBecauseCheckNested ResourceInstanceChangeActionReason = '#'
)

func (ResourceInstanceChangeActionReason) String

type ResourceInstanceChangeSrc

type ResourceInstanceChangeSrc struct {
	// Addr is the absolute address of the resource instance that the change
	// will apply to.
	Addr addrs.AbsResourceInstance

	// PrevRunAddr is the absolute address that this resource instance had at
	// the conclusion of a previous run.
	//
	// This will typically be the same as Addr, but can be different if the
	// previous resource instance was subject to a "moved" block that we
	// handled in the process of creating this plan.
	//
	// For the initial creation of a resource instance there isn't really any
	// meaningful "previous run address", but PrevRunAddr will still be set
	// equal to Addr in that case in order to simplify logic elsewhere which
	// aims to detect and react to the movement of instances between addresses.
	PrevRunAddr addrs.AbsResourceInstance

	// DeposedKey is the identifier for a deposed object associated with the
	// given instance, or states.NotDeposed if this change applies to the
	// current object.
	//
	// A Replace change for a resource with create_before_destroy set will
	// create a new DeposedKey temporarily during replacement. In that case,
	// DeposedKey in the plan is always states.NotDeposed, representing that
	// the current object is being replaced with the deposed.
	DeposedKey states.DeposedKey

	// Provider is the address of the provider configuration that was used
	// to plan this change, and thus the configuration that must also be
	// used to apply it.
	ProviderAddr addrs.AbsProviderConfig

	// ChangeSrc is an embedded description of the not-yet-decoded change.
	ChangeSrc

	// ActionReason is an optional extra indication of why we chose the
	// action recorded in Change.Action for this particular resource instance.
	//
	// This is an approximate mechanism only for the purpose of explaining the
	// plan to end-users in the UI and is not to be used for any
	// decision-making during the apply step; if apply behavior needs to vary
	// depending on the "action reason" then the information for that decision
	// must be recorded more precisely elsewhere for that purpose.
	//
	// See the field of the same name in ResourceInstanceChange for more
	// details.
	ActionReason ResourceInstanceChangeActionReason

	// RequiredReplace is a set of paths that caused the change action to be
	// Replace rather than Update. Always nil if the change action is not
	// Replace.
	RequiredReplace cty.PathSet

	// Private allows a provider to stash any extra data that is opaque to
	// OpenTofu that relates to this change. OpenTofu will save this
	// byte-for-byte and return it to the provider in the apply call.
	Private []byte
}

ResourceInstanceChangeSrc is a not-yet-decoded ResourceInstanceChange. Pass the associated resource type's schema type to method Decode to obtain a ResourceInstanceChange.

func (*ResourceInstanceChangeSrc) Decode

Decode unmarshals the raw representation of the instance object being changed. Pass the implied type of the corresponding resource type schema for correct operation.

func (*ResourceInstanceChangeSrc) DeepCopy

DeepCopy creates a copy of the receiver where any pointers to nested mutable values are also copied, thus ensuring that future mutations of the receiver will not affect the copy.

Some types used within a resource change are immutable by convention even though the Go language allows them to be mutated, such as the types from the addrs package. These are _not_ copied by this method, under the assumption that callers will behave themselves.

func (*ResourceInstanceChangeSrc) Moved

func (rcs *ResourceInstanceChangeSrc) Moved() bool

Directories

Path Synopsis
internal
planproto
Package planproto is home to the Go stubs generated from the tfplan protobuf schema.
Package planproto is home to the Go stubs generated from the tfplan protobuf schema.
Package objchange deals with the business logic of taking a prior state value and a config value and producing a proposed new merged value, along with other related rules in this domain.
Package objchange deals with the business logic of taking a prior state value and a config value and producing a proposed new merged value, along with other related rules in this domain.
Package planfile deals with the file format used to serialize plans to disk and then deserialize them back into memory later.
Package planfile deals with the file format used to serialize plans to disk and then deserialize them back into memory later.

Jump to

Keyboard shortcuts

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