terraform: NodePlannableResourceInstanceOrphan refactor

This commit is contained in:
Kristin Laemmert 2020-09-25 11:18:14 -04:00
parent 9c721a4131
commit d1cf0279fa
2 changed files with 126 additions and 49 deletions

View File

@ -2,7 +2,6 @@ package terraform
import (
"github.com/hashicorp/terraform/plans"
"github.com/hashicorp/terraform/providers"
"github.com/hashicorp/terraform/states"
)
@ -20,65 +19,79 @@ var (
_ GraphNodeResourceInstance = (*NodePlannableResourceInstanceOrphan)(nil)
_ GraphNodeAttachResourceConfig = (*NodePlannableResourceInstanceOrphan)(nil)
_ GraphNodeAttachResourceState = (*NodePlannableResourceInstanceOrphan)(nil)
_ GraphNodeEvalable = (*NodePlannableResourceInstanceOrphan)(nil)
)
var (
_ GraphNodeEvalable = (*NodePlannableResourceInstanceOrphan)(nil)
_ GraphNodeExecutable = (*NodePlannableResourceInstanceOrphan)(nil)
)
func (n *NodePlannableResourceInstanceOrphan) Name() string {
return n.ResourceInstanceAddr().String() + " (orphan)"
}
// GraphNodeEvalable
func (n *NodePlannableResourceInstanceOrphan) EvalTree() EvalNode {
// GraphNodeExecutable
func (n *NodePlannableResourceInstanceOrphan) Execute(ctx EvalContext, op walkOperation) error {
addr := n.ResourceInstanceAddr()
// Declare a bunch of variables that are used for state during
// evaluation. Most of this are written to by-address below.
// evaluation. These are written to by-address below.
var change *plans.ResourceInstanceChange
var state *states.ResourceInstanceObject
var provider providers.Interface
var providerSchema *ProviderSchema
return &EvalSequence{
Nodes: []EvalNode{
&EvalGetProvider{
Addr: n.ResolvedProvider,
Output: &provider,
Schema: &providerSchema,
},
&EvalReadState{
Addr: addr.Resource,
Provider: &provider,
ProviderSchema: &providerSchema,
Output: &state,
},
&EvalDiffDestroy{
Addr: addr.Resource,
State: &state,
ProviderAddr: n.ResolvedProvider,
Output: &change,
OutputState: &state, // Will point to a nil state after this complete, signalling destroyed
},
&EvalCheckPreventDestroy{
Addr: addr.Resource,
Config: n.Config,
Change: &change,
},
&EvalWriteDiff{
Addr: addr.Resource,
ProviderSchema: &providerSchema,
Change: &change,
},
&EvalWriteState{
Addr: addr.Resource,
ProviderAddr: n.ResolvedProvider,
ProviderSchema: &providerSchema,
State: &state,
},
},
provider, providerSchema, err := GetProvider(ctx, n.ResolvedProvider)
if err != nil {
return err
}
//EvalReadState
readState := &EvalReadState{
Addr: addr.Resource,
Provider: &provider,
ProviderSchema: &providerSchema,
Output: &state,
}
_, err = readState.Eval(ctx)
if err != nil {
return err
}
diffDestroy := &EvalDiffDestroy{
Addr: addr.Resource,
State: &state,
ProviderAddr: n.ResolvedProvider,
Output: &change,
OutputState: &state, // Will point to a nil state after this complete, signalling destroyed
}
_, err = diffDestroy.Eval(ctx)
if err != nil {
return err
}
checkPreventDestroy := &EvalCheckPreventDestroy{
Addr: addr.Resource,
Config: n.Config,
Change: &change,
}
_, err = checkPreventDestroy.Eval(ctx)
if err != nil {
return err
}
writeDiff := &EvalWriteDiff{
Addr: addr.Resource,
ProviderSchema: &providerSchema,
Change: &change,
}
_, err = writeDiff.Eval(ctx)
if err != nil {
return err
}
writeState := &EvalWriteState{
Addr: addr.Resource,
ProviderAddr: n.ResolvedProvider,
ProviderSchema: &providerSchema,
State: &state,
}
_, err = writeState.Eval(ctx)
if err != nil {
return err
}
return nil
}

View File

@ -0,0 +1,64 @@
package terraform
import (
"testing"
"github.com/hashicorp/terraform/addrs"
"github.com/hashicorp/terraform/configs/configschema"
"github.com/hashicorp/terraform/instances"
"github.com/hashicorp/terraform/plans"
"github.com/hashicorp/terraform/states"
)
func TestNodeResourcePlanOrphanExecute(t *testing.T) {
state := states.NewState()
state.Module(addrs.RootModuleInstance).SetResourceInstanceCurrent(
addrs.Resource{
Mode: addrs.ManagedResourceMode,
Type: "test_object",
Name: "foo",
}.Instance(addrs.NoKey),
&states.ResourceInstanceObjectSrc{
AttrsFlat: map[string]string{
"test_string": "foo",
},
Status: states.ObjectReady,
},
addrs.AbsProviderConfig{
Provider: addrs.NewDefaultProvider("test"),
Module: addrs.RootModule,
},
)
p := simpleMockProvider()
ctx := &MockEvalContext{
StateState: state.SyncWrapper(),
InstanceExpanderExpander: instances.NewExpander(),
ProviderProvider: p,
ProviderSchemaSchema: &ProviderSchema{
ResourceTypes: map[string]*configschema.Block{
"test_object": simpleTestSchema(),
},
},
ChangesChanges: plans.NewChanges().SyncWrapper(),
}
node := NodePlannableResourceInstanceOrphan{
NodeAbstractResourceInstance: &NodeAbstractResourceInstance{
NodeAbstractResource: NodeAbstractResource{
ResolvedProvider: addrs.AbsProviderConfig{
Provider: addrs.NewDefaultProvider("test"),
Module: addrs.RootModule,
},
},
Addr: mustResourceInstanceAddr("test_object.foo"),
},
}
err := node.Execute(ctx, walkApply)
if err != nil {
t.Fatalf("unexpected error: %s", err.Error())
}
if !state.Empty() {
t.Fatalf("expected empty state, got %s", state.String())
}
}