diff --git a/terraform/state_upgrade_v1_to_v2.go b/terraform/state_upgrade_v1_to_v2.go index 88192e87e..aa13cce80 100644 --- a/terraform/state_upgrade_v1_to_v2.go +++ b/terraform/state_upgrade_v1_to_v2.go @@ -64,11 +64,15 @@ func (old *moduleStateV1) upgradeToV2() (*ModuleState, error) { return nil, nil } - path, err := copystructure.Copy(old.Path) + pathRaw, err := copystructure.Copy(old.Path) if err != nil { return nil, fmt.Errorf("Error upgrading ModuleState V1: %v", err) } - if path == nil { + path, ok := pathRaw.([]string) + if !ok { + return nil, fmt.Errorf("Error upgrading ModuleState V1: path is not a list of strings") + } + if len(path) == 0 { // We found some V1 states with a nil path. Assume root and catch // duplicate path errors later (as part of Validate). path = rootModulePath @@ -99,7 +103,7 @@ func (old *moduleStateV1) upgradeToV2() (*ModuleState, error) { } return &ModuleState{ - Path: path.([]string), + Path: path, Outputs: outputs, Resources: resources, Dependencies: dependencies.([]string), diff --git a/terraform/state_upgrade_v1_to_v2_test.go b/terraform/state_upgrade_v1_to_v2_test.go new file mode 100644 index 000000000..a660ae898 --- /dev/null +++ b/terraform/state_upgrade_v1_to_v2_test.go @@ -0,0 +1,22 @@ +package terraform + +import ( + "os" + "path/filepath" + "testing" +) + +func TestReadStateV1ToV2_noPath(t *testing.T) { + f, err := os.Open(filepath.Join(fixtureDir, "state-upgrade", "v1-to-v2-empty-path.tfstate")) + if err != nil { + t.Fatalf("err: %s", err) + } + defer f.Close() + + s, err := ReadState(f) + if err != nil { + t.Fatalf("err: %s", err) + } + + checkStateString(t, s, "") +} diff --git a/terraform/test-fixtures/state-upgrade/v1-to-v2-empty-path.tfstate b/terraform/test-fixtures/state-upgrade/v1-to-v2-empty-path.tfstate new file mode 100644 index 000000000..ee7c9d187 --- /dev/null +++ b/terraform/test-fixtures/state-upgrade/v1-to-v2-empty-path.tfstate @@ -0,0 +1,38 @@ +{ + "version": 1, + "modules": [{ + "resources": { + "aws_instance.foo1": {"primary":{}}, + "cloudstack_instance.foo1": {"primary":{}}, + "cloudstack_instance.foo2": {"primary":{}}, + "digitalocean_droplet.foo1": {"primary":{}}, + "digitalocean_droplet.foo2": {"primary":{}}, + "digitalocean_droplet.foo3": {"primary":{}}, + "docker_container.foo1": {"primary":{}}, + "docker_container.foo2": {"primary":{}}, + "docker_container.foo3": {"primary":{}}, + "docker_container.foo4": {"primary":{}}, + "google_compute_instance.foo1": {"primary":{}}, + "google_compute_instance.foo2": {"primary":{}}, + "google_compute_instance.foo3": {"primary":{}}, + "google_compute_instance.foo4": {"primary":{}}, + "google_compute_instance.foo5": {"primary":{}}, + "heroku_app.foo1": {"primary":{}}, + "heroku_app.foo2": {"primary":{}}, + "heroku_app.foo3": {"primary":{}}, + "heroku_app.foo4": {"primary":{}}, + "heroku_app.foo5": {"primary":{}}, + "heroku_app.foo6": {"primary":{}}, + "openstack_compute_instance_v2.foo1": {"primary":{}}, + "openstack_compute_instance_v2.foo2": {"primary":{}}, + "openstack_compute_instance_v2.foo3": {"primary":{}}, + "openstack_compute_instance_v2.foo4": {"primary":{}}, + "openstack_compute_instance_v2.foo5": {"primary":{}}, + "openstack_compute_instance_v2.foo6": {"primary":{}}, + "openstack_compute_instance_v2.foo7": {"primary":{}}, + "bar": {"primary":{}}, + "baz": {"primary":{}}, + "zip": {"primary":{}} + } + }] +}