From 32f7f583453929c52cd6ea386d4a8ff556c276ed Mon Sep 17 00:00:00 2001 From: James Bardin Date: Thu, 1 Aug 2019 18:54:09 -0400 Subject: [PATCH] allow moving resource to new modules not in state Create the missing modules in the state when moving resources to a module that doesn't yet exist. This allows for refactoring of configuration into new modules, without having to create dummy resources in the module before the "state mv" operations. --- command/state_mv.go | 14 ++---- command/state_mv_test.go | 92 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+), 10 deletions(-) diff --git a/command/state_mv.go b/command/state_mv.go index 11005ad79..db76b30d1 100644 --- a/command/state_mv.go +++ b/command/state_mv.go @@ -194,11 +194,8 @@ func (c *StateMvCommand) Run(args []string) int { } diags = diags.Append(c.validateResourceMove(addrFrom, addrTo)) if stateTo.Module(addrTo.Module) == nil { - diags = diags.Append(tfdiags.Sourceless( - tfdiags.Error, - msgInvalidTarget, - fmt.Sprintf("Cannot move to %s: %s does not exist in the current state.", addrTo, addrTo.Module), - )) + // moving something to a mew module, so we need to ensure it exists + stateTo.EnsureModule(addrTo.Module) } if stateTo.Resource(addrTo) != nil { diags = diags.Append(tfdiags.Sourceless( @@ -251,11 +248,8 @@ func (c *StateMvCommand) Run(args []string) int { diags = diags.Append(c.validateResourceMove(addrFrom.ContainingResource(), addrTo.ContainingResource())) if stateTo.Module(addrTo.Module) == nil { - diags = diags.Append(tfdiags.Sourceless( - tfdiags.Error, - msgInvalidTarget, - fmt.Sprintf("Cannot move to %s: %s does not exist in the current state.", addrTo, addrTo.Module), - )) + // moving something to a mew module, so we need to ensure it exists + stateTo.EnsureModule(addrTo.Module) } if stateTo.ResourceInstance(addrTo) != nil { diags = diags.Append(tfdiags.Sourceless( diff --git a/command/state_mv_test.go b/command/state_mv_test.go index e0fae25fc..504c4fca1 100644 --- a/command/state_mv_test.go +++ b/command/state_mv_test.go @@ -765,6 +765,70 @@ func TestStateMv_stateOutNew_nestedModule(t *testing.T) { testStateOutput(t, backups[0], testStateMvNestedModule_stateOutOriginal) } +func TestStateMv_toNewModule(t *testing.T) { + state := states.BuildState(func(s *states.SyncState) { + s.SetResourceInstanceCurrent( + addrs.Resource{ + Mode: addrs.ManagedResourceMode, + Type: "test_instance", + Name: "bar", + }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance), + &states.ResourceInstanceObjectSrc{ + AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`), + Status: states.ObjectReady, + }, + addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance), + ) + }) + + statePath := testStateFile(t, state) + stateOutPath1 := statePath + ".out1" + stateOutPath2 := statePath + ".out2" + + p := testProvider() + ui := new(cli.MockUi) + c := &StateMvCommand{ + StateMeta{ + Meta: Meta{ + testingOverrides: metaOverridesForProvider(p), + Ui: ui, + }, + }, + } + + args := []string{ + "-state", statePath, + "-state-out", stateOutPath1, + "test_instance.bar", + "module.bar.test_instance.bar", + } + if code := c.Run(args); code != 0 { + t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) + } + + // Test it is correct + testStateOutput(t, stateOutPath1, testStateMvNewModule_stateOut) + testStateOutput(t, statePath, testStateMvNestedModule_stateOutSrc) + + // Test we have backups + backups := testStateBackups(t, filepath.Dir(statePath)) + if len(backups) != 1 { + t.Fatalf("bad: %#v", backups) + } + testStateOutput(t, backups[0], testStateMvNewModule_stateOutOriginal) + + // now verify we can move the module itself + args = []string{ + "-state", stateOutPath1, + "-state-out", stateOutPath2, + "module.bar", + "module.foo", + } + if code := c.Run(args); code != 0 { + t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) + } + testStateOutput(t, stateOutPath2, testStateMvModuleNewModule_stateOut) +} func TestStateMv_withinBackend(t *testing.T) { td := tempDir(t) copy.CopyDir(testFixturePath("backend-unchanged"), td) @@ -1129,6 +1193,34 @@ module.bar.child2: foo = value ` +const testStateMvNewModule_stateOut = ` + +module.bar: + test_instance.bar: + ID = bar + provider = provider.test + bar = value + foo = value +` + +const testStateMvModuleNewModule_stateOut = ` + +module.foo: + test_instance.bar: + ID = bar + provider = provider.test + bar = value + foo = value +` + +const testStateMvNewModule_stateOutOriginal = ` +test_instance.bar: + ID = bar + provider = provider.test + bar = value + foo = value +` + const testStateMvNestedModule_stateOutSrc = ` `