addrs: Adopt DeposedKey as an address type; remove states.Generation

Previously we had states.DeposedKey as our representation of the unique
keys used to differentiate between multiple deposed objects on the same
resource instance. That type is useful in various places, but its presence
in the "states" package made it troublesome to import for some callers.

Since its purpose is as an identifier, this type is more at home in the
"addrs" package. The states package retains a small number of aliases to
preserve compatibility with a few existing callers for now, until we have
the stomach for a more invasive change.

This also removes the largely-redundant states.Generation interface type,
which initially was intended as a way to distinguish between "current"
objects and deposed objects, but didn't really add anything because we
already have addrs.NotDeposed to represent that situation. Instead, we
just ended up with various bits of boilerplate adapter code converting
between the two representations. Everything now uses addrs.DeposedKey and
uses addrs.NotDeposed to identify non-deposed objects.
pull/34738/head
Martin Atkins 3 years ago
parent 54622c68a5
commit 13e26b60dd

@ -4,8 +4,11 @@
package addrs
import (
"encoding/hex"
"fmt"
"math/rand"
"strings"
"time"
)
// Resource is an address for a resource block within configuration, which
@ -292,6 +295,26 @@ func (r AbsResourceInstance) ConfigResource() ConfigResource {
}
}
// CurrentObject returns the address of the resource instance's "current"
// object, which is the one used for expression evaluation etc.
func (r AbsResourceInstance) CurrentObject() AbsResourceInstanceObject {
return AbsResourceInstanceObject{
ResourceInstance: r,
DeposedKey: NotDeposed,
}
}
// DeposedObject returns the address of a "deposed" object for the receiving
// resource instance, which appears only if a create-before-destroy replacement
// succeeds the create step but fails the destroy step, making the original
// object live on as a desposed object.
func (r AbsResourceInstance) DeposedObject(key DeposedKey) AbsResourceInstanceObject {
return AbsResourceInstanceObject{
ResourceInstance: r,
DeposedKey: key,
}
}
// TargetContains implements Targetable by returning true if the given other
// address is equal to the receiver.
func (r AbsResourceInstance) TargetContains(other Targetable) bool {
@ -480,3 +503,107 @@ const (
// "data" blocks in configuration.
DataResourceMode ResourceMode = 'D'
)
// AbsResourceInstanceObject represents one of the specific remote objects
// associated with a resource instance.
//
// When DeposedKey is [NotDeposed], this represents the "current" object.
// Otherwise, this represents a deposed object with the given key.
//
// The distinction between "current" and "deposed" objects is a planning and
// state concern that isn't reflected directly in configuration, so there
// are no "ConfigResourceInstanceObject" or "ResourceInstanceObject" address
// types.
type AbsResourceInstanceObject struct {
ResourceInstance AbsResourceInstance
DeposedKey DeposedKey
}
// String returns a string that could be used to refer to this object
// in the UI, but is not necessarily suitable for use as a unique key.
func (o AbsResourceInstanceObject) String() string {
if o.DeposedKey != NotDeposed {
return fmt.Sprintf("%s deposed object %s", o.ResourceInstance, o.DeposedKey)
}
return o.ResourceInstance.String()
}
// IsCurrent returns true only if this address is for a "current" object.
func (o AbsResourceInstanceObject) IsCurrent() bool {
return o.DeposedKey == NotDeposed
}
// IsCurrent returns true only if this address is for a "deposed" object.
func (o AbsResourceInstanceObject) IsDeposed() bool {
return o.DeposedKey != NotDeposed
}
// UniqueKey implements [UniqueKeyer]
func (o AbsResourceInstanceObject) UniqueKey() UniqueKey {
return absResourceInstanceObjectKey{
resourceInstanceKey: o.ResourceInstance.UniqueKey(),
deposedKey: o.DeposedKey,
}
}
type absResourceInstanceObjectKey struct {
resourceInstanceKey UniqueKey
deposedKey DeposedKey
}
func (absResourceInstanceObjectKey) uniqueKeySigil() {}
// DeposedKey is a 8-character hex string used to uniquely identify deposed
// instance objects in the state.
//
// The zero value of this type is [NotDeposed] and represents a "current"
// object, not deposed at all. All other valid values of this type are strings
// containing exactly eight lowercase hex characters.
type DeposedKey string
// NotDeposed is a special invalid value of DeposedKey that is used to represent
// the absense of a deposed key, typically when referring to the "current" object
// for a particular resource instance. It must not be used as an actual deposed
// key.
const NotDeposed = DeposedKey("")
var deposedKeyRand = rand.New(rand.NewSource(time.Now().UnixNano()))
// NewDeposedKey generates a pseudo-random deposed key. Because of the short
// length of these keys, uniqueness is not a natural consequence and so the
// caller should test to see if the generated key is already in use and generate
// another if so, until a unique key is found.
func NewDeposedKey() DeposedKey {
v := deposedKeyRand.Uint32()
return DeposedKey(fmt.Sprintf("%08x", v))
}
// ParseDeposedKey parses a string that is expected to be a deposed key,
// returning an error if it doesn't conform to the expected syntax.
func ParseDeposedKey(raw string) (DeposedKey, error) {
if len(raw) != 8 {
return "00000000", fmt.Errorf("must be eight hexadecimal digits")
}
if raw != strings.ToLower(raw) {
return "00000000", fmt.Errorf("must use lowercase hex digits")
}
_, err := hex.DecodeString(raw)
if err != nil {
return "00000000", fmt.Errorf("must be eight hexadecimal digits")
}
return DeposedKey(raw), nil
}
func (k DeposedKey) String() string {
return string(k)
}
func (k DeposedKey) GoString() string {
ks := string(k)
switch {
case ks == "":
return "states.NotDeposed"
default:
return fmt.Sprintf("states.DeposedKey(%q)", ks)
}
}

@ -10,7 +10,6 @@ import (
"github.com/hashicorp/terraform/internal/addrs"
"github.com/hashicorp/terraform/internal/plans"
"github.com/hashicorp/terraform/internal/states"
"github.com/hashicorp/terraform/internal/terraform"
)
@ -46,7 +45,7 @@ func (h *countHook) Reset() {
h.Imported = 0
}
func (h *countHook) PreApply(addr addrs.AbsResourceInstance, gen states.Generation, action plans.Action, priorState, plannedNewState cty.Value) (terraform.HookAction, error) {
func (h *countHook) PreApply(addr addrs.AbsResourceInstance, dk addrs.DeposedKey, action plans.Action, priorState, plannedNewState cty.Value) (terraform.HookAction, error) {
h.Lock()
defer h.Unlock()
@ -59,7 +58,7 @@ func (h *countHook) PreApply(addr addrs.AbsResourceInstance, gen states.Generati
return terraform.HookActionContinue, nil
}
func (h *countHook) PostApply(addr addrs.AbsResourceInstance, gen states.Generation, newState cty.Value, err error) (terraform.HookAction, error) {
func (h *countHook) PostApply(addr addrs.AbsResourceInstance, dk addrs.DeposedKey, newState cty.Value, err error) (terraform.HookAction, error) {
h.Lock()
defer h.Unlock()
@ -87,7 +86,7 @@ func (h *countHook) PostApply(addr addrs.AbsResourceInstance, gen states.Generat
return terraform.HookActionContinue, nil
}
func (h *countHook) PostDiff(addr addrs.AbsResourceInstance, gen states.Generation, action plans.Action, priorState, plannedNewState cty.Value) (terraform.HookAction, error) {
func (h *countHook) PostDiff(addr addrs.AbsResourceInstance, dk addrs.DeposedKey, action plans.Action, priorState, plannedNewState cty.Value) (terraform.HookAction, error) {
h.Lock()
defer h.Unlock()

@ -66,7 +66,7 @@ func TestCountHookPostDiff_DestroyOnly(t *testing.T) {
Name: k,
}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance)
h.PostDiff(addr, states.CurrentGen, plans.Delete, cty.DynamicVal, cty.DynamicVal)
h.PostDiff(addr, addrs.NotDeposed, plans.Delete, cty.DynamicVal, cty.DynamicVal)
}
expected := new(countHook)
@ -108,7 +108,7 @@ func TestCountHookPostDiff_AddOnly(t *testing.T) {
Name: k,
}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance)
h.PostDiff(addr, states.CurrentGen, plans.Create, cty.DynamicVal, cty.DynamicVal)
h.PostDiff(addr, addrs.NotDeposed, plans.Create, cty.DynamicVal, cty.DynamicVal)
}
expected := new(countHook)
@ -153,7 +153,7 @@ func TestCountHookPostDiff_ChangeOnly(t *testing.T) {
Name: k,
}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance)
h.PostDiff(addr, states.CurrentGen, plans.Update, cty.DynamicVal, cty.DynamicVal)
h.PostDiff(addr, addrs.NotDeposed, plans.Update, cty.DynamicVal, cty.DynamicVal)
}
expected := new(countHook)
@ -184,7 +184,7 @@ func TestCountHookPostDiff_Mixed(t *testing.T) {
Name: k,
}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance)
h.PostDiff(addr, states.CurrentGen, a, cty.DynamicVal, cty.DynamicVal)
h.PostDiff(addr, addrs.NotDeposed, a, cty.DynamicVal, cty.DynamicVal)
}
expected := new(countHook)
@ -216,7 +216,7 @@ func TestCountHookPostDiff_NoChange(t *testing.T) {
Name: k,
}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance)
h.PostDiff(addr, states.CurrentGen, plans.NoOp, cty.DynamicVal, cty.DynamicVal)
h.PostDiff(addr, addrs.NotDeposed, plans.NoOp, cty.DynamicVal, cty.DynamicVal)
}
expected := new(countHook)
@ -248,7 +248,7 @@ func TestCountHookPostDiff_DataSource(t *testing.T) {
Name: k,
}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance)
h.PostDiff(addr, states.CurrentGen, a, cty.DynamicVal, cty.DynamicVal)
h.PostDiff(addr, addrs.NotDeposed, a, cty.DynamicVal, cty.DynamicVal)
}
expected := new(countHook)
@ -294,8 +294,8 @@ func TestCountHookApply_ChangeOnly(t *testing.T) {
Name: k,
}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance)
h.PreApply(addr, states.CurrentGen, plans.Update, cty.DynamicVal, cty.DynamicVal)
h.PostApply(addr, states.CurrentGen, cty.DynamicVal, nil)
h.PreApply(addr, addrs.NotDeposed, plans.Update, cty.DynamicVal, cty.DynamicVal)
h.PostApply(addr, addrs.NotDeposed, cty.DynamicVal, nil)
}
expected := &countHook{pending: make(map[string]plans.Action)}
@ -325,8 +325,8 @@ func TestCountHookApply_DestroyOnly(t *testing.T) {
Name: k,
}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance)
h.PreApply(addr, states.CurrentGen, plans.Delete, cty.DynamicVal, cty.DynamicVal)
h.PostApply(addr, states.CurrentGen, cty.DynamicVal, nil)
h.PreApply(addr, addrs.NotDeposed, plans.Delete, cty.DynamicVal, cty.DynamicVal)
h.PostApply(addr, addrs.NotDeposed, cty.DynamicVal, nil)
}
expected := &countHook{pending: make(map[string]plans.Action)}

