core: EvalDiff handling of tainted objects

If the prior object is tainted, we behave as if it doesn't exist at all
for most of our logic here but then at the end turn it into a synthetic
replace operation going from the old object to the new object, similarly
to how we'd behave if given an argument change that "requires
replacement".
This commit is contained in:
Martin Atkins 2018-09-14 16:19:24 -07:00
parent 31c412b44d
commit a90d6cc599
1 changed files with 21 additions and 2 deletions

View File

@ -127,10 +127,21 @@ func (n *EvalDiff) Eval(ctx EvalContext) (interface{}, error) {
absAddr := n.Addr.Absolute(ctx.Path())
var priorVal cty.Value
var priorValTainted cty.Value
var priorPrivate []byte
if state != nil {
priorVal = state.Value
priorPrivate = state.Private
if state.Status != states.ObjectTainted {
priorVal = state.Value
priorPrivate = state.Private
} else {
// If the prior state is tainted then we'll proceed below like
// we're creating an entirely new object, but then turn it into
// a synthetic "Replace" change at the end, creating the same
// result as if the provider had marked at least one argument
// change as "requires replacement".
priorValTainted = state.Value
priorVal = cty.NullVal(schema.ImpliedType())
}
} else {
priorVal = cty.NullVal(schema.ImpliedType())
}
@ -312,6 +323,14 @@ func (n *EvalDiff) Eval(ctx EvalContext) (interface{}, error) {
}
}
// If our prior value was tainted then we actually want this to appear
// as a replace change, even though so far we've been treating it as a
// create.
if action == plans.Create && priorValTainted != cty.NilVal {
action = plans.Replace
priorVal = priorValTainted
}
// Call post-refresh hook
if !n.Stub {
err := ctx.Hook(func(h Hook) (HookAction, error) {