From 5964e928dc763fca4b2fa1004b665ccd0ef1ce43 Mon Sep 17 00:00:00 2001 From: Kristin Laemmert Date: Tue, 11 Aug 2020 11:50:07 -0400 Subject: [PATCH] states/statefile: consistently sort resources across modules (#25498) If a statefile had resources with the same name in different modules, the sort order could be inconsistent between state refreshes. This adds the module to the Less() function used in sorting and a minimal test to verify consistent ordering. --- states/statefile/version4.go | 2 ++ states/statefile/version4_test.go | 41 +++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 states/statefile/version4_test.go diff --git a/states/statefile/version4.go b/states/statefile/version4.go index ee63fb3d7..450062a5a 100644 --- a/states/statefile/version4.go +++ b/states/statefile/version4.go @@ -535,6 +535,8 @@ func (sr sortResourcesV4) Len() int { return len(sr) } func (sr sortResourcesV4) Swap(i, j int) { sr[i], sr[j] = sr[j], sr[i] } func (sr sortResourcesV4) Less(i, j int) bool { switch { + case sr[i].Module != sr[j].Module: + return sr[i].Module < sr[j].Module case sr[i].Mode != sr[j].Mode: return sr[i].Mode < sr[j].Mode case sr[i].Type != sr[j].Type: diff --git a/states/statefile/version4_test.go b/states/statefile/version4_test.go new file mode 100644 index 000000000..c59ad5c28 --- /dev/null +++ b/states/statefile/version4_test.go @@ -0,0 +1,41 @@ +package statefile + +import ( + "sort" + "testing" +) + +// This test verifies that modules are sorted before resources: +// https://github.com/hashicorp/terraform/issues/21552 +func TestVersion4_sort(t *testing.T) { + resources := sortResourcesV4{ + { + Module: "module.child", + Type: "test_instance", + Name: "foo", + }, + { + Type: "test_instance", + Name: "foo", + }, + { + Module: "module.kinder", + Type: "test_instance", + Name: "foo", + }, + { + Module: "module.child.grandchild", + Type: "test_instance", + Name: "foo", + }, + } + sort.Stable(resources) + + moduleOrder := []string{"", "module.child", "module.child.grandchild", "module.kinder"} + + for i, resource := range resources { + if resource.Module != moduleOrder[i] { + t.Errorf("wrong sort order: expected %q, got %q\n", moduleOrder[i], resource.Module) + } + } +}