From 2bfaddcf5776343957d08aa84747c685c82d31bc Mon Sep 17 00:00:00 2001 From: James Bardin Date: Fri, 24 Apr 2020 21:52:05 -0400 Subject: [PATCH] fix state mv to work without EachMode The only situation where `state mv` needs to understand the each mode is when with resource addresses that may reference a single instance, or a group of for_each or count instances. In this case we can differentiate the two by checking the existence of the NoKey instance key. --- command/state_mv.go | 32 +++++++------------------------- command/state_mv_test.go | 24 +++++++++++++----------- 2 files changed, 20 insertions(+), 36 deletions(-) diff --git a/command/state_mv.go b/command/state_mv.go index 7bcfb4428..10e9a86f7 100644 --- a/command/state_mv.go +++ b/command/state_mv.go @@ -279,10 +279,6 @@ func (c *StateMvCommand) Run(args []string) int { 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 @@ -291,15 +287,13 @@ func (c *StateMvCommand) Run(args []string) int { // address covers both). If there's an index in the // target then allow creating the new instance here. resourceAddr := addrTo.ContainingResource() - stateTo.SyncWrapper().SetResourceMeta( + stateTo.SyncWrapper().SetResourceProvider( resourceAddr, - 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: @@ -372,20 +366,6 @@ func (c *StateMvCommand) Run(args []string) int { return 0 } -func eachModeForInstanceKey(key addrs.InstanceKey) states.EachMode { - switch key.(type) { - case addrs.IntKey: - return states.EachList - case addrs.StringKey: - return states.EachMap - default: - if key == addrs.NoKey { - return states.NoEach - } - panic(fmt.Sprintf("don't know an each mode for instance key %#v", key)) - } -} - // sourceObjectAddrs takes a single source object address and expands it to // potentially multiple objects that need to be handled within it. // @@ -415,10 +395,12 @@ func (c *StateMvCommand) sourceObjectAddrs(state *states.State, matched addrs.Ta // terraform state mv aws_instance.foo aws_instance.bar[1] // That wouldn't be allowed if aws_instance.foo had multiple instances // since we can't move multiple instances into one. - if rs := state.Resource(addr); rs != nil && rs.EachMode == states.NoEach { - ret = append(ret, addr.Instance(addrs.NoKey)) - } else { - ret = append(ret, addr) + if rs := state.Resource(addr); rs != nil { + if _, ok := rs.Instances[addrs.NoKey]; ok { + ret = append(ret, addr.Instance(addrs.NoKey)) + } else { + ret = append(ret, addr) + } } default: ret = append(ret, matched) diff --git a/command/state_mv_test.go b/command/state_mv_test.go index e84aca6f1..f970185b1 100644 --- a/command/state_mv_test.go +++ b/command/state_mv_test.go @@ -97,9 +97,10 @@ func TestStateMv(t *testing.T) { 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) + for key := range s.Resource(addr).Instances { + if _, ok := key.(addrs.IntKey); !ok { + t.Fatalf("expected each mode List, got key %q", key) + } } // change from list to map @@ -118,9 +119,10 @@ func TestStateMv(t *testing.T) { 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) + for key := range s.Resource(addr).Instances { + if _, ok := key.(addrs.StringKey); !ok { + t.Fatalf("expected each mode map, found key %q", key) + } } // change from from map back to single @@ -139,9 +141,10 @@ func TestStateMv(t *testing.T) { 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) + for key := range s.Resource(addr).Instances { + if key != addrs.NoKey { + t.Fatalf("expected no each mode, found key %q", key) + } } } @@ -179,13 +182,12 @@ func TestStateMv_resourceToInstance(t *testing.T) { Module: addrs.RootModule, }, ) - s.SetResourceMeta( + s.SetResourceProvider( addrs.Resource{ Mode: addrs.ManagedResourceMode, Type: "test_instance", Name: "bar", }.Absolute(addrs.RootModuleInstance), - states.EachList, addrs.AbsProviderConfig{ Provider: addrs.NewLegacyProvider("test"), Module: addrs.RootModule,