diff --git a/terraform/diff.go b/terraform/diff.go index b3a8fe5de0..a474efad1c 100644 --- a/terraform/diff.go +++ b/terraform/diff.go @@ -32,6 +32,30 @@ type Diff struct { Modules []*ModuleDiff } +// Prune cleans out unused structures in the diff without affecting +// the behavior of the diff at all. +// +// This is not safe to call concurrently. This is safe to call on a +// nil Diff. +func (d *Diff) Prune() { + if d == nil { + return + } + + // Prune all empty modules + newModules := make([]*ModuleDiff, 0, len(d.Modules)) + for _, m := range d.Modules { + // If the module isn't empty, we keep it + if !m.Empty() { + newModules = append(newModules, m) + } + } + if len(newModules) == 0 { + newModules = nil + } + d.Modules = newModules +} + // AddModule adds the module with the given path to the diff. // // This should be the preferred method to add module diffs since it @@ -212,6 +236,10 @@ func (d *ModuleDiff) ChangeType() DiffChangeType { // Empty returns true if the diff has no changes within this module. func (d *ModuleDiff) Empty() bool { + if d.Destroy { + return false + } + if len(d.Resources) == 0 { return true } diff --git a/terraform/diff_test.go b/terraform/diff_test.go index fca0fbcbe3..655b165f96 100644 --- a/terraform/diff_test.go +++ b/terraform/diff_test.go @@ -103,6 +103,53 @@ func TestDiffEqual(t *testing.T) { } } +func TestDiffPrune(t *testing.T) { + cases := map[string]struct { + D1, D2 *Diff + }{ + "nil": { + nil, + nil, + }, + + "empty": { + new(Diff), + new(Diff), + }, + + "empty module": { + &Diff{ + Modules: []*ModuleDiff{ + &ModuleDiff{Path: []string{"root", "foo"}}, + }, + }, + &Diff{}, + }, + + "destroy module": { + &Diff{ + Modules: []*ModuleDiff{ + &ModuleDiff{Path: []string{"root", "foo"}, Destroy: true}, + }, + }, + &Diff{ + Modules: []*ModuleDiff{ + &ModuleDiff{Path: []string{"root", "foo"}, Destroy: true}, + }, + }, + }, + } + + for name, tc := range cases { + t.Run(name, func(t *testing.T) { + tc.D1.Prune() + if !tc.D1.Equal(tc.D2) { + t.Fatalf("bad:\n\n%#v\n\n%#v", tc.D1, tc.D2) + } + }) + } +} + func TestModuleDiff_ChangeType(t *testing.T) { cases := []struct { Diff *ModuleDiff