diff --git a/terraform/context.go b/terraform/context.go index cedc20b06..25be6c047 100644 --- a/terraform/context.go +++ b/terraform/context.go @@ -554,9 +554,11 @@ func (c *Context) applyWalkFn() depgraph.WalkFunc { // // Additionally, we need to be careful to not run this if there // was an error during the provider apply. + tainted := false if applyerr == nil && r.State.ID == "" && len(r.Provisioners) > 0 { if err := c.applyProvisioners(r, rs); err != nil { errs = append(errs, err) + tainted = true } } @@ -566,6 +568,10 @@ func (c *Context) applyWalkFn() depgraph.WalkFunc { delete(c.state.Resources, r.Id) } else { c.state.Resources[r.Id] = rs + + if tainted { + c.state.Tainted[r.Id] = struct{}{} + } } c.sl.Unlock() diff --git a/terraform/context_test.go b/terraform/context_test.go index f206a5080..d412dac06 100644 --- a/terraform/context_test.go +++ b/terraform/context_test.go @@ -457,14 +457,16 @@ func TestContextApply_Provisioner_compute(t *testing.T) { } func TestContextApply_provisionerFail(t *testing.T) { - t.Skip() - c := testConfig(t, "apply-provisioner-fail") p := testProvider("aws") pr := testProvisioner() p.ApplyFn = testApplyFn p.DiffFn = testDiffFn + pr.ApplyFn = func(*ResourceState, *ResourceConfig) error { + return fmt.Errorf("EXPLOSION") + } + ctx := testContext(t, &ContextOpts{ Config: c, Providers: map[string]ResourceProviderFactory{ @@ -483,8 +485,8 @@ func TestContextApply_provisionerFail(t *testing.T) { } state, err := ctx.Apply() - if err != nil { - t.Fatalf("err: %s", err) + if err == nil { + t.Fatal("should error") } actual := strings.TrimSpace(state.String()) diff --git a/terraform/state.go b/terraform/state.go index 5683f95f6..bd2767d5c 100644 --- a/terraform/state.go +++ b/terraform/state.go @@ -18,13 +18,20 @@ import ( type State struct { Outputs map[string]string Resources map[string]*ResourceState + Tainted map[string]struct{} once sync.Once } func (s *State) init() { s.once.Do(func() { - s.Resources = make(map[string]*ResourceState) + if s.Resources == nil { + 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 = "" } - 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)) attrKeys := make([]string, 0, len(rs.Attributes)) diff --git a/terraform/terraform_test.go b/terraform/terraform_test.go index 464d43a20..04885cb73 100644 --- a/terraform/terraform_test.go +++ b/terraform/terraform_test.go @@ -131,11 +131,10 @@ aws_instance.foo: ` const testTerraformApplyProvisionerFailStr = ` -aws_instance.bar: +aws_instance.bar: (tainted) ID = foo aws_instance.foo: ID = foo - dynamical = computed_dynamical num = 2 type = aws_instance `