terraform: refreshing tainted resources works
This commit is contained in:
parent
f89c2c5ff0
commit
157843725d
|
@ -893,19 +893,23 @@ func (c *Context) planDestroyWalkFn(result *Plan) depgraph.WalkFunc {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) refreshWalkFn() depgraph.WalkFunc {
|
func (c *Context) refreshWalkFn() depgraph.WalkFunc {
|
||||||
cb := func(r *Resource, tainted bool, inst **InstanceState) error {
|
cb := func(r *Resource) error {
|
||||||
if *inst == nil || (*inst).ID == "" {
|
is := r.State.Primary
|
||||||
|
if r.Tainted {
|
||||||
|
is = r.State.Tainted[r.TaintedIndex]
|
||||||
|
}
|
||||||
|
|
||||||
|
if is == nil || is.ID == "" {
|
||||||
log.Printf("[DEBUG] %s: Not refreshing, ID is empty", r.Id)
|
log.Printf("[DEBUG] %s: Not refreshing, ID is empty", r.Id)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
state := *inst
|
|
||||||
|
|
||||||
for _, h := range c.hooks {
|
for _, h := range c.hooks {
|
||||||
handleHook(h.PreRefresh(r.Id, state))
|
handleHook(h.PreRefresh(r.Id, is))
|
||||||
}
|
}
|
||||||
|
|
||||||
info := &InstanceInfo{Type: r.State.Type}
|
info := &InstanceInfo{Type: r.State.Type}
|
||||||
is, err := r.Provider.Refresh(info, state)
|
is, err := r.Provider.Refresh(info, is)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -914,8 +918,11 @@ func (c *Context) refreshWalkFn() depgraph.WalkFunc {
|
||||||
is.init()
|
is.init()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the state
|
if r.Tainted {
|
||||||
*inst = is
|
r.State.Tainted[r.TaintedIndex] = is
|
||||||
|
} else {
|
||||||
|
r.State.Primary = is
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Handle other modules
|
// TODO: Handle other modules
|
||||||
c.sl.Lock()
|
c.sl.Lock()
|
||||||
|
@ -930,7 +937,7 @@ func (c *Context) refreshWalkFn() depgraph.WalkFunc {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.genericWalkFn(instanceWalk(cb))
|
return c.genericWalkFn(cb)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) validateWalkFn(rws *[]string, res *[]error) depgraph.WalkFunc {
|
func (c *Context) validateWalkFn(rws *[]string, res *[]error) depgraph.WalkFunc {
|
||||||
|
|
|
@ -2235,6 +2235,7 @@ func TestContextRefresh_tainted(t *testing.T) {
|
||||||
Path: rootModulePath,
|
Path: rootModulePath,
|
||||||
Resources: map[string]*ResourceState{
|
Resources: map[string]*ResourceState{
|
||||||
"aws_instance.web": &ResourceState{
|
"aws_instance.web": &ResourceState{
|
||||||
|
Type: "aws_instance",
|
||||||
Tainted: []*InstanceState{
|
Tainted: []*InstanceState{
|
||||||
&InstanceState{
|
&InstanceState{
|
||||||
ID: "bar",
|
ID: "bar",
|
||||||
|
@ -2262,16 +2263,14 @@ func TestContextRefresh_tainted(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("err: %s", err)
|
t.Fatalf("err: %s", err)
|
||||||
}
|
}
|
||||||
originalMod := state.RootModule()
|
|
||||||
mod := s.RootModule()
|
|
||||||
if !p.RefreshCalled {
|
if !p.RefreshCalled {
|
||||||
t.Fatal("refresh should be called")
|
t.Fatal("refresh should be called")
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(p.RefreshState, originalMod.Resources["aws_instance.web"].Tainted[0]) {
|
|
||||||
t.Fatalf("bad: %#v %#v", p.RefreshState, originalMod.Resources["aws_instance.web"].Tainted[0])
|
actual := strings.TrimSpace(s.String())
|
||||||
}
|
expected := strings.TrimSpace(testContextRefreshTaintedStr)
|
||||||
if !reflect.DeepEqual(mod.Resources["aws_instance.web"].Tainted[0], p.RefreshReturn) {
|
if actual != expected {
|
||||||
t.Fatalf("bad: %#v", mod.Resources)
|
t.Fatalf("bad:\n\n%s\n\n%s", actual, expected)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2476,3 +2475,9 @@ root
|
||||||
root -> aws_instance.bar
|
root -> aws_instance.bar
|
||||||
root -> aws_instance.foo
|
root -> aws_instance.foo
|
||||||
`
|
`
|
||||||
|
|
||||||
|
const testContextRefreshTaintedStr = `
|
||||||
|
aws_instance.web: (1 tainted)
|
||||||
|
ID = <not created>
|
||||||
|
Tainted ID 1 = foo
|
||||||
|
`
|
||||||
|
|
|
@ -364,6 +364,12 @@ func (s *ResourceState) GoString() string {
|
||||||
return fmt.Sprintf("*%#v", *s)
|
return fmt.Sprintf("*%#v", *s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *ResourceState) String() string {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
buf.WriteString(fmt.Sprintf("Type = %s", s.Type))
|
||||||
|
return buf.String()
|
||||||
|
}
|
||||||
|
|
||||||
// InstanceState is used to track the unique state information belonging
|
// InstanceState is used to track the unique state information belonging
|
||||||
// to a given instance.
|
// to a given instance.
|
||||||
type InstanceState struct {
|
type InstanceState struct {
|
||||||
|
@ -451,7 +457,7 @@ func (i *InstanceState) GoString() string {
|
||||||
func (i *InstanceState) String() string {
|
func (i *InstanceState) String() string {
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
|
|
||||||
if i.ID == "" {
|
if i == nil || i.ID == "" {
|
||||||
return "<not created>"
|
return "<not created>"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue