terraform: validate diffs are the same

This commit is contained in:
Mitchell Hashimoto 2014-07-22 19:32:46 -07:00
parent 79eb52eba6
commit d5e3d5a196
3 changed files with 83 additions and 8 deletions

View File

@ -485,7 +485,6 @@ func (c *Context) applyWalkFn() depgraph.WalkFunc {
if err != nil {
return err
}
}
// This should never happen because we check if Diff.Empty above.
// If this happened, then the diff above returned a bad diff.
@ -495,6 +494,23 @@ func (c *Context) applyWalkFn() depgraph.WalkFunc {
"the resource provider. Please report a bug.")
}
// Delete id from the diff because it is dependent on
// our internal plan function.
delete(r.Diff.Attributes, "id")
delete(diff.Attributes, "id")
// Verify the diffs are the same
if !r.Diff.Same(diff) {
log.Printf(
"[ERROR] Diffs don't match.\n\nDiff 1: %#v"+
"\n\nDiff 2: %#v",
r.Diff, diff)
return fmt.Errorf(
"%s: diffs didn't match during apply. This is a " +
"bug with the resource provider, please report a bug.")
}
}
// If we do not have any connection info, initialize
if r.State.ConnInfo == nil {
r.State.ConnInfo = make(map[string]string)

View File

@ -309,6 +309,35 @@ func TestContextApply_Minimal(t *testing.T) {
}
}
func TestContextApply_badDiff(t *testing.T) {
c := testConfig(t, "apply-good")
p := testProvider("aws")
p.ApplyFn = testApplyFn
p.DiffFn = testDiffFn
ctx := testContext(t, &ContextOpts{
Config: c,
Providers: map[string]ResourceProviderFactory{
"aws": testProviderFuncFixed(p),
},
})
if _, err := ctx.Plan(nil); err != nil {
t.Fatalf("err: %s", err)
}
p.DiffFn = func(*ResourceState, *ResourceConfig) (*ResourceDiff, error) {
return &ResourceDiff{
Attributes: map[string]*ResourceAttrDiff{
"newp": nil,
},
}, nil
}
if _, err := ctx.Apply(); err == nil {
t.Fatal("should error")
}
}
func TestContextApply_cancel(t *testing.T) {
stopped := false

View File

@ -209,10 +209,40 @@ func (d *ResourceDiff) RequiresNew() bool {
}
for _, rd := range d.Attributes {
if rd.RequiresNew {
if rd != nil && rd.RequiresNew {
return true
}
}
return false
}
// Same checks whether or not to ResourceDiffs are the "same." When
// we say "same", it is not necessarily exactly equal. Instead, it is
// just checking that the same attributes are changing, a destroy
// isn't suddenly happening, etc.
func (d *ResourceDiff) Same(d2 *ResourceDiff) bool {
if d.Destroy != d2.Destroy {
return false
}
if d.RequiresNew() != d2.RequiresNew() {
return false
}
if len(d.Attributes) != len(d2.Attributes) {
return false
}
ks := make(map[string]struct{})
for k, _ := range d.Attributes {
ks[k] = struct{}{}
}
for k, _ := range d2.Attributes {
delete(ks, k)
}
if len(ks) > 0 {
return false
}
return true
}