From d2e836275b5825a098bf6368b047a723695ba0b9 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sat, 11 Oct 2014 12:47:06 -0700 Subject: [PATCH] terraform: sort the modules in the state [GH-318] --- terraform/state.go | 38 ++++++++++++++++++++++++++++++++ terraform/state_test.go | 49 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+) diff --git a/terraform/state.go b/terraform/state.go index 1a6980fc4..503f01c17 100644 --- a/terraform/state.go +++ b/terraform/state.go @@ -67,6 +67,7 @@ func (s *State) AddModule(path []string) *ModuleState { m := &ModuleState{Path: path} m.init() s.Modules = append(s.Modules, m) + s.sort() return m } @@ -135,6 +136,11 @@ func (s *State) prune() { } } +// sort sorts the modules +func (s *State) sort() { + sort.Sort(moduleStateSort(s.Modules)) +} + func (s *State) GoString() string { return fmt.Sprintf("*%#v", *s) } @@ -619,11 +625,18 @@ func ReadState(src io.Reader) (*State, error) { return nil, fmt.Errorf("State version %d not supported, please update.", state.Version) } + + // Sort it + state.sort() + return state, nil } // WriteState writes a state somewhere in a binary format. func WriteState(d *State, dst io.Writer) error { + // Make sure it is sorted + d.sort() + // Ensure the version is set d.Version = textStateVersion @@ -682,3 +695,28 @@ func upgradeV1State(old *StateV1) (*State, error) { } return s, nil } + +// moduleStateSort implements sort.Interface to sort module states +type moduleStateSort []*ModuleState + +func (s moduleStateSort) Len() int { + return len(s) +} + +func (s moduleStateSort) Less(i, j int) bool { + a := s[i] + b := s[j] + + // If the lengths are different, then the shorter one always wins + if len(a.Path) != len(b.Path) { + return len(a.Path) < len(b.Path) + } + + // Otherwise, compare by last path element + idx := len(a.Path) - 1 + return a.Path[idx] < b.Path[idx] +} + +func (s moduleStateSort) Swap(i, j int) { + s[i], s[j] = s[j], s[i] +} diff --git a/terraform/state_test.go b/terraform/state_test.go index 3066f0b7d..34e7b8029 100644 --- a/terraform/state_test.go +++ b/terraform/state_test.go @@ -10,6 +10,55 @@ import ( "github.com/hashicorp/terraform/config" ) +func TestStateAddModule(t *testing.T) { + cases := []struct{ + In [][]string + Out [][]string + }{ + { + [][]string{ + []string{"root"}, + []string{"root", "child"}, + }, + [][]string{ + []string{"root"}, + []string{"root", "child"}, + }, + }, + + { + [][]string{ + []string{"root", "foo", "bar"}, + []string{"root", "foo"}, + []string{"root"}, + []string{"root", "bar"}, + }, + [][]string{ + []string{"root"}, + []string{"root", "bar"}, + []string{"root", "foo"}, + []string{"root", "foo", "bar"}, + }, + }, + } + + for _, tc := range cases { + s := new(State) + for _, p := range tc.In { + s.AddModule(p) + } + + actual := make([][]string, 0, len(tc.In)) + for _, m := range s.Modules { + actual = append(actual, m.Path) + } + + if !reflect.DeepEqual(actual, tc.Out) { + t.Fatalf("In: %#v\n\nOut: %#v", tc.In, actual) + } + } +} + func TestInstanceState_MergeDiff(t *testing.T) { is := InstanceState{ ID: "foo",