From 10d926904f7bf61bda422c98777c42df15c33351 Mon Sep 17 00:00:00 2001 From: James Bardin Date: Mon, 2 Mar 2020 14:45:03 -0500 Subject: [PATCH] state mv should always target instance each mode When doing a state mv of an instance, the resulting each mode should always be taken from the target address. --- command/state_mv.go | 15 +++++---- command/state_mv_test.go | 66 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 72 insertions(+), 9 deletions(-) diff --git a/command/state_mv.go b/command/state_mv.go index 33014b3dc..b4dc14321 100644 --- a/command/state_mv.go +++ b/command/state_mv.go @@ -280,31 +280,30 @@ func (c *StateMvCommand) Run(args []string) int { fromResourceAddr := addrFrom.ContainingResource() fromResource := ssFrom.Resource(fromResourceAddr) fromProviderAddr := fromResource.ProviderConfig - fromEachMode := fromResource.EachMode ssFrom.ForgetResourceInstanceAll(addrFrom) ssFrom.RemoveResourceIfEmpty(fromResourceAddr) + // since this is moving an instance, we can infer the target + // mode from the address. + toEachMode := eachModeForInstanceKey(addrTo.Resource.Key) + rs := stateTo.Resource(addrTo.ContainingResource()) if rs == nil { // If we're moving to an address without an index then that // suggests the user's intent is to establish both the // resource and the instance at the same time (since the // address covers both). If there's an index in the - // target then allow creating the new instance here, - // inferring the mode from how the new address was parsed. - if addrTo.Resource.Key != addrs.NoKey { - fromEachMode = eachModeForInstanceKey(addrTo.Resource.Key) - } - + // target then allow creating the new instance here. resourceAddr := addrTo.ContainingResource() stateTo.SyncWrapper().SetResourceMeta( resourceAddr, - fromEachMode, + toEachMode, fromProviderAddr, // in this case, we bring the provider along as if we were moving the whole resource ) rs = stateTo.Resource(resourceAddr) } + rs.EachMode = toEachMode rs.Instances[addrTo.Resource.Key] = is } default: diff --git a/command/state_mv_test.go b/command/state_mv_test.go index c7ebee344..d7968b5e6 100644 --- a/command/state_mv_test.go +++ b/command/state_mv_test.go @@ -68,7 +68,7 @@ func TestStateMv(t *testing.T) { "test_instance.bar", } if code := c.Run(args); code != 0 { - t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) + t.Fatalf("return code: %d\n\n%s", code, ui.ErrorWriter.String()) } // Test it is correct @@ -80,6 +80,70 @@ func TestStateMv(t *testing.T) { t.Fatalf("bad: %#v", backups) } testStateOutput(t, backups[0], testStateMvOutputOriginal) + + // Change the single instance to a counted instance + args = []string{ + "-state", statePath, + "test_instance.bar", + "test_instance.bar[0]", + } + if code := c.Run(args); code != 0 { + t.Fatalf("return code: %d\n\n%s", code, ui.ErrorWriter.String()) + } + + // extract the resource and verify the mode + s := testStateRead(t, statePath) + addr, diags := addrs.ParseAbsResourceStr("test_instance.bar") + if diags.HasErrors() { + t.Fatal(diags.Err()) + } + i := s.Resource(addr) + if i.EachMode != states.EachList { + t.Fatalf("expected each mode List, got %s", i.EachMode) + } + + // change from list to map + args = []string{ + "-state", statePath, + "test_instance.bar[0]", + "test_instance.bar[\"baz\"]", + } + if code := c.Run(args); code != 0 { + t.Fatalf("return code: %d\n\n%s", code, ui.ErrorWriter.String()) + } + + // extract the resource and verify the mode + s = testStateRead(t, statePath) + addr, diags = addrs.ParseAbsResourceStr("test_instance.bar") + if diags.HasErrors() { + t.Fatal(diags.Err()) + } + i = s.Resource(addr) + if i.EachMode != states.EachMap { + t.Fatalf("expected each mode Map, got %s", i.EachMode) + } + + // change from from map back to single + args = []string{ + "-state", statePath, + "test_instance.bar[\"baz\"]", + "test_instance.bar", + } + if code := c.Run(args); code != 0 { + t.Fatalf("return code: %d\n\n%s", code, ui.ErrorWriter.String()) + } + + // extract the resource and verify the mode + s = testStateRead(t, statePath) + addr, diags = addrs.ParseAbsResourceStr("test_instance.bar") + if diags.HasErrors() { + t.Fatal(diags.Err()) + } + i = s.Resource(addr) + if i.EachMode != states.NoEach { + t.Fatalf("expected each mode NoEach, got %s", i.EachMode) + } + } func TestStateMv_resourceToInstance(t *testing.T) {