Skip to content

Commit a3be475

Browse files
authored
Merge pull request #24254 from hashicorp/jbardin/state-mv
state mv should always use target address to determine each mode.
2 parents 430b7c8 + 10d9269 commit a3be475

File tree

2 files changed

+72
-9
lines changed

2 files changed

+72
-9
lines changed

command/state_mv.go

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -280,31 +280,30 @@ func (c *StateMvCommand) Run(args []string) int {
280280
fromResourceAddr := addrFrom.ContainingResource()
281281
fromResource := ssFrom.Resource(fromResourceAddr)
282282
fromProviderAddr := fromResource.ProviderConfig
283-
fromEachMode := fromResource.EachMode
284283
ssFrom.ForgetResourceInstanceAll(addrFrom)
285284
ssFrom.RemoveResourceIfEmpty(fromResourceAddr)
286285

286+
// since this is moving an instance, we can infer the target
287+
// mode from the address.
288+
toEachMode := eachModeForInstanceKey(addrTo.Resource.Key)
289+
287290
rs := stateTo.Resource(addrTo.ContainingResource())
288291
if rs == nil {
289292
// If we're moving to an address without an index then that
290293
// suggests the user's intent is to establish both the
291294
// resource and the instance at the same time (since the
292295
// address covers both). If there's an index in the
293-
// target then allow creating the new instance here,
294-
// inferring the mode from how the new address was parsed.
295-
if addrTo.Resource.Key != addrs.NoKey {
296-
fromEachMode = eachModeForInstanceKey(addrTo.Resource.Key)
297-
}
298-
296+
// target then allow creating the new instance here.
299297
resourceAddr := addrTo.ContainingResource()
300298
stateTo.SyncWrapper().SetResourceMeta(
301299
resourceAddr,
302-
fromEachMode,
300+
toEachMode,
303301
fromProviderAddr, // in this case, we bring the provider along as if we were moving the whole resource
304302
)
305303
rs = stateTo.Resource(resourceAddr)
306304
}
307305

306+
rs.EachMode = toEachMode
308307
rs.Instances[addrTo.Resource.Key] = is
309308
}
310309
default:

command/state_mv_test.go

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ func TestStateMv(t *testing.T) {
6868
"test_instance.bar",
6969
}
7070
if code := c.Run(args); code != 0 {
71-
t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
71+
t.Fatalf("return code: %d\n\n%s", code, ui.ErrorWriter.String())
7272
}
7373

7474
// Test it is correct
@@ -80,6 +80,70 @@ func TestStateMv(t *testing.T) {
8080
t.Fatalf("bad: %#v", backups)
8181
}
8282
testStateOutput(t, backups[0], testStateMvOutputOriginal)
83+
84+
// Change the single instance to a counted instance
85+
args = []string{
86+
"-state", statePath,
87+
"test_instance.bar",
88+
"test_instance.bar[0]",
89+
}
90+
if code := c.Run(args); code != 0 {
91+
t.Fatalf("return code: %d\n\n%s", code, ui.ErrorWriter.String())
92+
}
93+
94+
// extract the resource and verify the mode
95+
s := testStateRead(t, statePath)
96+
addr, diags := addrs.ParseAbsResourceStr("test_instance.bar")
97+
if diags.HasErrors() {
98+
t.Fatal(diags.Err())
99+
}
100+
i := s.Resource(addr)
101+
if i.EachMode != states.EachList {
102+
t.Fatalf("expected each mode List, got %s", i.EachMode)
103+
}
104+
105+
// change from list to map
106+
args = []string{
107+
"-state", statePath,
108+
"test_instance.bar[0]",
109+
"test_instance.bar[\"baz\"]",
110+
}
111+
if code := c.Run(args); code != 0 {
112+
t.Fatalf("return code: %d\n\n%s", code, ui.ErrorWriter.String())
113+
}
114+
115+
// extract the resource and verify the mode
116+
s = testStateRead(t, statePath)
117+
addr, diags = addrs.ParseAbsResourceStr("test_instance.bar")
118+
if diags.HasErrors() {
119+
t.Fatal(diags.Err())
120+
}
121+
i = s.Resource(addr)
122+
if i.EachMode != states.EachMap {
123+
t.Fatalf("expected each mode Map, got %s", i.EachMode)
124+
}
125+
126+
// change from from map back to single
127+
args = []string{
128+
"-state", statePath,
129+
"test_instance.bar[\"baz\"]",
130+
"test_instance.bar",
131+
}
132+
if code := c.Run(args); code != 0 {
133+
t.Fatalf("return code: %d\n\n%s", code, ui.ErrorWriter.String())
134+
}
135+
136+
// extract the resource and verify the mode
137+
s = testStateRead(t, statePath)
138+
addr, diags = addrs.ParseAbsResourceStr("test_instance.bar")
139+
if diags.HasErrors() {
140+
t.Fatal(diags.Err())
141+
}
142+
i = s.Resource(addr)
143+
if i.EachMode != states.NoEach {
144+
t.Fatalf("expected each mode NoEach, got %s", i.EachMode)
145+
}
146+
83147
}
84148

85149
func TestStateMv_resourceToInstance(t *testing.T) {

0 commit comments

Comments
 (0)