mirror of
https://github.com/opentofu/opentofu.git
synced 2024-12-27 09:21:14 -06:00
terraform: make things more linear
This commit is contained in:
parent
67e7aeeea0
commit
93f3050dbd
@ -81,6 +81,24 @@ func (c *Context2) GraphBuilder() GraphBuilder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Apply applies the changes represented by this context and returns
|
||||||
|
// the resulting state.
|
||||||
|
//
|
||||||
|
// In addition to returning the resulting state, this context is updated
|
||||||
|
// with the latest state.
|
||||||
|
func (c *Context2) Apply() (*State, error) {
|
||||||
|
// Copy our own state
|
||||||
|
c.state = c.state.deepcopy()
|
||||||
|
|
||||||
|
// Do the walk
|
||||||
|
_, err := c.walk(walkApply)
|
||||||
|
|
||||||
|
// Clean out any unused things
|
||||||
|
c.state.prune()
|
||||||
|
|
||||||
|
return c.state, err
|
||||||
|
}
|
||||||
|
|
||||||
// Plan generates an execution plan for the given context.
|
// Plan generates an execution plan for the given context.
|
||||||
//
|
//
|
||||||
// The execution plan encapsulates the context and can be stored
|
// The execution plan encapsulates the context and can be stored
|
||||||
|
@ -2671,13 +2671,15 @@ func TestContextInput_varOnly(t *testing.T) {
|
|||||||
t.Fatalf("bad: \n%s", actualStr)
|
t.Fatalf("bad: \n%s", actualStr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
func TestContextApply(t *testing.T) {
|
/*
|
||||||
|
func TestContext2Apply(t *testing.T) {
|
||||||
m := testModule(t, "apply-good")
|
m := testModule(t, "apply-good")
|
||||||
p := testProvider("aws")
|
p := testProvider("aws")
|
||||||
p.ApplyFn = testApplyFn
|
p.ApplyFn = testApplyFn
|
||||||
p.DiffFn = testDiffFn
|
p.DiffFn = testDiffFn
|
||||||
ctx := testContext(t, &ContextOpts{
|
ctx := testContext2(t, &ContextOpts{
|
||||||
Module: m,
|
Module: m,
|
||||||
Providers: map[string]ResourceProviderFactory{
|
Providers: map[string]ResourceProviderFactory{
|
||||||
"aws": testProviderFuncFixed(p),
|
"aws": testProviderFuncFixed(p),
|
||||||
@ -2705,6 +2707,7 @@ func TestContextApply(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
func TestContextApply_emptyModule(t *testing.T) {
|
func TestContextApply_emptyModule(t *testing.T) {
|
||||||
m := testModule(t, "apply-empty-module")
|
m := testModule(t, "apply-empty-module")
|
||||||
p := testProvider("aws")
|
p := testProvider("aws")
|
||||||
|
@ -3,11 +3,12 @@ package terraform
|
|||||||
// EvalDiff is an EvalNode implementation that does a refresh for
|
// EvalDiff is an EvalNode implementation that does a refresh for
|
||||||
// a resource.
|
// a resource.
|
||||||
type EvalDiff struct {
|
type EvalDiff struct {
|
||||||
Info *InstanceInfo
|
Info *InstanceInfo
|
||||||
Config EvalNode
|
Config EvalNode
|
||||||
Provider EvalNode
|
Provider EvalNode
|
||||||
State EvalNode
|
State EvalNode
|
||||||
Output *InstanceDiff
|
Output **InstanceDiff
|
||||||
|
OutputState **InstanceState
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *EvalDiff) Args() ([]EvalNode, []EvalType) {
|
func (n *EvalDiff) Args() ([]EvalNode, []EvalType) {
|
||||||
@ -82,11 +83,12 @@ func (n *EvalDiff) Eval(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Update our output
|
// Update our output
|
||||||
*n.Output = *diff
|
*n.Output = diff
|
||||||
|
*n.OutputState = state
|
||||||
|
|
||||||
// Merge our state so that the state is updated with our plan
|
// Merge our state so that the state is updated with our plan
|
||||||
if !diff.Empty() {
|
if !diff.Empty() && n.OutputState != nil {
|
||||||
state = state.MergeDiff(diff)
|
*n.OutputState = state.MergeDiff(diff)
|
||||||
}
|
}
|
||||||
|
|
||||||
return state, nil
|
return state, nil
|
||||||
@ -101,7 +103,7 @@ func (n *EvalDiff) Type() EvalType {
|
|||||||
type EvalDiffDestroy struct {
|
type EvalDiffDestroy struct {
|
||||||
Info *InstanceInfo
|
Info *InstanceInfo
|
||||||
State EvalNode
|
State EvalNode
|
||||||
Output *InstanceDiff
|
Output **InstanceDiff
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *EvalDiffDestroy) Args() ([]EvalNode, []EvalType) {
|
func (n *EvalDiffDestroy) Args() ([]EvalNode, []EvalType) {
|
||||||
@ -142,7 +144,7 @@ func (n *EvalDiffDestroy) Eval(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Update our output
|
// Update our output
|
||||||
*n.Output = *diff
|
*n.Output = diff
|
||||||
|
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
@ -188,7 +190,7 @@ func (n *EvalDiffDestroyModule) Type() EvalType {
|
|||||||
// the full diff.
|
// the full diff.
|
||||||
type EvalDiffTainted struct {
|
type EvalDiffTainted struct {
|
||||||
Name string
|
Name string
|
||||||
Diff *InstanceDiff
|
Diff **InstanceDiff
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *EvalDiffTainted) Args() ([]EvalNode, []EvalType) {
|
func (n *EvalDiffTainted) Args() ([]EvalNode, []EvalType) {
|
||||||
@ -218,7 +220,7 @@ func (n *EvalDiffTainted) Eval(
|
|||||||
|
|
||||||
// If we have tainted, then mark it on the diff
|
// If we have tainted, then mark it on the diff
|
||||||
if len(rs.Tainted) > 0 {
|
if len(rs.Tainted) > 0 {
|
||||||
n.Diff.DestroyTainted = true
|
(*n.Diff).DestroyTainted = true
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, nil
|
return nil, nil
|
||||||
@ -228,11 +230,46 @@ func (n *EvalDiffTainted) Type() EvalType {
|
|||||||
return EvalTypeNull
|
return EvalTypeNull
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EvalReadDiff is an EvalNode implementation that writes the diff to
|
||||||
|
// the full diff.
|
||||||
|
type EvalReadDiff struct {
|
||||||
|
Name string
|
||||||
|
Diff **InstanceDiff
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *EvalReadDiff) Args() ([]EvalNode, []EvalType) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: test
|
||||||
|
func (n *EvalReadDiff) Eval(
|
||||||
|
ctx EvalContext, args []interface{}) (interface{}, error) {
|
||||||
|
diff, lock := ctx.Diff()
|
||||||
|
|
||||||
|
// Acquire the lock so that we can do this safely concurrently
|
||||||
|
lock.Lock()
|
||||||
|
defer lock.Unlock()
|
||||||
|
|
||||||
|
// Write the diff
|
||||||
|
modDiff := diff.ModuleByPath(ctx.Path())
|
||||||
|
if modDiff == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
*n.Diff = modDiff.Resources[n.Name]
|
||||||
|
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *EvalReadDiff) Type() EvalType {
|
||||||
|
return EvalTypeNull
|
||||||
|
}
|
||||||
|
|
||||||
// EvalWriteDiff is an EvalNode implementation that writes the diff to
|
// EvalWriteDiff is an EvalNode implementation that writes the diff to
|
||||||
// the full diff.
|
// the full diff.
|
||||||
type EvalWriteDiff struct {
|
type EvalWriteDiff struct {
|
||||||
Name string
|
Name string
|
||||||
Diff *InstanceDiff
|
Diff **InstanceDiff
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *EvalWriteDiff) Args() ([]EvalNode, []EvalType) {
|
func (n *EvalWriteDiff) Args() ([]EvalNode, []EvalType) {
|
||||||
@ -245,7 +282,7 @@ func (n *EvalWriteDiff) Eval(
|
|||||||
diff, lock := ctx.Diff()
|
diff, lock := ctx.Diff()
|
||||||
|
|
||||||
// The diff to write, if its empty it should write nil
|
// The diff to write, if its empty it should write nil
|
||||||
diffVal := n.Diff
|
diffVal := *n.Diff
|
||||||
if diffVal.Empty() {
|
if diffVal.Empty() {
|
||||||
diffVal = nil
|
diffVal = nil
|
||||||
}
|
}
|
||||||
|
@ -55,7 +55,8 @@ func (n *EvalInitProvider) Type() EvalType {
|
|||||||
// EvalGetProvider is an EvalNode implementation that retrieves an already
|
// EvalGetProvider is an EvalNode implementation that retrieves an already
|
||||||
// initialized provider instance for the given name.
|
// initialized provider instance for the given name.
|
||||||
type EvalGetProvider struct {
|
type EvalGetProvider struct {
|
||||||
Name string
|
Name string
|
||||||
|
Output *ResourceProvider
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *EvalGetProvider) Args() ([]EvalNode, []EvalType) {
|
func (n *EvalGetProvider) Args() ([]EvalNode, []EvalType) {
|
||||||
@ -69,6 +70,10 @@ func (n *EvalGetProvider) Eval(
|
|||||||
return nil, fmt.Errorf("provider %s not initialized", n.Name)
|
return nil, fmt.Errorf("provider %s not initialized", n.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if n.Output != nil {
|
||||||
|
*n.Output = result
|
||||||
|
}
|
||||||
|
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,29 +1,31 @@
|
|||||||
package terraform
|
package terraform
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
)
|
||||||
|
|
||||||
// EvalRefresh is an EvalNode implementation that does a refresh for
|
// EvalRefresh is an EvalNode implementation that does a refresh for
|
||||||
// a resource.
|
// a resource.
|
||||||
type EvalRefresh struct {
|
type EvalRefresh struct {
|
||||||
Provider EvalNode
|
Provider EvalNode
|
||||||
State EvalNode
|
State **InstanceState
|
||||||
Info *InstanceInfo
|
Info *InstanceInfo
|
||||||
|
Output **InstanceState
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *EvalRefresh) Args() ([]EvalNode, []EvalType) {
|
func (n *EvalRefresh) Args() ([]EvalNode, []EvalType) {
|
||||||
return []EvalNode{n.Provider, n.State},
|
return []EvalNode{n.Provider}, []EvalType{EvalTypeResourceProvider}
|
||||||
[]EvalType{EvalTypeResourceProvider, EvalTypeInstanceState}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: test
|
// TODO: test
|
||||||
func (n *EvalRefresh) Eval(
|
func (n *EvalRefresh) Eval(
|
||||||
ctx EvalContext, args []interface{}) (interface{}, error) {
|
ctx EvalContext, args []interface{}) (interface{}, error) {
|
||||||
var state *InstanceState
|
|
||||||
provider := args[0].(ResourceProvider)
|
provider := args[0].(ResourceProvider)
|
||||||
if args[1] != nil {
|
state := *n.State
|
||||||
state = args[1].(*InstanceState)
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we have no state, we don't do any refreshing
|
// If we have no state, we don't do any refreshing
|
||||||
if state == nil {
|
if state == nil {
|
||||||
|
log.Printf("[DEBUG] refresh: %s: no state, not refreshing", n.Info.Id)
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,6 +51,9 @@ func (n *EvalRefresh) Eval(
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if n.Output != nil {
|
||||||
|
*n.Output = state
|
||||||
|
}
|
||||||
return state, nil
|
return state, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ type EvalReadState struct {
|
|||||||
Name string
|
Name string
|
||||||
Tainted bool
|
Tainted bool
|
||||||
TaintedIndex int
|
TaintedIndex int
|
||||||
|
Output **InstanceState
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *EvalReadState) Args() ([]EvalNode, []EvalType) {
|
func (n *EvalReadState) Args() ([]EvalNode, []EvalType) {
|
||||||
@ -37,13 +38,21 @@ func (n *EvalReadState) Eval(
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var result *InstanceState
|
||||||
if !n.Tainted {
|
if !n.Tainted {
|
||||||
// Return the primary
|
// Return the primary
|
||||||
return rs.Primary, nil
|
result = rs.Primary
|
||||||
} else {
|
} else {
|
||||||
// Return the proper tainted resource
|
// Return the proper tainted resource
|
||||||
return rs.Tainted[n.TaintedIndex], nil
|
result = rs.Tainted[n.TaintedIndex]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Write the result to the output pointer
|
||||||
|
if n.Output != nil {
|
||||||
|
*n.Output = result
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *EvalReadState) Type() EvalType {
|
func (n *EvalReadState) Type() EvalType {
|
||||||
@ -56,23 +65,18 @@ type EvalWriteState struct {
|
|||||||
Name string
|
Name string
|
||||||
ResourceType string
|
ResourceType string
|
||||||
Dependencies []string
|
Dependencies []string
|
||||||
State EvalNode
|
State **InstanceState
|
||||||
Tainted bool
|
Tainted bool
|
||||||
TaintedIndex int
|
TaintedIndex int
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *EvalWriteState) Args() ([]EvalNode, []EvalType) {
|
func (n *EvalWriteState) Args() ([]EvalNode, []EvalType) {
|
||||||
return []EvalNode{n.State}, []EvalType{EvalTypeInstanceState}
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: test
|
// TODO: test
|
||||||
func (n *EvalWriteState) Eval(
|
func (n *EvalWriteState) Eval(
|
||||||
ctx EvalContext, args []interface{}) (interface{}, error) {
|
ctx EvalContext, args []interface{}) (interface{}, error) {
|
||||||
var instanceState *InstanceState
|
|
||||||
if args[0] != nil {
|
|
||||||
instanceState = args[0].(*InstanceState)
|
|
||||||
}
|
|
||||||
|
|
||||||
state, lock := ctx.State()
|
state, lock := ctx.State()
|
||||||
if state == nil {
|
if state == nil {
|
||||||
return nil, fmt.Errorf("cannot write state to nil state")
|
return nil, fmt.Errorf("cannot write state to nil state")
|
||||||
@ -100,11 +104,11 @@ func (n *EvalWriteState) Eval(
|
|||||||
|
|
||||||
if n.Tainted {
|
if n.Tainted {
|
||||||
if n.TaintedIndex != -1 {
|
if n.TaintedIndex != -1 {
|
||||||
rs.Tainted[n.TaintedIndex] = instanceState
|
rs.Tainted[n.TaintedIndex] = *n.State
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Set the primary state
|
// Set the primary state
|
||||||
rs.Primary = instanceState
|
rs.Primary = *n.State
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prune because why not, we can clear out old useless entries now
|
// Prune because why not, we can clear out old useless entries now
|
||||||
|
@ -550,7 +550,7 @@ func (r *ResourceState) prune() {
|
|||||||
n := len(r.Tainted)
|
n := len(r.Tainted)
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
inst := r.Tainted[i]
|
inst := r.Tainted[i]
|
||||||
if inst.ID == "" {
|
if inst == nil || inst.ID == "" {
|
||||||
copy(r.Tainted[i:], r.Tainted[i+1:])
|
copy(r.Tainted[i:], r.Tainted[i+1:])
|
||||||
r.Tainted[n-1] = nil
|
r.Tainted[n-1] = nil
|
||||||
n--
|
n--
|
||||||
|
@ -171,6 +171,8 @@ func (n *graphNodeOrphanResource) ProvidedBy() []string {
|
|||||||
|
|
||||||
// GraphNodeEvalable impl.
|
// GraphNodeEvalable impl.
|
||||||
func (n *graphNodeOrphanResource) EvalTree() EvalNode {
|
func (n *graphNodeOrphanResource) EvalTree() EvalNode {
|
||||||
|
var state *InstanceState
|
||||||
|
|
||||||
seq := &EvalSequence{Nodes: make([]EvalNode, 0, 5)}
|
seq := &EvalSequence{Nodes: make([]EvalNode, 0, 5)}
|
||||||
|
|
||||||
// Build instance info
|
// Build instance info
|
||||||
@ -180,22 +182,30 @@ func (n *graphNodeOrphanResource) EvalTree() EvalNode {
|
|||||||
// Refresh the resource
|
// Refresh the resource
|
||||||
seq.Nodes = append(seq.Nodes, &EvalOpFilter{
|
seq.Nodes = append(seq.Nodes, &EvalOpFilter{
|
||||||
Ops: []walkOperation{walkRefresh},
|
Ops: []walkOperation{walkRefresh},
|
||||||
Node: &EvalWriteState{
|
Node: &EvalSequence{
|
||||||
Name: n.ResourceName,
|
Nodes: []EvalNode{
|
||||||
ResourceType: n.ResourceType,
|
&EvalReadState{
|
||||||
Dependencies: n.DependentOn(),
|
Name: n.ResourceName,
|
||||||
State: &EvalRefresh{
|
Output: &state,
|
||||||
Info: info,
|
},
|
||||||
Provider: &EvalGetProvider{Name: n.ProvidedBy()[0]},
|
&EvalRefresh{
|
||||||
State: &EvalReadState{
|
Info: info,
|
||||||
Name: n.ResourceName,
|
Provider: &EvalGetProvider{Name: n.ProvidedBy()[0]},
|
||||||
|
State: &state,
|
||||||
|
Output: &state,
|
||||||
|
},
|
||||||
|
&EvalWriteState{
|
||||||
|
Name: n.ResourceName,
|
||||||
|
ResourceType: n.ResourceType,
|
||||||
|
Dependencies: n.DependentOn(),
|
||||||
|
State: &state,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
// Diff the resource
|
// Diff the resource
|
||||||
var diff InstanceDiff
|
var diff *InstanceDiff
|
||||||
seq.Nodes = append(seq.Nodes, &EvalOpFilter{
|
seq.Nodes = append(seq.Nodes, &EvalOpFilter{
|
||||||
Ops: []walkOperation{walkPlan, walkPlanDestroy},
|
Ops: []walkOperation{walkPlan, walkPlanDestroy},
|
||||||
Node: &EvalSequence{
|
Node: &EvalSequence{
|
||||||
|
@ -98,6 +98,9 @@ func (n *graphNodeExpandedResource) ProvidedBy() []string {
|
|||||||
|
|
||||||
// GraphNodeEvalable impl.
|
// GraphNodeEvalable impl.
|
||||||
func (n *graphNodeExpandedResource) EvalTree() EvalNode {
|
func (n *graphNodeExpandedResource) EvalTree() EvalNode {
|
||||||
|
var diff *InstanceDiff
|
||||||
|
var state *InstanceState
|
||||||
|
|
||||||
// Build the resource. If we aren't part of a multi-resource, then
|
// Build the resource. If we aren't part of a multi-resource, then
|
||||||
// we still consider ourselves as count index zero.
|
// we still consider ourselves as count index zero.
|
||||||
index := n.Index
|
index := n.Index
|
||||||
@ -145,35 +148,46 @@ func (n *graphNodeExpandedResource) EvalTree() EvalNode {
|
|||||||
// Refresh the resource
|
// Refresh the resource
|
||||||
seq.Nodes = append(seq.Nodes, &EvalOpFilter{
|
seq.Nodes = append(seq.Nodes, &EvalOpFilter{
|
||||||
Ops: []walkOperation{walkRefresh},
|
Ops: []walkOperation{walkRefresh},
|
||||||
Node: &EvalWriteState{
|
Node: &EvalSequence{
|
||||||
Name: n.stateId(),
|
Nodes: []EvalNode{
|
||||||
ResourceType: n.Resource.Type,
|
&EvalReadState{
|
||||||
Dependencies: n.DependentOn(),
|
Name: n.stateId(),
|
||||||
State: &EvalRefresh{
|
Output: &state,
|
||||||
Info: info,
|
},
|
||||||
Provider: &EvalGetProvider{Name: n.ProvidedBy()[0]},
|
&EvalRefresh{
|
||||||
State: &EvalReadState{Name: n.stateId()},
|
Info: info,
|
||||||
|
Provider: &EvalGetProvider{Name: n.ProvidedBy()[0]},
|
||||||
|
State: &state,
|
||||||
|
Output: &state,
|
||||||
|
},
|
||||||
|
&EvalWriteState{
|
||||||
|
Name: n.stateId(),
|
||||||
|
ResourceType: n.Resource.Type,
|
||||||
|
Dependencies: n.DependentOn(),
|
||||||
|
State: &state,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
// Diff the resource
|
// Diff the resource
|
||||||
var diff InstanceDiff
|
|
||||||
seq.Nodes = append(seq.Nodes, &EvalOpFilter{
|
seq.Nodes = append(seq.Nodes, &EvalOpFilter{
|
||||||
Ops: []walkOperation{walkPlan},
|
Ops: []walkOperation{walkPlan},
|
||||||
Node: &EvalSequence{
|
Node: &EvalSequence{
|
||||||
Nodes: []EvalNode{
|
Nodes: []EvalNode{
|
||||||
|
&EvalDiff{
|
||||||
|
Info: info,
|
||||||
|
Config: interpolateNode,
|
||||||
|
Provider: &EvalGetProvider{Name: n.ProvidedBy()[0]},
|
||||||
|
State: &EvalReadState{Name: n.stateId()},
|
||||||
|
Output: &diff,
|
||||||
|
OutputState: &state,
|
||||||
|
},
|
||||||
&EvalWriteState{
|
&EvalWriteState{
|
||||||
Name: n.stateId(),
|
Name: n.stateId(),
|
||||||
ResourceType: n.Resource.Type,
|
ResourceType: n.Resource.Type,
|
||||||
Dependencies: n.DependentOn(),
|
Dependencies: n.DependentOn(),
|
||||||
State: &EvalDiff{
|
State: &state,
|
||||||
Info: info,
|
|
||||||
Config: interpolateNode,
|
|
||||||
Provider: &EvalGetProvider{Name: n.ProvidedBy()[0]},
|
|
||||||
State: &EvalReadState{Name: n.stateId()},
|
|
||||||
Output: &diff,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
&EvalDiffTainted{
|
&EvalDiffTainted{
|
||||||
Diff: &diff,
|
Diff: &diff,
|
||||||
@ -205,6 +219,41 @@ func (n *graphNodeExpandedResource) EvalTree() EvalNode {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Diff the resource for destruction
|
||||||
|
var provider ResourceProvider
|
||||||
|
seq.Nodes = append(seq.Nodes, &EvalOpFilter{
|
||||||
|
Ops: []walkOperation{walkApply},
|
||||||
|
Node: &EvalSequence{
|
||||||
|
Nodes: []EvalNode{
|
||||||
|
&EvalGetProvider{
|
||||||
|
Name: n.ProvidedBy()[0],
|
||||||
|
Output: &provider,
|
||||||
|
},
|
||||||
|
&EvalReadDiff{
|
||||||
|
Name: n.stateId(),
|
||||||
|
Diff: &diff,
|
||||||
|
},
|
||||||
|
&EvalReadState{
|
||||||
|
Name: n.stateId(),
|
||||||
|
Output: &state,
|
||||||
|
},
|
||||||
|
&EvalApply{
|
||||||
|
Info: info,
|
||||||
|
State: &state,
|
||||||
|
Diff: &diff,
|
||||||
|
Provider: &provider,
|
||||||
|
Output: &state,
|
||||||
|
},
|
||||||
|
&EvalWriteState{
|
||||||
|
Name: n.stateId(),
|
||||||
|
ResourceType: n.Resource.Type,
|
||||||
|
Dependencies: n.DependentOn(),
|
||||||
|
State: &state,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
return seq
|
return seq
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,6 +65,8 @@ func (n *graphNodeTaintedResource) ProvidedBy() []string {
|
|||||||
|
|
||||||
// GraphNodeEvalable impl.
|
// GraphNodeEvalable impl.
|
||||||
func (n *graphNodeTaintedResource) EvalTree() EvalNode {
|
func (n *graphNodeTaintedResource) EvalTree() EvalNode {
|
||||||
|
var state *InstanceState
|
||||||
|
|
||||||
seq := &EvalSequence{Nodes: make([]EvalNode, 0, 5)}
|
seq := &EvalSequence{Nodes: make([]EvalNode, 0, 5)}
|
||||||
|
|
||||||
// Build instance info
|
// Build instance info
|
||||||
@ -74,19 +76,27 @@ func (n *graphNodeTaintedResource) EvalTree() EvalNode {
|
|||||||
// Refresh the resource
|
// Refresh the resource
|
||||||
seq.Nodes = append(seq.Nodes, &EvalOpFilter{
|
seq.Nodes = append(seq.Nodes, &EvalOpFilter{
|
||||||
Ops: []walkOperation{walkRefresh},
|
Ops: []walkOperation{walkRefresh},
|
||||||
Node: &EvalWriteState{
|
Node: &EvalSequence{
|
||||||
Name: n.ResourceName,
|
Nodes: []EvalNode{
|
||||||
ResourceType: n.ResourceType,
|
&EvalReadState{
|
||||||
Dependencies: n.DependentOn(),
|
|
||||||
Tainted: true,
|
|
||||||
TaintedIndex: n.Index,
|
|
||||||
State: &EvalRefresh{
|
|
||||||
Info: info,
|
|
||||||
Provider: &EvalGetProvider{Name: n.ProvidedBy()[0]},
|
|
||||||
State: &EvalReadState{
|
|
||||||
Name: n.ResourceName,
|
Name: n.ResourceName,
|
||||||
Tainted: true,
|
Tainted: true,
|
||||||
TaintedIndex: n.Index,
|
TaintedIndex: n.Index,
|
||||||
|
Output: &state,
|
||||||
|
},
|
||||||
|
&EvalRefresh{
|
||||||
|
Info: info,
|
||||||
|
Provider: &EvalGetProvider{Name: n.ProvidedBy()[0]},
|
||||||
|
State: &state,
|
||||||
|
Output: &state,
|
||||||
|
},
|
||||||
|
&EvalWriteState{
|
||||||
|
Name: n.ResourceName,
|
||||||
|
ResourceType: n.ResourceType,
|
||||||
|
Dependencies: n.DependentOn(),
|
||||||
|
State: &state,
|
||||||
|
Tainted: true,
|
||||||
|
TaintedIndex: n.Index,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user