Merge pull request #27563 from hashicorp/jbardin/refresh-tainted
Error planning tainted resource when it no longer exists
This commit is contained in:
commit
543706c0d6
|
@ -0,0 +1 @@
|
||||||
|
package terraform
|
|
@ -12564,3 +12564,8 @@ resource "test_object" "a" {
|
||||||
t.Fatalf("error missing expected info: %q", errString)
|
t.Fatalf("error missing expected info: %q", errString)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// NOTE: Due to the size of this file, new tests should be added to
|
||||||
|
// context_apply2_test.go.
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
package terraform
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform/addrs"
|
||||||
|
"github.com/hashicorp/terraform/plans"
|
||||||
|
"github.com/hashicorp/terraform/providers"
|
||||||
|
"github.com/hashicorp/terraform/states"
|
||||||
|
"github.com/zclconf/go-cty/cty"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestContext2Plan_removedDuringRefresh(t *testing.T) {
|
||||||
|
// The resource was added to state but actually failed to create and was
|
||||||
|
// left tainted. This should be removed during plan and result in a Create
|
||||||
|
// action.
|
||||||
|
m := testModuleInline(t, map[string]string{
|
||||||
|
"main.tf": `
|
||||||
|
resource "test_object" "a" {
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
})
|
||||||
|
|
||||||
|
p := simpleMockProvider()
|
||||||
|
p.ReadResourceFn = func(req providers.ReadResourceRequest) (resp providers.ReadResourceResponse) {
|
||||||
|
resp.NewState = cty.NullVal(req.PriorState.Type())
|
||||||
|
return resp
|
||||||
|
}
|
||||||
|
|
||||||
|
addr := mustResourceInstanceAddr("test_object.a")
|
||||||
|
state := states.BuildState(func(s *states.SyncState) {
|
||||||
|
s.SetResourceInstanceCurrent(addr, &states.ResourceInstanceObjectSrc{
|
||||||
|
AttrsJSON: []byte(`{"test_string":"foo"}`),
|
||||||
|
Status: states.ObjectTainted,
|
||||||
|
}, mustProviderConfig(`provider["registry.terraform.io/hashicorp/test"]`))
|
||||||
|
})
|
||||||
|
|
||||||
|
ctx := testContext2(t, &ContextOpts{
|
||||||
|
Config: m,
|
||||||
|
State: state,
|
||||||
|
Providers: map[addrs.Provider]providers.Factory{
|
||||||
|
addrs.NewDefaultProvider("test"): testProviderFuncFixed(p),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
plan, diags := ctx.Plan()
|
||||||
|
if diags.HasErrors() {
|
||||||
|
t.Fatal(diags.Err())
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, c := range plan.Changes.Resources {
|
||||||
|
if c.Action != plans.Create {
|
||||||
|
t.Fatalf("expected Create action for missing %s, got %s", c.Addr, c.Action)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_, diags = ctx.Apply()
|
||||||
|
if diags.HasErrors() {
|
||||||
|
t.Fatal(diags.Err())
|
||||||
|
}
|
||||||
|
}
|
|
@ -6732,3 +6732,8 @@ output "planned" {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// NOTE: Due to the size of this file, new tests should be added to
|
||||||
|
// context_plan2_test.go.
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -905,7 +905,7 @@ func (n *NodeAbstractResourceInstance) plan(
|
||||||
// If our prior value was tainted then we actually want this to appear
|
// 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
|
// as a replace change, even though so far we've been treating it as a
|
||||||
// create.
|
// create.
|
||||||
if action == plans.Create && priorValTainted != cty.NilVal {
|
if action == plans.Create && !priorValTainted.IsNull() {
|
||||||
if createBeforeDestroy {
|
if createBeforeDestroy {
|
||||||
action = plans.CreateThenDelete
|
action = plans.CreateThenDelete
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -128,11 +128,12 @@ func (n *NodePlannableResourceInstance) managedResourceExecute(ctx EvalContext)
|
||||||
|
|
||||||
// Refresh, maybe
|
// Refresh, maybe
|
||||||
if !n.skipRefresh {
|
if !n.skipRefresh {
|
||||||
instanceRefreshState, refreshDiags := n.refresh(ctx, instanceRefreshState)
|
s, refreshDiags := n.refresh(ctx, instanceRefreshState)
|
||||||
diags = diags.Append(refreshDiags)
|
diags = diags.Append(refreshDiags)
|
||||||
if diags.HasErrors() {
|
if diags.HasErrors() {
|
||||||
return diags
|
return diags
|
||||||
}
|
}
|
||||||
|
instanceRefreshState = s
|
||||||
|
|
||||||
diags = diags.Append(n.writeResourceInstanceState(ctx, instanceRefreshState, n.Dependencies, refreshState))
|
diags = diags.Append(n.writeResourceInstanceState(ctx, instanceRefreshState, n.Dependencies, refreshState))
|
||||||
if diags.HasErrors() {
|
if diags.HasErrors() {
|
||||||
|
|
Loading…
Reference in New Issue