Merge pull request #26343 from hashicorp/jbardin/update-cbd-state

Update create_before_destroy in state during refresh
This commit is contained in:
James Bardin 2020-09-24 10:03:18 -04:00 committed by GitHub
commit 435d8bdbae
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 92 additions and 0 deletions

View File

@ -1689,3 +1689,56 @@ aws_instance.foo:
checkStateString(t, result, expect) checkStateString(t, result, expect)
} }
// verify that create_before_destroy is updated in the state during refresh
func TestRefresh_updateLifecycle(t *testing.T) {
state := states.NewState()
root := state.EnsureModule(addrs.RootModuleInstance)
root.SetResourceInstanceCurrent(
addrs.Resource{
Mode: addrs.ManagedResourceMode,
Type: "aws_instance",
Name: "bar",
}.Instance(addrs.NoKey),
&states.ResourceInstanceObjectSrc{
Status: states.ObjectReady,
AttrsJSON: []byte(`{"id":"bar"}`),
},
addrs.AbsProviderConfig{
Provider: addrs.NewDefaultProvider("aws"),
Module: addrs.RootModule,
},
)
m := testModuleInline(t, map[string]string{
"main.tf": `
resource "aws_instance" "bar" {
lifecycle {
create_before_destroy = true
}
}
`,
})
p := testProvider("aws")
p.ApplyFn = testApplyFn
p.DiffFn = testDiffFn
ctx := testContext2(t, &ContextOpts{
Config: m,
Providers: map[addrs.Provider]providers.Factory{
addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p),
},
State: state,
})
state, diags := ctx.Refresh()
if diags.HasErrors() {
t.Fatalf("plan errors: %s", diags.Err())
}
r := state.ResourceInstance(mustResourceInstanceAddr("aws_instance.bar"))
if !r.Current.CreateBeforeDestroy {
t.Fatal("create_before_destroy not updated in instance state")
}
}

View File

@ -529,3 +529,36 @@ func (n *EvalWriteResourceState) Eval(ctx EvalContext) (interface{}, error) {
return nil, nil return nil, nil
} }
// EvalRefreshLifecycle is an EvalNode implementation that updates
// the status of the lifecycle options stored in the state.
// This currently only applies to create_before_destroy.
type EvalRefreshLifecycle struct {
Addr addrs.AbsResourceInstance
Config *configs.Resource
// Prior State
State **states.ResourceInstanceObject
// ForceCreateBeforeDestroy indicates a create_before_destroy resource
// depends on this resource.
ForceCreateBeforeDestroy bool
}
func (n *EvalRefreshLifecycle) Eval(ctx EvalContext) (interface{}, error) {
state := *n.State
if state == nil {
// no existing state
return nil, nil
}
// In 0.13 we could be refreshing a resource with no config.
// We should be operating on managed resource, but check here to be certain
if n.Config == nil || n.Config.Managed == nil {
log.Printf("[WARN] EvalRefreshLifecycle: no Managed config value found in instance state for %q", n.Addr)
return nil, nil
}
state.CreateBeforeDestroy = n.Config.Managed.CreateBeforeDestroy || n.ForceCreateBeforeDestroy
return nil, nil
}

View File

@ -148,6 +148,12 @@ func (n *NodePlannableResourceInstance) evalTreeManagedResource(addr addrs.AbsRe
ProviderSchema: &providerSchema, ProviderSchema: &providerSchema,
Output: &instanceRefreshState, Output: &instanceRefreshState,
}, },
&EvalRefreshLifecycle{
Addr: addr,
Config: n.Config,
State: &instanceRefreshState,
ForceCreateBeforeDestroy: n.ForceCreateBeforeDestroy,
},
&EvalRefresh{ &EvalRefresh{
Addr: addr.Resource, Addr: addr.Resource,
ProviderAddr: n.ResolvedProvider, ProviderAddr: n.ResolvedProvider,