Skip to content

Commit 2680b6b

Browse files
committed
terraform: refresh tainted resources
1 parent e5e4ac7 commit 2680b6b

4 files changed

Lines changed: 61 additions & 12 deletions

File tree

‎terraform/context_test.go‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -365,8 +365,7 @@ func TestContext2Refresh_state(t *testing.T) {
365365
}
366366
}
367367

368-
/*
369-
func TestContextRefresh_tainted(t *testing.T) {
368+
func TestContext2Refresh_tainted(t *testing.T) {
370369
p := testProvider("aws")
371370
m := testModule(t, "refresh-basic")
372371
state := &State{
@@ -386,7 +385,7 @@ func TestContextRefresh_tainted(t *testing.T) {
386385
},
387386
},
388387
}
389-
ctx := testContext(t, &ContextOpts{
388+
ctx := testContext2(t, &ContextOpts{
390389
Module: m,
391390
Providers: map[string]ResourceProviderFactory{
392391
"aws": testProviderFuncFixed(p),
@@ -414,6 +413,7 @@ func TestContextRefresh_tainted(t *testing.T) {
414413
}
415414
}
416415

416+
/*
417417
func TestContextRefresh_vars(t *testing.T) {
418418
p := testProvider("aws")
419419
m := testModule(t, "refresh-vars")

‎terraform/eval_state.go‎

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ import (
77
// EvalReadState is an EvalNode implementation that reads the
88
// InstanceState for a specific resource out of the state.
99
type EvalReadState struct {
10-
Name string
10+
Name string
11+
Tainted bool
12+
TaintedIndex int
1113
}
1214

1315
func (n *EvalReadState) Args() ([]EvalNode, []EvalType) {
@@ -35,8 +37,13 @@ func (n *EvalReadState) Eval(
3537
return nil, nil
3638
}
3739

38-
// Return the primary
39-
return rs.Primary, nil
40+
if !n.Tainted {
41+
// Return the primary
42+
return rs.Primary, nil
43+
} else {
44+
// Return the proper tainted resource
45+
return rs.Tainted[n.TaintedIndex], nil
46+
}
4047
}
4148

4249
func (n *EvalReadState) Type() EvalType {
@@ -50,6 +57,8 @@ type EvalWriteState struct {
5057
ResourceType string
5158
Dependencies []string
5259
State EvalNode
60+
Tainted bool
61+
TaintedIndex int
5362
}
5463

5564
func (n *EvalWriteState) Args() ([]EvalNode, []EvalType) {
@@ -89,8 +98,14 @@ func (n *EvalWriteState) Eval(
8998
rs.Type = n.ResourceType
9099
rs.Dependencies = n.Dependencies
91100

92-
// Set the primary state
93-
rs.Primary = instanceState
101+
if n.Tainted {
102+
if n.TaintedIndex != -1 {
103+
rs.Tainted[n.TaintedIndex] = instanceState
104+
}
105+
} else {
106+
// Set the primary state
107+
rs.Primary = instanceState
108+
}
94109

95110
// Prune because why not, we can clear out old useless entries now
96111
rs.prune()

‎terraform/transform_resource.go‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,8 @@ func (n *graphNodeExpandedResource) DependentOn() []string {
7272
}
7373

7474
// GraphNodeProviderConsumer
75-
func (n *graphNodeExpandedResource) ProvidedBy() string {
76-
return resourceProvider(n.Resource.Type)
75+
func (n *graphNodeExpandedResource) ProvidedBy() []string {
76+
return []string{resourceProvider(n.Resource.Type)}
7777
}
7878

7979
// GraphNodeEvalable impl.
@@ -82,7 +82,7 @@ func (n *graphNodeExpandedResource) EvalTree() EvalNode {
8282

8383
// Validate the resource
8484
seq.Nodes = append(seq.Nodes, &EvalValidateResource{
85-
Provider: &EvalGetProvider{Name: n.ProvidedBy()},
85+
Provider: &EvalGetProvider{Name: n.ProvidedBy()[0]},
8686
Config: &EvalInterpolate{Config: n.Resource.RawConfig},
8787
ResourceName: n.Resource.Name,
8888
ResourceType: n.Resource.Type,
@@ -109,7 +109,7 @@ func (n *graphNodeExpandedResource) EvalTree() EvalNode {
109109
Dependencies: n.DependentOn(),
110110
State: &EvalRefresh{
111111
Info: info,
112-
Provider: &EvalGetProvider{Name: n.ProvidedBy()},
112+
Provider: &EvalGetProvider{Name: n.ProvidedBy()[0]},
113113
State: &EvalReadState{Name: n.stateId()},
114114
},
115115
},

‎terraform/transform_tainted.go‎

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ func (t *TaintedTransformer) Transform(g *Graph) error {
3434
g.ConnectFrom(k, g.Add(&graphNodeTaintedResource{
3535
Index: i,
3636
ResourceName: k,
37+
ResourceType: rs.Type,
3738
}))
3839
}
3940
}
@@ -47,6 +48,7 @@ func (t *TaintedTransformer) Transform(g *Graph) error {
4748
type graphNodeTaintedResource struct {
4849
Index int
4950
ResourceName string
51+
ResourceType string
5052
}
5153

5254
func (n *graphNodeTaintedResource) DependentOn() []string {
@@ -60,3 +62,35 @@ func (n *graphNodeTaintedResource) Name() string {
6062
func (n *graphNodeTaintedResource) ProvidedBy() []string {
6163
return []string{resourceProvider(n.ResourceName)}
6264
}
65+
66+
// GraphNodeEvalable impl.
67+
func (n *graphNodeTaintedResource) EvalTree() EvalNode {
68+
seq := &EvalSequence{Nodes: make([]EvalNode, 0, 5)}
69+
70+
// Build instance info
71+
info := &InstanceInfo{Id: n.ResourceName, Type: n.ResourceType}
72+
seq.Nodes = append(seq.Nodes, &EvalInstanceInfo{Info: info})
73+
74+
// Refresh the resource
75+
seq.Nodes = append(seq.Nodes, &EvalOpFilter{
76+
Ops: []walkOperation{walkRefresh},
77+
Node: &EvalWriteState{
78+
Name: n.ResourceName,
79+
ResourceType: n.ResourceType,
80+
Dependencies: n.DependentOn(),
81+
Tainted: true,
82+
TaintedIndex: n.Index,
83+
State: &EvalRefresh{
84+
Info: info,
85+
Provider: &EvalGetProvider{Name: n.ProvidedBy()[0]},
86+
State: &EvalReadState{
87+
Name: n.ResourceName,
88+
Tainted: true,
89+
TaintedIndex: n.Index,
90+
},
91+
},
92+
},
93+
})
94+
95+
return seq
96+
}

0 commit comments

Comments
 (0)