terraform: partial state should be saved on apply error
This commit is contained in:
parent
f78f97647a
commit
ff36378c4e
|
@ -440,6 +440,8 @@ func (c *Context) releaseRun(ch chan<- struct{}) {
|
||||||
|
|
||||||
func (c *Context) applyWalkFn() depgraph.WalkFunc {
|
func (c *Context) applyWalkFn() depgraph.WalkFunc {
|
||||||
cb := func(r *Resource) error {
|
cb := func(r *Resource) error {
|
||||||
|
var err error
|
||||||
|
|
||||||
diff := r.Diff
|
diff := r.Diff
|
||||||
if diff.Empty() {
|
if diff.Empty() {
|
||||||
log.Printf("[DEBUG] %s: Diff is empty. Will not apply.", r.Id)
|
log.Printf("[DEBUG] %s: Diff is empty. Will not apply.", r.Id)
|
||||||
|
@ -452,7 +454,6 @@ func (c *Context) applyWalkFn() depgraph.WalkFunc {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
|
||||||
diff, err = r.Provider.Diff(r.State, r.Config)
|
diff, err = r.Provider.Diff(r.State, r.Config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -486,9 +487,11 @@ func (c *Context) applyWalkFn() depgraph.WalkFunc {
|
||||||
|
|
||||||
// With the completed diff, apply!
|
// With the completed diff, apply!
|
||||||
log.Printf("[DEBUG] %s: Executing Apply", r.Id)
|
log.Printf("[DEBUG] %s: Executing Apply", r.Id)
|
||||||
rs, err := r.Provider.Apply(r.State, diff)
|
rs, applyerr := r.Provider.Apply(r.State, diff)
|
||||||
if err != nil {
|
|
||||||
return err
|
var errs []error
|
||||||
|
if applyerr != nil {
|
||||||
|
errs = append(errs, applyerr)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure the result is instantiated
|
// Make sure the result is instantiated
|
||||||
|
@ -508,7 +511,6 @@ func (c *Context) applyWalkFn() depgraph.WalkFunc {
|
||||||
rs.Attributes["id"] = rs.ID
|
rs.Attributes["id"] = rs.ID
|
||||||
}
|
}
|
||||||
|
|
||||||
var errs []error
|
|
||||||
for ak, av := range rs.Attributes {
|
for ak, av := range rs.Attributes {
|
||||||
// If the value is the unknown variable value, then it is an error.
|
// If the value is the unknown variable value, then it is an error.
|
||||||
// In this case we record the error and remove it from the state
|
// In this case we record the error and remove it from the state
|
||||||
|
@ -522,7 +524,10 @@ func (c *Context) applyWalkFn() depgraph.WalkFunc {
|
||||||
// Invoke any provisioners we have defined. This is only done
|
// Invoke any provisioners we have defined. This is only done
|
||||||
// if the resource was created, as updates or deletes do not
|
// if the resource was created, as updates or deletes do not
|
||||||
// invoke provisioners.
|
// invoke provisioners.
|
||||||
if r.State.ID == "" && len(r.Provisioners) > 0 {
|
//
|
||||||
|
// Additionally, we need to be careful to not run this if there
|
||||||
|
// was an error during the provider apply.
|
||||||
|
if applyerr == nil && r.State.ID == "" && len(r.Provisioners) > 0 {
|
||||||
rs, err = c.applyProvisioners(r, rs)
|
rs, err = c.applyProvisioners(r, rs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errs = append(errs, err)
|
errs = append(errs, err)
|
||||||
|
|
|
@ -738,7 +738,10 @@ func TestContextApply_error(t *testing.T) {
|
||||||
|
|
||||||
p.ApplyFn = func(*ResourceState, *ResourceDiff) (*ResourceState, error) {
|
p.ApplyFn = func(*ResourceState, *ResourceDiff) (*ResourceState, error) {
|
||||||
if errored {
|
if errored {
|
||||||
return nil, fmt.Errorf("error")
|
state := &ResourceState{
|
||||||
|
ID: "bar",
|
||||||
|
}
|
||||||
|
return state, fmt.Errorf("error")
|
||||||
}
|
}
|
||||||
errored = true
|
errored = true
|
||||||
|
|
||||||
|
@ -768,10 +771,6 @@ func TestContextApply_error(t *testing.T) {
|
||||||
t.Fatal("should have error")
|
t.Fatal("should have error")
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(state.Resources) != 1 {
|
|
||||||
t.Fatalf("bad: %#v", state.Resources)
|
|
||||||
}
|
|
||||||
|
|
||||||
actual := strings.TrimSpace(state.String())
|
actual := strings.TrimSpace(state.String())
|
||||||
expected := strings.TrimSpace(testTerraformApplyErrorStr)
|
expected := strings.TrimSpace(testTerraformApplyErrorStr)
|
||||||
if actual != expected {
|
if actual != expected {
|
||||||
|
@ -800,9 +799,9 @@ func TestContextApply_errorPartial(t *testing.T) {
|
||||||
State: s,
|
State: s,
|
||||||
})
|
})
|
||||||
|
|
||||||
p.ApplyFn = func(*ResourceState, *ResourceDiff) (*ResourceState, error) {
|
p.ApplyFn = func(s *ResourceState, d *ResourceDiff) (*ResourceState, error) {
|
||||||
if errored {
|
if errored {
|
||||||
return nil, fmt.Errorf("error")
|
return s, fmt.Errorf("error")
|
||||||
}
|
}
|
||||||
errored = true
|
errored = true
|
||||||
|
|
||||||
|
|
|
@ -135,6 +135,8 @@ const testTerraformApplyDestroyStr = `
|
||||||
`
|
`
|
||||||
|
|
||||||
const testTerraformApplyErrorStr = `
|
const testTerraformApplyErrorStr = `
|
||||||
|
aws_instance.bar:
|
||||||
|
ID = bar
|
||||||
aws_instance.foo:
|
aws_instance.foo:
|
||||||
ID = foo
|
ID = foo
|
||||||
num = 2
|
num = 2
|
||||||
|
|
Loading…
Reference in New Issue