Skip to content

Commit

Permalink
Merge pull request #10504 from hashicorp/b-no-prune
Browse files Browse the repository at this point in the history
terraform: don't prune state on init()
  • Loading branch information
mitchellh authored Dec 2, 2016
2 parents 8dec180 + cfb440e commit be012a5
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 16 deletions.
36 changes: 30 additions & 6 deletions terraform/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,10 @@ func (s *State) Children(path []string) []*ModuleState {
func (s *State) children(path []string) []*ModuleState {
result := make([]*ModuleState, 0)
for _, m := range s.Modules {
if m == nil {
continue
}

if len(m.Path) != len(path)+1 {
continue
}
Expand Down Expand Up @@ -161,6 +165,9 @@ func (s *State) ModuleByPath(path []string) *ModuleState {

func (s *State) moduleByPath(path []string) *ModuleState {
for _, mod := range s.Modules {
if mod == nil {
continue
}
if mod.Path == nil {
panic("missing module path")
}
Expand Down Expand Up @@ -213,6 +220,10 @@ func (s *State) moduleOrphans(path []string, c *config.Config) [][]string {

// Find the orphans that are nested...
for _, m := range s.Modules {
if m == nil {
continue
}

// We only want modules that are at least grandchildren
if len(m.Path) < len(path)+2 {
continue
Expand Down Expand Up @@ -328,6 +339,10 @@ func (s *State) Validate() error {
{
found := make(map[string]struct{})
for _, ms := range s.Modules {
if ms == nil {
continue
}

key := strings.Join(ms.Path, ".")
if _, ok := found[key]; ok {
result = multierror.Append(result, fmt.Errorf(
Expand Down Expand Up @@ -644,12 +659,10 @@ func (s *State) init() {
}
s.ensureHasLineage()

// We can't trust that state read from a file doesn't have nil/empty
// modules
s.prune()

for _, mod := range s.Modules {
mod.init()
if mod != nil {
mod.init()
}
}

if s.Remote != nil {
Expand Down Expand Up @@ -726,7 +739,9 @@ func (s *State) sort() {

// Allow modules to be sorted
for _, m := range s.Modules {
m.sort()
if m != nil {
m.sort()
}
}
}

Expand Down Expand Up @@ -1810,6 +1825,10 @@ func ReadState(src io.Reader) (*State, error) {
panic("resulting state in load not set, assertion failed")
}

// Prune the state when read it. Its possible to write unpruned states or
// for a user to make a state unpruned (nil-ing a module state for example).
result.prune()

// Validate the state file is valid
if err := result.Validate(); err != nil {
return nil, err
Expand Down Expand Up @@ -1968,6 +1987,11 @@ func (s moduleStateSort) Less(i, j int) bool {
a := s[i]
b := s[j]

// If either is nil, then the nil one is "less" than
if a == nil || b == nil {
return a == nil
}

// 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)
Expand Down
38 changes: 28 additions & 10 deletions terraform/state_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1695,16 +1695,34 @@ func TestStateModuleOrphans_empty(t *testing.T) {

// just calling this to check for panic
state.ModuleOrphans(RootModulePath, nil)
}

for _, mod := range state.Modules {
if mod == nil {
t.Fatal("found nil module")
}
if mod.Path == nil {
t.Fatal("found nil module path")
}
if len(mod.Path) == 0 {
t.Fatal("found empty module path")
}
func TestReadState_prune(t *testing.T) {
state := &State{
Modules: []*ModuleState{
&ModuleState{Path: rootModulePath},
nil,
},
}
state.init()

buf := new(bytes.Buffer)
if err := WriteState(state, buf); err != nil {
t.Fatalf("err: %s", err)
}

actual, err := ReadState(buf)
if err != nil {
t.Fatalf("err: %s", err)
}

expected := &State{
Version: state.Version,
Lineage: state.Lineage,
}
expected.init()

if !reflect.DeepEqual(actual, expected) {
t.Fatalf("got:\n%#v", actual)
}
}
4 changes: 4 additions & 0 deletions terraform/transform_orphan_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ func (t *OrphanResourceTransformer) Transform(g *Graph) error {
}

func (t *OrphanResourceTransformer) transform(g *Graph, ms *ModuleState) error {
if ms == nil {
return nil
}

// Get the configuration for this path. The configuration might be
// nil if the module was removed from the configuration. This is okay,
// this just means that every resource is an orphan.
Expand Down
25 changes: 25 additions & 0 deletions terraform/transform_orphan_resource_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,31 @@ func TestOrphanResourceTransformer(t *testing.T) {
}
}

func TestOrphanResourceTransformer_nilModule(t *testing.T) {
mod := testModule(t, "transform-orphan-basic")
state := &State{
Modules: []*ModuleState{nil},
}

g := Graph{Path: RootModulePath}
{
tf := &ConfigTransformer{Module: mod}
if err := tf.Transform(&g); err != nil {
t.Fatalf("err: %s", err)
}
}

{
tf := &OrphanResourceTransformer{
Concrete: testOrphanResourceConcreteFunc,
State: state, Module: mod,
}
if err := tf.Transform(&g); err != nil {
t.Fatalf("err: %s", err)
}
}
}

func TestOrphanResourceTransformer_countGood(t *testing.T) {
mod := testModule(t, "transform-orphan-count")
state := &State{
Expand Down

0 comments on commit be012a5

Please sign in to comment.