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.
This commit is contained in:
James Bardin 2019-08-01 18:54:09 -04:00
parent e0329c2e0f
commit 32f7f58345
2 changed files with 96 additions and 10 deletions

View File

@ -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(

View File

@ -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 = `
<no state>
module.bar:
test_instance.bar:
ID = bar
provider = provider.test
bar = value
foo = value
`
const testStateMvModuleNewModule_stateOut = `
<no state>
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 = `
<no state>
`