core: Plan drift includes move-only changes

Previously, drifted resources included only updates and deletes. To
correctly display the full changes which would result as part of a
refresh-only apply, the drifted resources must also include move-only
changes.
This commit is contained in:
Alisdair McDiarmid 2021-09-16 12:42:00 -04:00
parent 9a7bbdab6f
commit 61b2d8e3fe
1 changed files with 27 additions and 9 deletions

View File

@ -499,6 +499,14 @@ func (c *Context) driftedResources(config *configs.Config, oldState, newState *s
continue continue
} }
addr := rs.Addr.Instance(key) addr := rs.Addr.Instance(key)
// Previous run address defaults to the current address, but
// can differ if the resource moved before refreshing
prevRunAddr := addr
if move, ok := moves[addr.UniqueKey()]; ok {
prevRunAddr = move.From
}
newIS := newState.ResourceInstance(addr) newIS := newState.ResourceInstance(addr)
schema, _ := schemas.ResourceTypeConfig( schema, _ := schemas.ResourceTypeConfig(
@ -547,20 +555,30 @@ func (c *Context) driftedResources(config *configs.Config, oldState, newState *s
newVal = cty.NullVal(ty) newVal = cty.NullVal(ty)
} }
if oldVal.RawEquals(newVal) { if oldVal.RawEquals(newVal) && addr.Equal(prevRunAddr) {
// No drift if the two values are semantically equivalent // No drift if the two values are semantically equivalent
// and no move has happened
continue continue
} }
// We can only detect updates and deletes as drift. // We can detect three types of changes after refreshing state,
action := plans.Update // only two of which are easily understood as "drift":
if newVal.IsNull() { //
// - Resources which were deleted outside of Terraform;
// - Resources where the object value has changed outside of
// Terraform;
// - Resources which have been moved without other changes.
//
// All of these are returned as drift, to allow refresh-only plans
// to present a full set of changes which will be applied.
var action plans.Action
switch {
case newVal.IsNull():
action = plans.Delete action = plans.Delete
} case !oldVal.RawEquals(newVal):
action = plans.Update
prevRunAddr := addr default:
if move, ok := moves[addr.UniqueKey()]; ok { action = plans.NoOp
prevRunAddr = move.From
} }
change := &plans.ResourceInstanceChange{ change := &plans.ResourceInstanceChange{