@ -59,6 +59,18 @@ func (n *EvalCheckPlannedChange) Eval(ctx EvalContext) (interface{}, error) {
// all of the unknown values, since the final values might actually
// match what was there before after all.
log . Printf ( "[DEBUG] After incorporating new values learned so far during apply, %s change has become NoOp" , absAddr )
case ( plannedChange . Action == plans . CreateThenDelete && actualChange . Action == plans . DeleteThenCreate ) ||
( plannedChange . Action == plans . DeleteThenCreate && actualChange . Action == plans . CreateThenDelete ) :
// If the order of replacement changed, then that is a bug in terraform
diags = diags . Append ( tfdiags . Sourceless (
tfdiags . Error ,
"Terraform produced inconsistent final plan" ,
fmt . Sprintf (
"When expanding the plan for %s to include new values learned so far during apply, the planned action changed from %s to %s.\n\nThis is a bug in Terraform and should be reported." ,
absAddr , plannedChange . Action , actualChange . Action ,
) ,
) )
default :
diags = diags . Append ( tfdiags . Sourceless (
tfdiags . Error ,
@ -118,6 +130,12 @@ func (n *EvalDiff) Eval(ctx EvalContext) (interface{}, error) {
provider := * n . Provider
providerSchema := * n . ProviderSchema
createBeforeDestroy := n . CreateBeforeDestroy
if n . PreviousDiff != nil {
// If we already planned the action, we stick to that plan
createBeforeDestroy = ( * n . PreviousDiff ) . Action == plans . CreateThenDelete
}
if providerSchema == nil {
return nil , fmt . Errorf ( "provider schema is unavailable for %s" , n . Addr )
}
@ -388,7 +406,7 @@ func (n *EvalDiff) Eval(ctx EvalContext) (interface{}, error) {
case ! reqRep . Empty ( ) :
// If there are any "requires replace" paths left _after our filtering
// above_ then this is a replace action.
if n. C reateBeforeDestroy {
if c reateBeforeDestroy {
action = plans . CreateThenDelete
} else {
action = plans . DeleteThenCreate
@ -454,7 +472,7 @@ func (n *EvalDiff) Eval(ctx EvalContext) (interface{}, error) {
// as a replace change, even though so far we've been treating it as a
// create.
if action == plans . Create && priorValTainted != cty . NilVal {
if n. C reateBeforeDestroy {
if c reateBeforeDestroy {
action = plans . CreateThenDelete
} else {
action = plans . DeleteThenCreate