@ -16,7 +16,6 @@ import (
"github.com/hashicorp/terraform/internal/command/format"
"github.com/hashicorp/terraform/internal/command/views/json"
"github.com/hashicorp/terraform/internal/plans"
"github.com/hashicorp/terraform/internal/states"
"github.com/hashicorp/terraform/internal/terraform"
)
@ -62,7 +61,7 @@ type applyProgress struct {
heartbeatDone chan struct{}
}
func (h *jsonHook) PreApply(addr addrs.AbsResourceInstance, gen states.Generation, action plans.Action, priorState, plannedNewState cty.Value) (terraform.HookAction, error) {
func (h *jsonHook) PreApply(addr addrs.AbsResourceInstance, dk addrs.DeposedKey, action plans.Action, priorState, plannedNewState cty.Value) (terraform.HookAction, error) {
if action != plans.NoOp {
idKey, idValue := format.ObjectValueIDOrName(priorState)
h.view.Hook(json.NewApplyStart(addr, action, idKey, idValue))
@ -99,7 +98,7 @@ func (h *jsonHook) applyingHeartbeat(progress applyProgress) {
}
}
func (h *jsonHook) PostApply(addr addrs.AbsResourceInstance, gen states.Generation, newState cty.Value, err error) (terraform.HookAction, error) {
func (h *jsonHook) PostApply(addr addrs.AbsResourceInstance, dk addrs.DeposedKey, newState cty.Value, err error) (terraform.HookAction, error) {
key := addr.String()
h.applyingLock.Lock()
progress := h.applying[key]
@ -155,13 +154,13 @@ func (h *jsonHook) ProvisionOutput(addr addrs.AbsResourceInstance, typeName stri
}
}
func (h *jsonHook) PreRefresh(addr addrs.AbsResourceInstance, gen states.Generation, priorState cty.Value) (terraform.HookAction, error) {
func (h *jsonHook) PreRefresh(addr addrs.AbsResourceInstance, dk addrs.DeposedKey, priorState cty.Value) (terraform.HookAction, error) {
idKey, idValue := format.ObjectValueID(priorState)
h.view.Hook(json.NewRefreshStart(addr, idKey, idValue))
return terraform.HookActionContinue, nil
}
func (h *jsonHook) PostRefresh(addr addrs.AbsResourceInstance, gen states.Generation, priorState cty.Value, newState cty.Value) (terraform.HookAction, error) {
func (h *jsonHook) PostRefresh(addr addrs.AbsResourceInstance, dk addrs.DeposedKey, priorState cty.Value, newState cty.Value) (terraform.HookAction, error) {
idKey, idValue := format.ObjectValueID(newState)
h.view.Hook(json.NewRefreshComplete(addr, idKey, idValue))
return terraform.HookActionContinue, nil

@ -11,7 +11,6 @@ import (
"github.com/hashicorp/terraform/internal/addrs"
"github.com/hashicorp/terraform/internal/plans"
"github.com/hashicorp/terraform/internal/states"
"github.com/hashicorp/terraform/internal/terminal"
"github.com/hashicorp/terraform/internal/terraform"
"github.com/zclconf/go-cty/cty"
@ -49,7 +48,7 @@ func TestJSONHook_create(t *testing.T) {
}),
})
action, err := hook.PreApply(addr, states.CurrentGen, plans.Create, priorState, plannedNewState)
action, err := hook.PreApply(addr, addrs.NotDeposed, plans.Create, priorState, plannedNewState)
testHookReturnValues(t, action, err)
action, err = hook.PreProvisionInstanceStep(addr, "local-exec")
@ -81,7 +80,7 @@ func TestJSONHook_create(t *testing.T) {
now = now.Add(2 * time.Second)
nowMu.Unlock()
action, err = hook.PostApply(addr, states.CurrentGen, plannedNewState, nil)
action, err = hook.PostApply(addr, addrs.NotDeposed, plannedNewState, nil)
testHookReturnValues(t, action, err)
// Shut down the progress goroutine if still active
@ -204,7 +203,7 @@ func TestJSONHook_errors(t *testing.T) {
}),
})
action, err := hook.PreApply(addr, states.CurrentGen, plans.Delete, priorState, plannedNewState)
action, err := hook.PreApply(addr, addrs.NotDeposed, plans.Delete, priorState, plannedNewState)
testHookReturnValues(t, action, err)
provisionError := fmt.Errorf("provisioner didn't want to")
@ -212,7 +211,7 @@ func TestJSONHook_errors(t *testing.T) {
testHookReturnValues(t, action, err)
applyError := fmt.Errorf("provider was sad")
action, err = hook.PostApply(addr, states.CurrentGen, plannedNewState, applyError)
action, err = hook.PostApply(addr, addrs.NotDeposed, plannedNewState, applyError)
testHookReturnValues(t, action, err)
// Shut down the progress goroutine
@ -286,10 +285,10 @@ func TestJSONHook_refresh(t *testing.T) {
}),
})
action, err := hook.PreRefresh(addr, states.CurrentGen, state)
action, err := hook.PreRefresh(addr, addrs.NotDeposed, state)
testHookReturnValues(t, action, err)
action, err = hook.PostRefresh(addr, states.CurrentGen, state, state)
action, err = hook.PostRefresh(addr, addrs.NotDeposed, state, state)
testHookReturnValues(t, action, err)
wantResource := map[string]interface{}{

@ -18,7 +18,6 @@ import (
"github.com/hashicorp/terraform/internal/command/format"
"github.com/hashicorp/terraform/internal/plans"
"github.com/hashicorp/terraform/internal/providers"
"github.com/hashicorp/terraform/internal/states"
"github.com/hashicorp/terraform/internal/terraform"
)
@ -71,10 +70,10 @@ const (
uiResourceNoOp
)
func (h *UiHook) PreApply(addr addrs.AbsResourceInstance, gen states.Generation, action plans.Action, priorState, plannedNewState cty.Value) (terraform.HookAction, error) {
func (h *UiHook) PreApply(addr addrs.AbsResourceInstance, dk addrs.DeposedKey, action plans.Action, priorState, plannedNewState cty.Value) (terraform.HookAction, error) {
dispAddr := addr.String()
if gen != states.CurrentGen {
dispAddr = fmt.Sprintf("%s (deposed object %s)", dispAddr, gen)
if dk != addrs.NotDeposed {
dispAddr = fmt.Sprintf("%s (deposed object %s)", dispAddr, dk)
}
var operation string
@ -184,7 +183,7 @@ func (h *UiHook) stillApplying(state uiResourceState) {
}
}
func (h *UiHook) PostApply(addr addrs.AbsResourceInstance, gen states.Generation, newState cty.Value, applyerr error) (terraform.HookAction, error) {
func (h *UiHook) PostApply(addr addrs.AbsResourceInstance, dk addrs.DeposedKey, newState cty.Value, applyerr error) (terraform.HookAction, error) {
id := addr.String()
h.resourcesLock.Lock()
@ -224,8 +223,8 @@ func (h *UiHook) PostApply(addr addrs.AbsResourceInstance, gen states.Generation
}
addrStr := addr.String()
if depKey, ok := gen.(states.DeposedKey); ok {
addrStr = fmt.Sprintf("%s (deposed object %s)", addrStr, depKey)
if dk != addrs.NotDeposed {
addrStr = fmt.Sprintf("%s (deposed object %s)", addrStr, dk)
}
colorized := fmt.Sprintf(
@ -264,15 +263,15 @@ func (h *UiHook) ProvisionOutput(addr addrs.AbsResourceInstance, typeName string
h.println(strings.TrimSpace(buf.String()))
}
func (h *UiHook) PreRefresh(addr addrs.AbsResourceInstance, gen states.Generation, priorState cty.Value) (terraform.HookAction, error) {
func (h *UiHook) PreRefresh(addr addrs.AbsResourceInstance, dk addrs.DeposedKey, priorState cty.Value) (terraform.HookAction, error) {
var stateIdSuffix string
if k, v := format.ObjectValueID(priorState); k != "" && v != "" {
stateIdSuffix = fmt.Sprintf(" [%s=%s]", k, v)
}
addrStr := addr.String()
if depKey, ok := gen.(states.DeposedKey); ok {
addrStr = fmt.Sprintf("%s (deposed object %s)", addrStr, depKey)
if dk != addrs.NotDeposed {
addrStr = fmt.Sprintf("%s (deposed object %s)", addrStr, dk)
}
h.println(fmt.Sprintf(

@ -51,7 +51,7 @@ func TestUiHookPreApply_create(t *testing.T) {
}),
})
action, err := h.PreApply(addr, states.CurrentGen, plans.Create, priorState, plannedNewState)
action, err := h.PreApply(addr, addrs.NotDeposed, plans.Create, priorState, plannedNewState)
if err != nil {
t.Fatal(err)
}
@ -109,7 +109,7 @@ func TestUiHookPreApply_periodicTimer(t *testing.T) {
}),
})
action, err := h.PreApply(addr, states.CurrentGen, plans.Update, priorState, plannedNewState)
action, err := h.PreApply(addr, addrs.NotDeposed, plans.Update, priorState, plannedNewState)
if err != nil {
t.Fatal(err)
}
@ -224,7 +224,7 @@ func TestUiHookPostApply_colorInterpolation(t *testing.T) {
"id": cty.StringVal("[blue]"),
})
action, err := h.PostApply(addr, states.CurrentGen, newState, nil)
action, err := h.PostApply(addr, addrs.NotDeposed, newState, nil)
if err != nil {
t.Fatal(err)
}
@ -277,7 +277,7 @@ func TestUiHookPostApply_emptyState(t *testing.T) {
"names": cty.List(cty.String),
}))
action, err := h.PostApply(addr, states.CurrentGen, newState, nil)
action, err := h.PostApply(addr, addrs.NotDeposed, newState, nil)
if err != nil {
t.Fatal(err)
}
@ -425,7 +425,7 @@ func TestPreRefresh(t *testing.T) {
"bar": cty.ListValEmpty(cty.String),
})
action, err := h.PreRefresh(addr, states.CurrentGen, priorState)
action, err := h.PreRefresh(addr, addrs.NotDeposed, priorState)
if err != nil {
t.Fatal(err)
@ -457,7 +457,7 @@ func TestPreRefresh_noID(t *testing.T) {
"bar": cty.ListValEmpty(cty.String),
})
action, err := h.PreRefresh(addr, states.CurrentGen, priorState)
action, err := h.PreRefresh(addr, addrs.NotDeposed, priorState)
if err != nil {
t.Fatal(err)

@ -4,11 +4,9 @@
package plans
import (
"fmt"
"sync"
"github.com/hashicorp/terraform/internal/addrs"
"github.com/hashicorp/terraform/internal/states"
)
// ChangesSync is a wrapper around a Changes that provides a concurrency-safe
@ -42,27 +40,26 @@ func (cs *ChangesSync) AppendResourceInstanceChange(changeSrc *ResourceInstanceC
}
// GetResourceInstanceChange searches the set of resource instance changes for
// one matching the given address and generation, returning it if it exists.
// one matching the given address and deposed key, returning it if it exists.
// Use [addrs.NotDeposed] as the deposed key to represent the "current"
// object for the given resource instance.
//
// 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 (cs *ChangesSync) GetResourceInstanceChange(addr addrs.AbsResourceInstance, gen states.Generation) *ResourceInstanceChangeSrc {
func (cs *ChangesSync) GetResourceInstanceChange(addr addrs.AbsResourceInstance, dk addrs.DeposedKey) *ResourceInstanceChangeSrc {
if cs == nil {
panic("GetResourceInstanceChange on nil ChangesSync")
}
cs.lock.Lock()
defer cs.lock.Unlock()
if gen == states.CurrentGen {
if dk == addrs.NotDeposed {
return cs.changes.ResourceInstance(addr).DeepCopy()
}
if dk, ok := gen.(states.DeposedKey); ok {
return cs.changes.ResourceInstanceDeposed(addr, dk).DeepCopy()
}
panic(fmt.Sprintf("unsupported generation value %#v", gen))
return cs.changes.ResourceInstanceDeposed(addr, dk).DeepCopy()
}
// GetChangesForConfigResource searches the set of resource instance
@ -110,20 +107,15 @@ func (cs *ChangesSync) GetChangesForAbsResource(addr addrs.AbsResource) []*Resou
}
// RemoveResourceInstanceChange searches the set of resource instance changes
// for one matching the given address and generation, and removes it from the
// for one matching the given address and deposed key, and removes it from the
// set if it exists.
func (cs *ChangesSync) RemoveResourceInstanceChange(addr addrs.AbsResourceInstance, gen states.Generation) {
func (cs *ChangesSync) RemoveResourceInstanceChange(addr addrs.AbsResourceInstance, dk addrs.DeposedKey) {
if cs == nil {
panic("RemoveResourceInstanceChange on nil ChangesSync")
}
cs.lock.Lock()
defer cs.lock.Unlock()
dk := states.NotDeposed
if realDK, ok := gen.(states.DeposedKey); ok {
dk = realDK
}
addrStr := addr.String()
for i, r := range cs.changes.Resources {
if r.Addr.String() != addrStr || r.DeposedKey != dk {

@ -10,7 +10,6 @@ import (
"github.com/hashicorp/terraform/internal/plans"
"github.com/hashicorp/terraform/internal/stacks/stackaddrs"
"github.com/hashicorp/terraform/internal/stacks/stackruntime/hooks"
"github.com/hashicorp/terraform/internal/states"
"github.com/hashicorp/terraform/internal/terraform"
"github.com/zclconf/go-cty/cty"
)
@ -39,7 +38,7 @@ func (h *componentInstanceTerraformHook) resourceInstanceAddr(addr addrs.AbsReso
}
}
func (h *componentInstanceTerraformHook) PreDiff(addr addrs.AbsResourceInstance, gen states.Generation, priorState, proposedNewState cty.Value) (terraform.HookAction, error) {
func (h *componentInstanceTerraformHook) PreDiff(addr addrs.AbsResourceInstance, dk addrs.DeposedKey, priorState, proposedNewState cty.Value) (terraform.HookAction, error) {
hookMore(h.ctx, h.seq, h.hooks.ReportResourceInstanceStatus, &hooks.ResourceInstanceStatusHookData{
Addr: h.resourceInstanceAddr(addr),
Status: hooks.ResourceInstancePlanning,
@ -47,7 +46,7 @@ func (h *componentInstanceTerraformHook) PreDiff(addr addrs.AbsResourceInstance,
return terraform.HookActionContinue, nil
}
func (h *componentInstanceTerraformHook) PostDiff(addr addrs.AbsResourceInstance, gen states.Generation, action plans.Action, priorState, plannedNewState cty.Value) (terraform.HookAction, error) {
func (h *componentInstanceTerraformHook) PostDiff(addr addrs.AbsResourceInstance, dk addrs.DeposedKey, action plans.Action, priorState, plannedNewState cty.Value) (terraform.HookAction, error) {
hookMore(h.ctx, h.seq, h.hooks.ReportResourceInstanceStatus, &hooks.ResourceInstanceStatusHookData{
Addr: h.resourceInstanceAddr(addr),
Status: hooks.ResourceInstancePlanned,
@ -55,7 +54,7 @@ func (h *componentInstanceTerraformHook) PostDiff(addr addrs.AbsResourceInstance
return terraform.HookActionContinue, nil
}
func (h *componentInstanceTerraformHook) PreApply(addr addrs.AbsResourceInstance, gen states.Generation, action plans.Action, priorState, plannedNewState cty.Value) (terraform.HookAction, error) {
func (h *componentInstanceTerraformHook) PreApply(addr addrs.AbsResourceInstance, dk addrs.DeposedKey, action plans.Action, priorState, plannedNewState cty.Value) (terraform.HookAction, error) {
if action != plans.NoOp {
hookMore(h.ctx, h.seq, h.hooks.ReportResourceInstanceStatus, &hooks.ResourceInstanceStatusHookData{
Addr: h.resourceInstanceAddr(addr),
@ -65,7 +64,7 @@ func (h *componentInstanceTerraformHook) PreApply(addr addrs.AbsResourceInstance
return terraform.HookActionContinue, nil
}
func (h *componentInstanceTerraformHook) PostApply(addr addrs.AbsResourceInstance, gen states.Generation, newState cty.Value, err error) (terraform.HookAction, error) {
func (h *componentInstanceTerraformHook) PostApply(addr addrs.AbsResourceInstance, dk addrs.DeposedKey, newState cty.Value, err error) (terraform.HookAction, error) {
// FIXME: need to emit nothing if this was a no-op, which means tracking
// the `action` argument to `PreApply`. See `jsonHook` for more on this.
status := hooks.ResourceInstanceApplied

@ -1,23 +0,0 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package states
// Generation is used to represent multiple objects in a succession of objects
// represented by a single resource instance address. A resource instance can
// have multiple generations over its lifetime due to object replacement
// (when a change can't be applied without destroying and re-creating), and
// multiple generations can exist at the same time when create_before_destroy
// is used.
//
// A Generation value can either be the value of the variable "CurrentGen" or
// a value of type DeposedKey. Generation values can be compared for equality
// using "==" and used as map keys. The zero value of Generation (nil) is not
// a valid generation and must not be used.
type Generation interface {
generation()
}
// CurrentGen is the Generation representing the currently-active object for
// a resource instance.
var CurrentGen Generation

@ -4,11 +4,7 @@
package states
import (
"encoding/hex"
"fmt"
"math/rand"
"strings"
"time"
"github.com/hashicorp/terraform/internal/addrs"
)
@ -128,23 +124,14 @@ func (i *ResourceInstance) deposeCurrentObject(forceKey DeposedKey) DeposedKey {
return key
}
// GetGeneration retrieves the object of the given generation from the
// ResourceInstance, or returns nil if there is no such object.
//
// If the given generation is nil or invalid, this method will panic.
func (i *ResourceInstance) GetGeneration(gen Generation) *ResourceInstanceObjectSrc {
if gen == CurrentGen {
// Object retrieves the object with the given deposed key from the
// ResourceInstance, or returns nil if there is no such object. Use
// [addrs.NotDeposed] to retrieve the "current" object, if any.
func (i *ResourceInstance) Object(dk DeposedKey) *ResourceInstanceObjectSrc {
if dk == addrs.NotDeposed {
return i.Current
}
if dk, ok := gen.(DeposedKey); ok {
return i.Deposed[dk]
}
if gen == nil {
panic("get with nil Generation")
}
// Should never fall out here, since the above covers all possible
// Generation values.
panic(fmt.Sprintf("get invalid Generation %#v", gen))
return i.Deposed[dk]
}
// FindUnusedDeposedKey generates a unique DeposedKey that is guaranteed not to
@ -172,65 +159,21 @@ func (i *ResourceInstance) findUnusedDeposedKey() DeposedKey {
}
}
// DeposedKey is a 8-character hex string used to uniquely identify deposed
// instance objects in the state.
type DeposedKey string
// NotDeposed is a special invalid value of DeposedKey that is used to represent
// the absense of a deposed key. It must not be used as an actual deposed key.
const NotDeposed = DeposedKey("")
// DeposedKey is an alias for [addrs.DeposedKey], representing keys assigned
// to deposed resource instance objects.
type DeposedKey = addrs.DeposedKey
var deposedKeyRand = rand.New(rand.NewSource(time.Now().UnixNano()))
// NotDeposed is an alias for the zero value of [addrs.DeposedKey], which
// represents the absense of a deposed key, i.e. that the associated object
// is the "current" object for some resource instance.
const NotDeposed = addrs.NotDeposed
// NewDeposedKey generates a pseudo-random deposed key. Because of the short
// length of these keys, uniqueness is not a natural consequence and so the
// caller should test to see if the generated key is already in use and generate
// another if so, until a unique key is found.
// NewDeposedKey is an alias for [addrs.NewDeposedKey].
func NewDeposedKey() DeposedKey {
v := deposedKeyRand.Uint32()
return DeposedKey(fmt.Sprintf("%08x", v))
return addrs.NewDeposedKey()
}
// ParseDeposedKey parses a string that is expected to be a deposed key,
// returning an error if it doesn't conform to the expected syntax.
// ParseDeposedKey is an alias for [addrs.ParseDeposedKey].
func ParseDeposedKey(raw string) (DeposedKey, error) {
if len(raw) != 8 {
return "00000000", fmt.Errorf("must be eight hexadecimal digits")
}
if raw != strings.ToLower(raw) {
return "00000000", fmt.Errorf("must use lowercase hex digits")
}
_, err := hex.DecodeString(raw)
if err != nil {
return "00000000", fmt.Errorf("must be eight hexadecimal digits")
}
return DeposedKey(raw), nil
}
func (k DeposedKey) String() string {
return string(k)
}
func (k DeposedKey) GoString() string {
ks := string(k)
switch {
case ks == "":
return "states.NotDeposed"
default:
return fmt.Sprintf("states.DeposedKey(%s)", ks)
}
return addrs.ParseDeposedKey(raw)
}
// Generation is a helper method to convert a DeposedKey into a Generation.
// If the reciever is anything other than NotDeposed then the result is
// just the same value as a Generation. If the receiver is NotDeposed then
// the result is CurrentGen.
func (k DeposedKey) Generation() Generation {
if k == NotDeposed {
return CurrentGen
}
return k
}
// generation is an implementation of Generation.
func (k DeposedKey) generation() {}

@ -181,13 +181,14 @@ func (s *SyncState) ResourceInstance(addr addrs.AbsResourceInstance) *ResourceIn
return ret
}
// ResourceInstanceObject returns a snapshot of the current instance object
// of the given generation belonging to the instance with the given address,
// or nil if no such object is tracked..
// ResourceInstanceObject returns a snapshot of the resource instance object
// of the given deposed key belonging to the given resource instance. Use
// [addrs.NotDeposed] for the deposed key to retrieve the "current" object,
// if any. Returns nil if there is no such object.
//
// The return value is a pointer to a copy of the object, which the caller may
// then freely access and mutate.
func (s *SyncState) ResourceInstanceObject(addr addrs.AbsResourceInstance, gen Generation) *ResourceInstanceObjectSrc {
func (s *SyncState) ResourceInstanceObject(addr addrs.AbsResourceInstance, dk DeposedKey) *ResourceInstanceObjectSrc {
s.lock.RLock()
defer s.lock.RUnlock()
@ -195,7 +196,7 @@ func (s *SyncState) ResourceInstanceObject(addr addrs.AbsResourceInstance, gen G
if inst == nil {
return nil
}
return inst.GetGeneration(gen).DeepCopy()
return inst.Object(dk).DeepCopy()
}
// SetResourceMeta updates the resource-level metadata for the resource at

@ -1135,7 +1135,7 @@ func TestContext2Apply_createBeforeDestroy_hook(t *testing.T) {
var actual []cty.Value
var actualLock sync.Mutex
h.PostApplyFn = func(addr addrs.AbsResourceInstance, gen states.Generation, sv cty.Value, e error) (HookAction, error) {
h.PostApplyFn = func(addr addrs.AbsResourceInstance, dk addrs.DeposedKey, sv cty.Value, e error) (HookAction, error) {
actualLock.Lock()
defer actualLock.Unlock()

@ -331,7 +331,7 @@ func (ctx *BuiltinEvalContext) EvaluateReplaceTriggeredBy(expr hcl.Expression, r
case addrs.ResourceInstance:
resourceAddr = sub.ContainingResource()
rc := sub.Absolute(ctx.Path())
change := ctx.Changes().GetResourceInstanceChange(rc, states.CurrentGen)
change := ctx.Changes().GetResourceInstanceChange(rc, addrs.NotDeposed)
if change != nil {
// we'll generate an error below if there was no change
changes = append(changes, change)

@ -755,7 +755,7 @@ func (d *evaluationStateData) GetResource(addr addrs.Resource, rng tfdiags.Sourc
instAddr := addr.Instance(key).Absolute(d.ModulePath)
change := d.Evaluator.Changes.GetResourceInstanceChange(instAddr, states.CurrentGen)
change := d.Evaluator.Changes.GetResourceInstanceChange(instAddr, addrs.NotDeposed)
if change != nil {
// Don't take any resources that are yet to be deleted into account.
// If the referenced resource is CreateBeforeDestroy, then orphaned

@ -36,14 +36,14 @@ type Hook interface {
// PreApply and PostApply are called before and after an action for a
// single instance is applied. The error argument in PostApply is the
// error, if any, that was returned from the provider Apply call itself.
PreApply(addr addrs.AbsResourceInstance, gen states.Generation, action plans.Action, priorState, plannedNewState cty.Value) (HookAction, error)
PostApply(addr addrs.AbsResourceInstance, gen states.Generation, newState cty.Value, err error) (HookAction, error)
PreApply(addr addrs.AbsResourceInstance, dk addrs.DeposedKey, action plans.Action, priorState, plannedNewState cty.Value) (HookAction, error)
PostApply(addr addrs.AbsResourceInstance, dk addrs.DeposedKey, newState cty.Value, err error) (HookAction, error)
// PreDiff and PostDiff are called before and after a provider is given
// the opportunity to customize the proposed new state to produce the
// planned new state.
PreDiff(addr addrs.AbsResourceInstance, gen states.Generation, priorState, proposedNewState cty.Value) (HookAction, error)
PostDiff(addr addrs.AbsResourceInstance, gen states.Generation, action plans.Action, priorState, plannedNewState cty.Value) (HookAction, error)
PreDiff(addr addrs.AbsResourceInstance, dk addrs.DeposedKey, priorState, proposedNewState cty.Value) (HookAction, error)
PostDiff(addr addrs.AbsResourceInstance, dk addrs.DeposedKey, action plans.Action, priorState, plannedNewState cty.Value) (HookAction, error)
// The provisioning hooks signal both the overall start end end of
// provisioning for a particular instance and of each of the individual
@ -71,8 +71,8 @@ type Hook interface {
// PreRefresh and PostRefresh are called before and after a single
// resource state is refreshed, respectively.
PreRefresh(addr addrs.AbsResourceInstance, gen states.Generation, priorState cty.Value) (HookAction, error)
PostRefresh(addr addrs.AbsResourceInstance, gen states.Generation, priorState cty.Value, newState cty.Value) (HookAction, error)
PreRefresh(addr addrs.AbsResourceInstance, dk addrs.DeposedKey, priorState cty.Value) (HookAction, error)
PostRefresh(addr addrs.AbsResourceInstance, dk addrs.DeposedKey, priorState cty.Value, newState cty.Value) (HookAction, error)
// PreImportState and PostImportState are called before and after
// (respectively) each state import operation for a given resource address when
@ -119,19 +119,19 @@ type NilHook struct{}
var _ Hook = (*NilHook)(nil)
func (*NilHook) PreApply(addr addrs.AbsResourceInstance, gen states.Generation, action plans.Action, priorState, plannedNewState cty.Value) (HookAction, error) {
func (*NilHook) PreApply(addr addrs.AbsResourceInstance, dk addrs.DeposedKey, action plans.Action, priorState, plannedNewState cty.Value) (HookAction, error) {
return HookActionContinue, nil
}
func (*NilHook) PostApply(addr addrs.AbsResourceInstance, gen states.Generation, newState cty.Value, err error) (HookAction, error) {
func (*NilHook) PostApply(addr addrs.AbsResourceInstance, dk addrs.DeposedKey, newState cty.Value, err error) (HookAction, error) {
return HookActionContinue, nil
}
func (*NilHook) PreDiff(addr addrs.AbsResourceInstance, gen states.Generation, priorState, proposedNewState cty.Value) (HookAction, error) {
func (*NilHook) PreDiff(addr addrs.AbsResourceInstance, dk addrs.DeposedKey, priorState, proposedNewState cty.Value) (HookAction, error) {
return HookActionContinue, nil
}
func (*NilHook) PostDiff(addr addrs.AbsResourceInstance, gen states.Generation, action plans.Action, priorState, plannedNewState cty.Value) (HookAction, error) {
func (*NilHook) PostDiff(addr addrs.AbsResourceInstance, dk addrs.DeposedKey, action plans.Action, priorState, plannedNewState cty.Value) (HookAction, error) {
return HookActionContinue, nil
}
@ -154,11 +154,11 @@ func (*NilHook) PostProvisionInstanceStep(addr addrs.AbsResourceInstance, typeNa
func (*NilHook) ProvisionOutput(addr addrs.AbsResourceInstance, typeName string, line string) {
}
func (*NilHook) PreRefresh(addr addrs.AbsResourceInstance, gen states.Generation, priorState cty.Value) (HookAction, error) {
func (*NilHook) PreRefresh(addr addrs.AbsResourceInstance, dk addrs.DeposedKey, priorState cty.Value) (HookAction, error) {
return HookActionContinue, nil
}
func (*NilHook) PostRefresh(addr addrs.AbsResourceInstance, gen states.Generation, priorState cty.Value, newState cty.Value) (HookAction, error) {
func (*NilHook) PostRefresh(addr addrs.AbsResourceInstance, dk addrs.DeposedKey, priorState cty.Value, newState cty.Value) (HookAction, error) {
return HookActionContinue, nil
}

@ -21,7 +21,7 @@ type MockHook struct {
PreApplyCalled bool
PreApplyAddr addrs.AbsResourceInstance
PreApplyGen states.Generation
PreApplyGen addrs.DeposedKey
PreApplyAction plans.Action
PreApplyPriorState cty.Value
PreApplyPlannedState cty.Value
@ -30,16 +30,16 @@ type MockHook struct {
PostApplyCalled bool
PostApplyAddr addrs.AbsResourceInstance
PostApplyGen states.Generation
PostApplyGen addrs.DeposedKey
PostApplyNewState cty.Value
PostApplyError error
PostApplyReturn HookAction
PostApplyReturnError error
PostApplyFn func(addrs.AbsResourceInstance, states.Generation, cty.Value, error) (HookAction, error)
PostApplyFn func(addrs.AbsResourceInstance, addrs.DeposedKey, cty.Value, error) (HookAction, error)
PreDiffCalled bool
PreDiffAddr addrs.AbsResourceInstance
PreDiffGen states.Generation
PreDiffGen addrs.DeposedKey
PreDiffPriorState cty.Value
PreDiffProposedState cty.Value
PreDiffReturn HookAction
@ -47,7 +47,7 @@ type MockHook struct {
PostDiffCalled bool
PostDiffAddr addrs.AbsResourceInstance
PostDiffGen states.Generation
PostDiffGen addrs.DeposedKey
PostDiffAction plans.Action
PostDiffPriorState cty.Value
PostDiffPlannedState cty.Value
@ -86,14 +86,14 @@ type MockHook struct {
PreRefreshCalled bool
PreRefreshAddr addrs.AbsResourceInstance
PreRefreshGen states.Generation
PreRefreshGen addrs.DeposedKey
PreRefreshPriorState cty.Value
PreRefreshReturn HookAction
PreRefreshError error
PostRefreshCalled bool
PostRefreshAddr addrs.AbsResourceInstance
PostRefreshGen states.Generation
PostRefreshGen addrs.DeposedKey
PostRefreshPriorState cty.Value
PostRefreshNewState cty.Value
PostRefreshReturn HookAction
@ -141,55 +141,55 @@ type MockHook struct {
var _ Hook = (*MockHook)(nil)
func (h *MockHook) PreApply(addr addrs.AbsResourceInstance, gen states.Generation, action plans.Action, priorState, plannedNewState cty.Value) (HookAction, error) {
func (h *MockHook) PreApply(addr addrs.AbsResourceInstance, dk addrs.DeposedKey, action plans.Action, priorState, plannedNewState cty.Value) (HookAction, error) {
h.Lock()
defer h.Unlock()
h.PreApplyCalled = true
h.PreApplyAddr = addr
h.PreApplyGen = gen
h.PreApplyGen = dk
h.PreApplyAction = action
h.PreApplyPriorState = priorState
h.PreApplyPlannedState = plannedNewState
return h.PreApplyReturn, h.PreApplyError
}
func (h *MockHook) PostApply(addr addrs.AbsResourceInstance, gen states.Generation, newState cty.Value, err error) (HookAction, error) {
func (h *MockHook) PostApply(addr addrs.AbsResourceInstance, dk addrs.DeposedKey, newState cty.Value, err error) (HookAction, error) {
h.Lock()
defer h.Unlock()
h.PostApplyCalled = true
h.PostApplyAddr = addr
h.PostApplyGen = gen
h.PostApplyGen = dk
h.PostApplyNewState = newState
h.PostApplyError = err
if h.PostApplyFn != nil {
return h.PostApplyFn(addr, gen, newState, err)
return h.PostApplyFn(addr, dk, newState, err)
}
return h.PostApplyReturn, h.PostApplyReturnError
}
func (h *MockHook) PreDiff(addr addrs.AbsResourceInstance, gen states.Generation, priorState, proposedNewState cty.Value) (HookAction, error) {
func (h *MockHook) PreDiff(addr addrs.AbsResourceInstance, dk addrs.DeposedKey, priorState, proposedNewState cty.Value) (HookAction, error) {
h.Lock()
defer h.Unlock()
h.PreDiffCalled = true
h.PreDiffAddr = addr
h.PreDiffGen = gen
h.PreDiffGen = dk
h.PreDiffPriorState = priorState
h.PreDiffProposedState = proposedNewState
return h.PreDiffReturn, h.PreDiffError
}
func (h *MockHook) PostDiff(addr addrs.AbsResourceInstance, gen states.Generation, action plans.Action, priorState, plannedNewState cty.Value) (HookAction, error) {
func (h *MockHook) PostDiff(addr addrs.AbsResourceInstance, dk addrs.DeposedKey, action plans.Action, priorState, plannedNewState cty.Value) (HookAction, error) {
h.Lock()
defer h.Unlock()
h.PostDiffCalled = true
h.PostDiffAddr = addr
h.PostDiffGen = gen
h.PostDiffGen = dk
h.PostDiffAction = action
h.PostDiffPriorState = priorState
h.PostDiffPlannedState = plannedNewState
@ -247,18 +247,18 @@ func (h *MockHook) ProvisionOutput(addr addrs.AbsResourceInstance, typeName stri
h.ProvisionOutputMessage = line
}
func (h *MockHook) PreRefresh(addr addrs.AbsResourceInstance, gen states.Generation, priorState cty.Value) (HookAction, error) {
func (h *MockHook) PreRefresh(addr addrs.AbsResourceInstance, dk addrs.DeposedKey, priorState cty.Value) (HookAction, error) {
h.Lock()
defer h.Unlock()
h.PreRefreshCalled = true
h.PreRefreshAddr = addr
h.PreRefreshGen = gen
h.PreRefreshGen = dk
h.PreRefreshPriorState = priorState
return h.PreRefreshReturn, h.PreRefreshError
}
func (h *MockHook) PostRefresh(addr addrs.AbsResourceInstance, gen states.Generation, priorState cty.Value, newState cty.Value) (HookAction, error) {
func (h *MockHook) PostRefresh(addr addrs.AbsResourceInstance, dk addrs.DeposedKey, priorState cty.Value, newState cty.Value) (HookAction, error) {
h.Lock()
defer h.Unlock()

@ -23,19 +23,19 @@ type stopHook struct {
var _ Hook = (*stopHook)(nil)
func (h *stopHook) PreApply(addr addrs.AbsResourceInstance, gen states.Generation, action plans.Action, priorState, plannedNewState cty.Value) (HookAction, error) {
func (h *stopHook) PreApply(addr addrs.AbsResourceInstance, dk addrs.DeposedKey, action plans.Action, priorState, plannedNewState cty.Value) (HookAction, error) {
return h.hook()
}
func (h *stopHook) PostApply(addr addrs.AbsResourceInstance, gen states.Generation, newState cty.Value, err error) (HookAction, error) {
func (h *stopHook) PostApply(addr addrs.AbsResourceInstance, dk addrs.DeposedKey, newState cty.Value, err error) (HookAction, error) {
return h.hook()
}
func (h *stopHook) PreDiff(addr addrs.AbsResourceInstance, gen states.Generation, priorState, proposedNewState cty.Value) (HookAction, error) {
func (h *stopHook) PreDiff(addr addrs.AbsResourceInstance, dk addrs.DeposedKey, priorState, proposedNewState cty.Value) (HookAction, error) {
return h.hook()
}
func (h *stopHook) PostDiff(addr addrs.AbsResourceInstance, gen states.Generation, action plans.Action, priorState, plannedNewState cty.Value) (HookAction, error) {
func (h *stopHook) PostDiff(addr addrs.AbsResourceInstance, dk addrs.DeposedKey, action plans.Action, priorState, plannedNewState cty.Value) (HookAction, error) {
return h.hook()
}
@ -58,11 +58,11 @@ func (h *stopHook) PostProvisionInstanceStep(addr addrs.AbsResourceInstance, typ
func (h *stopHook) ProvisionOutput(addr addrs.AbsResourceInstance, typeName string, line string) {
}
func (h *stopHook) PreRefresh(addr addrs.AbsResourceInstance, gen states.Generation, priorState cty.Value) (HookAction, error) {
func (h *stopHook) PreRefresh(addr addrs.AbsResourceInstance, dk addrs.DeposedKey, priorState cty.Value) (HookAction, error) {
return h.hook()
}
func (h *stopHook) PostRefresh(addr addrs.AbsResourceInstance, gen states.Generation, priorState cty.Value, newState cty.Value) (HookAction, error) {
func (h *stopHook) PostRefresh(addr addrs.AbsResourceInstance, dk addrs.DeposedKey, priorState cty.Value, newState cty.Value) (HookAction, error) {
return h.hook()
}

@ -37,28 +37,28 @@ type testHookCall struct {
InstanceID string
}
func (h *testHook) PreApply(addr addrs.AbsResourceInstance, gen states.Generation, action plans.Action, priorState, plannedNewState cty.Value) (HookAction, error) {
func (h *testHook) PreApply(addr addrs.AbsResourceInstance, dk addrs.DeposedKey, action plans.Action, priorState, plannedNewState cty.Value) (HookAction, error) {
h.mu.Lock()
defer h.mu.Unlock()
h.Calls = append(h.Calls, &testHookCall{"PreApply", addr.String()})
return HookActionContinue, nil
}
func (h *testHook) PostApply(addr addrs.AbsResourceInstance, gen states.Generation, newState cty.Value, err error) (HookAction, error) {
func (h *testHook) PostApply(addr addrs.AbsResourceInstance, dk addrs.DeposedKey, newState cty.Value, err error) (HookAction, error) {
h.mu.Lock()
defer h.mu.Unlock()
h.Calls = append(h.Calls, &testHookCall{"PostApply", addr.String()})
return HookActionContinue, nil
}
func (h *testHook) PreDiff(addr addrs.AbsResourceInstance, gen states.Generation, priorState, proposedNewState cty.Value) (HookAction, error) {
func (h *testHook) PreDiff(addr addrs.AbsResourceInstance, dk addrs.DeposedKey, priorState, proposedNewState cty.Value) (HookAction, error) {
h.mu.Lock()
defer h.mu.Unlock()
h.Calls = append(h.Calls, &testHookCall{"PreDiff", addr.String()})
return HookActionContinue, nil
}
func (h *testHook) PostDiff(addr addrs.AbsResourceInstance, gen states.Generation, action plans.Action, priorState, plannedNewState cty.Value) (HookAction, error) {
func (h *testHook) PostDiff(addr addrs.AbsResourceInstance, dk addrs.DeposedKey, action plans.Action, priorState, plannedNewState cty.Value) (HookAction, error) {
h.mu.Lock()
defer h.mu.Unlock()
h.Calls = append(h.Calls, &testHookCall{"PostDiff", addr.String()})
@ -99,14 +99,14 @@ func (h *testHook) ProvisionOutput(addr addrs.AbsResourceInstance, typeName stri
h.Calls = append(h.Calls, &testHookCall{"ProvisionOutput", addr.String()})
}
func (h *testHook) PreRefresh(addr addrs.AbsResourceInstance, gen states.Generation, priorState cty.Value) (HookAction, error) {
func (h *testHook) PreRefresh(addr addrs.AbsResourceInstance, dk addrs.DeposedKey, priorState cty.Value) (HookAction, error) {
h.mu.Lock()
defer h.mu.Unlock()
h.Calls = append(h.Calls, &testHookCall{"PreRefresh", addr.String()})
return HookActionContinue, nil
}
func (h *testHook) PostRefresh(addr addrs.AbsResourceInstance, gen states.Generation, priorState cty.Value, newState cty.Value) (HookAction, error) {
func (h *testHook) PostRefresh(addr addrs.AbsResourceInstance, dk addrs.DeposedKey, priorState cty.Value, newState cty.Value) (HookAction, error) {
h.mu.Lock()
defer h.mu.Unlock()
h.Calls = append(h.Calls, &testHookCall{"PostRefresh", addr.String()})

@ -445,7 +445,7 @@ func (n *NodeAbstractResource) readResourceInstanceState(ctx EvalContext, addr a
log.Printf("[TRACE] readResourceInstanceState: reading state for %s", addr)
src := ctx.State().ResourceInstanceObject(addr, states.CurrentGen)
src := ctx.State().ResourceInstanceObject(addr, addrs.NotDeposed)
if src == nil {
// Presumably we only have deposed objects, then.
log.Printf("[TRACE] readResourceInstanceState: no state present for %s", addr)

@ -161,8 +161,7 @@ func (n *NodeAbstractResourceInstance) readDiff(ctx EvalContext, providerSchema
return nil, fmt.Errorf("provider does not support resource type %q", addr.Resource.Resource.Type)
}
gen := states.CurrentGen
csrc := changes.GetResourceInstanceChange(addr, gen)
csrc := changes.GetResourceInstanceChange(addr, addrs.NotDeposed)
if csrc == nil {
log.Printf("[TRACE] readDiff: No planned change recorded for %s", n.Addr)
return nil, nil
@ -216,7 +215,7 @@ func (n *NodeAbstractResourceInstance) preApplyHook(ctx EvalContext, change *pla
plannedNewState := change.After
diags = diags.Append(ctx.Hook(func(h Hook) (HookAction, error) {
return h.PreApply(n.Addr, change.DeposedKey.Generation(), change.Action, priorState, plannedNewState)
return h.PreApply(n.Addr, change.DeposedKey, change.Action, priorState, plannedNewState)
}))
if diags.HasErrors() {
return diags
@ -239,7 +238,7 @@ func (n *NodeAbstractResourceInstance) postApplyHook(ctx EvalContext, state *sta
newState = cty.NullVal(cty.DynamicPseudoType)
}
diags = diags.Append(ctx.Hook(func(h Hook) (HookAction, error) {
return h.PostApply(n.Addr, nil, newState, err)
return h.PostApply(n.Addr, addrs.NotDeposed, newState, err)
}))
}
@ -484,11 +483,7 @@ func (n *NodeAbstractResourceInstance) writeChange(ctx EvalContext, change *plan
if change == nil {
// Caller sets nil to indicate that we need to remove a change from
// the set of changes.
gen := states.CurrentGen
if deposedKey != states.NotDeposed {
gen = deposedKey
}
changes.RemoveResourceInstanceChange(n.Addr, gen)
changes.RemoveResourceInstanceChange(n.Addr, deposedKey)
return nil
}
@ -566,14 +561,9 @@ func (n *NodeAbstractResourceInstance) refresh(ctx EvalContext, deposedKey state
return state, diags
}
hookGen := states.CurrentGen
if deposedKey != states.NotDeposed {
hookGen = deposedKey
}
// Call pre-refresh hook
diags = diags.Append(ctx.Hook(func(h Hook) (HookAction, error) {
return h.PreRefresh(absAddr, hookGen, state.Value)
return h.PreRefresh(absAddr, deposedKey, state.Value)
}))
if diags.HasErrors() {
return state, diags
@ -660,7 +650,7 @@ func (n *NodeAbstractResourceInstance) refresh(ctx EvalContext, deposedKey state
// Call post-refresh hook
diags = diags.Append(ctx.Hook(func(h Hook) (HookAction, error) {
return h.PostRefresh(absAddr, hookGen, priorVal, ret.Value)
return h.PostRefresh(absAddr, deposedKey, priorVal, ret.Value)
}))
if diags.HasErrors() {
return ret, diags
@ -824,7 +814,7 @@ func (n *NodeAbstractResourceInstance) plan(
// Call pre-diff hook
diags = diags.Append(ctx.Hook(func(h Hook) (HookAction, error) {
return h.PreDiff(n.Addr, states.CurrentGen, priorVal, proposedNewVal)
return h.PreDiff(n.Addr, addrs.NotDeposed, priorVal, proposedNewVal)
}))
if diags.HasErrors() {
return nil, nil, keyData, diags
@ -1178,7 +1168,7 @@ func (n *NodeAbstractResourceInstance) plan(
// Call post-refresh hook
diags = diags.Append(ctx.Hook(func(h Hook) (HookAction, error) {
return h.PostDiff(n.Addr, states.CurrentGen, action, priorVal, plannedNewVal)
return h.PostDiff(n.Addr, addrs.NotDeposed, action, priorVal, plannedNewVal)
}))
if diags.HasErrors() {
return nil, nil, keyData, diags
@ -1505,7 +1495,7 @@ func (n *NodeAbstractResourceInstance) readDataSource(ctx EvalContext, configVal
log.Printf("[TRACE] readDataSource: %s configuration is complete, so reading from provider", n.Addr)
diags = diags.Append(ctx.Hook(func(h Hook) (HookAction, error) {
return h.PreApply(n.Addr, states.CurrentGen, plans.Read, cty.NullVal(configVal.Type()), configVal)
return h.PreApply(n.Addr, addrs.NotDeposed, plans.Read, cty.NullVal(configVal.Type()), configVal)
}))
if diags.HasErrors() {
return newVal, diags
@ -1588,7 +1578,7 @@ func (n *NodeAbstractResourceInstance) readDataSource(ctx EvalContext, configVal
}
diags = diags.Append(ctx.Hook(func(h Hook) (HookAction, error) {
return h.PostApply(n.Addr, states.CurrentGen, newVal, diags.Err())
return h.PostApply(n.Addr, addrs.NotDeposed, newVal, diags.Err())
}))
return newVal, diags
@ -1754,7 +1744,7 @@ func (n *NodeAbstractResourceInstance) planDataSource(ctx EvalContext, checkRule
}
diags = diags.Append(ctx.Hook(func(h Hook) (HookAction, error) {
return h.PostDiff(n.Addr, states.CurrentGen, plans.Read, priorVal, proposedNewVal)
return h.PostDiff(n.Addr, addrs.NotDeposed, plans.Read, priorVal, proposedNewVal)
}))
return plannedChange, plannedNewState, keyData, diags
@ -1944,7 +1934,7 @@ func (n *NodeAbstractResourceInstance) applyDataSource(ctx EvalContext, planned
diags = diags.Append(checkDiags)
if diags.HasErrors() {
diags = diags.Append(ctx.Hook(func(h Hook) (HookAction, error) {
return h.PostApply(n.Addr, states.CurrentGen, planned.Before, diags.Err())
return h.PostApply(n.Addr, addrs.NotDeposed, planned.Before, diags.Err())
}))
return nil, keyData, diags // failed preconditions prevent further evaluation
}

@ -122,7 +122,7 @@ func (n *NodeApplyableResourceInstance) Execute(ctx EvalContext, op walkOperatio
// to do and the change was left in the plan for informational
// purposes only.
changes := ctx.Changes()
csrc := changes.GetResourceInstanceChange(n.ResourceInstanceAddr(), states.CurrentGen)
csrc := changes.GetResourceInstanceChange(n.ResourceInstanceAddr(), addrs.NotDeposed)
if csrc == nil || csrc.Action == plans.NoOp {
log.Printf("[DEBUG] NodeApplyableResourceInstance: No config or planned change recorded for %s", n.Addr)
return nil

@ -263,7 +263,7 @@ type HookRecordApplyOrder struct {
l sync.Mutex
}
func (h *HookRecordApplyOrder) PreApply(addr addrs.AbsResourceInstance, gen states.Generation, action plans.Action, priorState, plannedNewState cty.Value) (HookAction, error) {
func (h *HookRecordApplyOrder) PreApply(addr addrs.AbsResourceInstance, dk addrs.DeposedKey, action plans.Action, priorState, plannedNewState cty.Value) (HookAction, error) {
if plannedNewState.RawEquals(priorState) {
return HookActionContinue, nil
}

Loading…
Cancel
Save