terraform: mark resource as tainted if provisioning fails
This commit is contained in:
parent
808036bf60
commit
192fc1e544
|
@ -554,9 +554,11 @@ func (c *Context) applyWalkFn() depgraph.WalkFunc {
|
||||||
//
|
//
|
||||||
// Additionally, we need to be careful to not run this if there
|
// Additionally, we need to be careful to not run this if there
|
||||||
// was an error during the provider apply.
|
// was an error during the provider apply.
|
||||||
|
tainted := false
|
||||||
if applyerr == nil && r.State.ID == "" && len(r.Provisioners) > 0 {
|
if applyerr == nil && r.State.ID == "" && len(r.Provisioners) > 0 {
|
||||||
if err := c.applyProvisioners(r, rs); err != nil {
|
if err := c.applyProvisioners(r, rs); err != nil {
|
||||||
errs = append(errs, err)
|
errs = append(errs, err)
|
||||||
|
tainted = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -566,6 +568,10 @@ func (c *Context) applyWalkFn() depgraph.WalkFunc {
|
||||||
delete(c.state.Resources, r.Id)
|
delete(c.state.Resources, r.Id)
|
||||||
} else {
|
} else {
|
||||||
c.state.Resources[r.Id] = rs
|
c.state.Resources[r.Id] = rs
|
||||||
|
|
||||||
|
if tainted {
|
||||||
|
c.state.Tainted[r.Id] = struct{}{}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
c.sl.Unlock()
|
c.sl.Unlock()
|
||||||
|
|
||||||
|
|
|
@ -457,14 +457,16 @@ func TestContextApply_Provisioner_compute(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestContextApply_provisionerFail(t *testing.T) {
|
func TestContextApply_provisionerFail(t *testing.T) {
|
||||||
t.Skip()
|
|
||||||
|
|
||||||
c := testConfig(t, "apply-provisioner-fail")
|
c := testConfig(t, "apply-provisioner-fail")
|
||||||
p := testProvider("aws")
|
p := testProvider("aws")
|
||||||
pr := testProvisioner()
|
pr := testProvisioner()
|
||||||
p.ApplyFn = testApplyFn
|
p.ApplyFn = testApplyFn
|
||||||
p.DiffFn = testDiffFn
|
p.DiffFn = testDiffFn
|
||||||
|
|
||||||
|
pr.ApplyFn = func(*ResourceState, *ResourceConfig) error {
|
||||||
|
return fmt.Errorf("EXPLOSION")
|
||||||
|
}
|
||||||
|
|
||||||
ctx := testContext(t, &ContextOpts{
|
ctx := testContext(t, &ContextOpts{
|
||||||
Config: c,
|
Config: c,
|
||||||
Providers: map[string]ResourceProviderFactory{
|
Providers: map[string]ResourceProviderFactory{
|
||||||
|
@ -483,8 +485,8 @@ func TestContextApply_provisionerFail(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
state, err := ctx.Apply()
|
state, err := ctx.Apply()
|
||||||
if err != nil {
|
if err == nil {
|
||||||
t.Fatalf("err: %s", err)
|
t.Fatal("should error")
|
||||||
}
|
}
|
||||||
|
|
||||||
actual := strings.TrimSpace(state.String())
|
actual := strings.TrimSpace(state.String())
|
||||||
|
|
|
@ -18,13 +18,20 @@ import (
|
||||||
type State struct {
|
type State struct {
|
||||||
Outputs map[string]string
|
Outputs map[string]string
|
||||||
Resources map[string]*ResourceState
|
Resources map[string]*ResourceState
|
||||||
|
Tainted map[string]struct{}
|
||||||
|
|
||||||
once sync.Once
|
once sync.Once
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *State) init() {
|
func (s *State) init() {
|
||||||
s.once.Do(func() {
|
s.once.Do(func() {
|
||||||
|
if s.Resources == nil {
|
||||||
s.Resources = make(map[string]*ResourceState)
|
s.Resources = make(map[string]*ResourceState)
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.Tainted == nil {
|
||||||
|
s.Tainted = make(map[string]struct{})
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,7 +104,12 @@ func (s *State) String() string {
|
||||||
id = "<not created>"
|
id = "<not created>"
|
||||||
}
|
}
|
||||||
|
|
||||||
buf.WriteString(fmt.Sprintf("%s:\n", k))
|
taintStr := ""
|
||||||
|
if _, ok := s.Tainted[k]; ok {
|
||||||
|
taintStr = " (tainted)"
|
||||||
|
}
|
||||||
|
|
||||||
|
buf.WriteString(fmt.Sprintf("%s:%s\n", k, taintStr))
|
||||||
buf.WriteString(fmt.Sprintf(" ID = %s\n", id))
|
buf.WriteString(fmt.Sprintf(" ID = %s\n", id))
|
||||||
|
|
||||||
attrKeys := make([]string, 0, len(rs.Attributes))
|
attrKeys := make([]string, 0, len(rs.Attributes))
|
||||||
|
|
|
@ -131,11 +131,10 @@ aws_instance.foo:
|
||||||
`
|
`
|
||||||
|
|
||||||
const testTerraformApplyProvisionerFailStr = `
|
const testTerraformApplyProvisionerFailStr = `
|
||||||
aws_instance.bar:
|
aws_instance.bar: (tainted)
|
||||||
ID = foo
|
ID = foo
|
||||||
aws_instance.foo:
|
aws_instance.foo:
|
||||||
ID = foo
|
ID = foo
|
||||||
dynamical = computed_dynamical
|
|
||||||
num = 2
|
num = 2
|
||||||
type = aws_instance
|
type = aws_instance
|
||||||
`
|
`
|
||||||
|
|
Loading…
Reference in New Issue