From 1b75c51ed7af618fcefbaf2f892301cd9c83867a Mon Sep 17 00:00:00 2001 From: James Bardin Date: Tue, 28 Jun 2016 19:19:00 -0400 Subject: [PATCH] Don't nil module maps during state upgrade The Outputs and Resources maps in the state modules are expected to be non-nil, and initialized that way when a new module is added to the state. The V1->V2 upgrade was setting the maps to nil if the len == 0. --- terraform/state_upgrade_v1_to_v2.go | 7 +---- terraform/upgrade_state_v1_test.go | 48 +++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 6 deletions(-) diff --git a/terraform/state_upgrade_v1_to_v2.go b/terraform/state_upgrade_v1_to_v2.go index 98d58d47d..d4bf9f8f0 100644 --- a/terraform/state_upgrade_v1_to_v2.go +++ b/terraform/state_upgrade_v1_to_v2.go @@ -2,6 +2,7 @@ package terraform import ( "fmt" + "github.com/mitchellh/copystructure" ) @@ -76,9 +77,6 @@ func (old *moduleStateV1) upgradeToV2() (*ModuleState, error) { Sensitive: false, } } - if len(outputs) == 0 { - outputs = nil - } resources := make(map[string]*ResourceState) for key, oldResource := range old.Resources { @@ -88,9 +86,6 @@ func (old *moduleStateV1) upgradeToV2() (*ModuleState, error) { } resources[key] = upgraded } - if len(resources) == 0 { - resources = nil - } dependencies, err := copystructure.Copy(old.Dependencies) if err != nil { diff --git a/terraform/upgrade_state_v1_test.go b/terraform/upgrade_state_v1_test.go index 74e8bce64..ad6d57409 100644 --- a/terraform/upgrade_state_v1_test.go +++ b/terraform/upgrade_state_v1_test.go @@ -68,6 +68,54 @@ func TestReadUpgradeStateV1toV3_outputs(t *testing.T) { } } +// Upgrading the state should not lose empty module Outputs and Resources maps +// during upgrade. The init for a new module initializes new maps, so we may not +// be expecting to check for a nil map. +func TestReadUpgradeStateV1toV3_emptyState(t *testing.T) { + // ReadState should transparently detect the old version but will upgrade + // it on Write. + orig, err := ReadStateV1([]byte(testV1EmptyState)) + if err != nil { + t.Fatalf("err: %s", err) + } + + stateV2, err := upgradeStateV1ToV2(orig) + for _, m := range stateV2.Modules { + if m.Resources == nil { + t.Fatal("V1 to V2 upgrade lost module.Resources") + } + if m.Outputs == nil { + t.Fatal("V1 to V2 upgrade lost module.Outputs") + } + } + + stateV3, err := upgradeStateV2ToV3(stateV2) + for _, m := range stateV3.Modules { + if m.Resources == nil { + t.Fatal("V2 to V3 upgrade lost module.Resources") + } + if m.Outputs == nil { + t.Fatal("V2 to V3 upgrade lost module.Outputs") + } + } + +} + +const testV1EmptyState = `{ + "version": 1, + "serial": 0, + "modules": [ + { + "path": [ + "root" + ], + "outputs": {}, + "resources": {} + } + ] +} +` + const testV1State = `{ "version": 1, "serial": 9,