github.com/rstandt/terraform@v0.12.32-0.20230710220336-b1063613405c/command/state_mv_test.go (about) 1 package command 2 3 import ( 4 "fmt" 5 "os" 6 "path/filepath" 7 "strings" 8 "testing" 9 10 "github.com/mitchellh/cli" 11 12 "github.com/hashicorp/terraform/addrs" 13 "github.com/hashicorp/terraform/helper/copy" 14 "github.com/hashicorp/terraform/states" 15 "github.com/hashicorp/terraform/terraform" 16 ) 17 18 func TestStateMv(t *testing.T) { 19 state := states.BuildState(func(s *states.SyncState) { 20 s.SetResourceInstanceCurrent( 21 addrs.Resource{ 22 Mode: addrs.ManagedResourceMode, 23 Type: "test_instance", 24 Name: "foo", 25 }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance), 26 &states.ResourceInstanceObjectSrc{ 27 AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`), 28 Status: states.ObjectReady, 29 }, 30 addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), 31 ) 32 s.SetResourceInstanceCurrent( 33 addrs.Resource{ 34 Mode: addrs.ManagedResourceMode, 35 Type: "test_instance", 36 Name: "baz", 37 }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance), 38 &states.ResourceInstanceObjectSrc{ 39 AttrsJSON: []byte(`{"id":"foo","foo":"value","bar":"value"}`), 40 Status: states.ObjectReady, 41 Dependencies: []addrs.AbsResource{mustResourceAddr("test_instance.foo")}, 42 }, 43 addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), 44 ) 45 }) 46 statePath := testStateFile(t, state) 47 48 p := testProvider() 49 ui := new(cli.MockUi) 50 c := &StateMvCommand{ 51 StateMeta{ 52 Meta: Meta{ 53 testingOverrides: metaOverridesForProvider(p), 54 Ui: ui, 55 }, 56 }, 57 } 58 59 args := []string{ 60 "-state", statePath, 61 "test_instance.foo", 62 "test_instance.bar", 63 } 64 if code := c.Run(args); code != 0 { 65 t.Fatalf("return code: %d\n\n%s", code, ui.ErrorWriter.String()) 66 } 67 68 // Test it is correct 69 testStateOutput(t, statePath, testStateMvOutput) 70 71 // Test we have backups 72 backups := testStateBackups(t, filepath.Dir(statePath)) 73 if len(backups) != 1 { 74 t.Fatalf("bad: %#v", backups) 75 } 76 testStateOutput(t, backups[0], testStateMvOutputOriginal) 77 78 // Change the single instance to a counted instance 79 args = []string{ 80 "-state", statePath, 81 "test_instance.bar", 82 "test_instance.bar[0]", 83 } 84 if code := c.Run(args); code != 0 { 85 t.Fatalf("return code: %d\n\n%s", code, ui.ErrorWriter.String()) 86 } 87 88 // extract the resource and verify the mode 89 s := testStateRead(t, statePath) 90 addr, diags := addrs.ParseAbsResourceStr("test_instance.bar") 91 if diags.HasErrors() { 92 t.Fatal(diags.Err()) 93 } 94 i := s.Resource(addr) 95 if i.EachMode != states.EachList { 96 t.Fatalf("expected each mode List, got %s", i.EachMode) 97 } 98 99 // change from list to map 100 args = []string{ 101 "-state", statePath, 102 "test_instance.bar[0]", 103 "test_instance.bar[\"baz\"]", 104 } 105 if code := c.Run(args); code != 0 { 106 t.Fatalf("return code: %d\n\n%s", code, ui.ErrorWriter.String()) 107 } 108 109 // extract the resource and verify the mode 110 s = testStateRead(t, statePath) 111 addr, diags = addrs.ParseAbsResourceStr("test_instance.bar") 112 if diags.HasErrors() { 113 t.Fatal(diags.Err()) 114 } 115 i = s.Resource(addr) 116 if i.EachMode != states.EachMap { 117 t.Fatalf("expected each mode Map, got %s", i.EachMode) 118 } 119 120 // change from from map back to single 121 args = []string{ 122 "-state", statePath, 123 "test_instance.bar[\"baz\"]", 124 "test_instance.bar", 125 } 126 if code := c.Run(args); code != 0 { 127 t.Fatalf("return code: %d\n\n%s", code, ui.ErrorWriter.String()) 128 } 129 130 // extract the resource and verify the mode 131 s = testStateRead(t, statePath) 132 addr, diags = addrs.ParseAbsResourceStr("test_instance.bar") 133 if diags.HasErrors() { 134 t.Fatal(diags.Err()) 135 } 136 i = s.Resource(addr) 137 if i.EachMode != states.NoEach { 138 t.Fatalf("expected each mode NoEach, got %s", i.EachMode) 139 } 140 141 } 142 143 func TestStateMv_resourceToInstance(t *testing.T) { 144 state := states.BuildState(func(s *states.SyncState) { 145 s.SetResourceInstanceCurrent( 146 addrs.Resource{ 147 Mode: addrs.ManagedResourceMode, 148 Type: "test_instance", 149 Name: "foo", 150 }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance), 151 &states.ResourceInstanceObjectSrc{ 152 AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`), 153 Status: states.ObjectReady, 154 }, 155 addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), 156 ) 157 s.SetResourceInstanceCurrent( 158 addrs.Resource{ 159 Mode: addrs.ManagedResourceMode, 160 Type: "test_instance", 161 Name: "baz", 162 }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance), 163 &states.ResourceInstanceObjectSrc{ 164 AttrsJSON: []byte(`{"id":"foo","foo":"value","bar":"value"}`), 165 Status: states.ObjectReady, 166 Dependencies: []addrs.AbsResource{mustResourceAddr("test_instance.foo")}, 167 }, 168 addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), 169 ) 170 s.SetResourceMeta( 171 addrs.Resource{ 172 Mode: addrs.ManagedResourceMode, 173 Type: "test_instance", 174 Name: "bar", 175 }.Absolute(addrs.RootModuleInstance), 176 states.EachList, 177 addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), 178 ) 179 }) 180 statePath := testStateFile(t, state) 181 182 p := testProvider() 183 ui := new(cli.MockUi) 184 c := &StateMvCommand{ 185 StateMeta{ 186 Meta: Meta{ 187 testingOverrides: metaOverridesForProvider(p), 188 Ui: ui, 189 }, 190 }, 191 } 192 193 args := []string{ 194 "-state", statePath, 195 "test_instance.foo", 196 "test_instance.bar[0]", 197 } 198 if code := c.Run(args); code != 0 { 199 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 200 } 201 202 // Test it is correct 203 testStateOutput(t, statePath, ` 204 test_instance.bar.0: 205 ID = bar 206 provider = provider.test 207 bar = value 208 foo = value 209 test_instance.baz: 210 ID = foo 211 provider = provider.test 212 bar = value 213 foo = value 214 `) 215 216 // Test we have backups 217 backups := testStateBackups(t, filepath.Dir(statePath)) 218 if len(backups) != 1 { 219 t.Fatalf("bad: %#v", backups) 220 } 221 testStateOutput(t, backups[0], testStateMvOutputOriginal) 222 } 223 224 func TestStateMv_instanceToResource(t *testing.T) { 225 state := states.BuildState(func(s *states.SyncState) { 226 s.SetResourceInstanceCurrent( 227 addrs.Resource{ 228 Mode: addrs.ManagedResourceMode, 229 Type: "test_instance", 230 Name: "foo", 231 }.Instance(addrs.IntKey(0)).Absolute(addrs.RootModuleInstance), 232 &states.ResourceInstanceObjectSrc{ 233 AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`), 234 Status: states.ObjectReady, 235 }, 236 addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), 237 ) 238 s.SetResourceInstanceCurrent( 239 addrs.Resource{ 240 Mode: addrs.ManagedResourceMode, 241 Type: "test_instance", 242 Name: "baz", 243 }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance), 244 &states.ResourceInstanceObjectSrc{ 245 AttrsJSON: []byte(`{"id":"foo","foo":"value","bar":"value"}`), 246 Status: states.ObjectReady, 247 }, 248 addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), 249 ) 250 }) 251 statePath := testStateFile(t, state) 252 253 p := testProvider() 254 ui := new(cli.MockUi) 255 c := &StateMvCommand{ 256 StateMeta{ 257 Meta: Meta{ 258 testingOverrides: metaOverridesForProvider(p), 259 Ui: ui, 260 }, 261 }, 262 } 263 264 args := []string{ 265 "-state", statePath, 266 "test_instance.foo[0]", 267 "test_instance.bar", 268 } 269 if code := c.Run(args); code != 0 { 270 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 271 } 272 273 // Test it is correct 274 testStateOutput(t, statePath, ` 275 test_instance.bar: 276 ID = bar 277 provider = provider.test 278 bar = value 279 foo = value 280 test_instance.baz: 281 ID = foo 282 provider = provider.test 283 bar = value 284 foo = value 285 `) 286 287 // Test we have backups 288 backups := testStateBackups(t, filepath.Dir(statePath)) 289 if len(backups) != 1 { 290 t.Fatalf("bad: %#v", backups) 291 } 292 testStateOutput(t, backups[0], ` 293 test_instance.baz: 294 ID = foo 295 provider = provider.test 296 bar = value 297 foo = value 298 test_instance.foo.0: 299 ID = bar 300 provider = provider.test 301 bar = value 302 foo = value 303 `) 304 } 305 306 func TestStateMv_instanceToNewResource(t *testing.T) { 307 state := states.BuildState(func(s *states.SyncState) { 308 s.SetResourceInstanceCurrent( 309 addrs.Resource{ 310 Mode: addrs.ManagedResourceMode, 311 Type: "test_instance", 312 Name: "foo", 313 }.Instance(addrs.IntKey(0)).Absolute(addrs.RootModuleInstance), 314 &states.ResourceInstanceObjectSrc{ 315 AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`), 316 Status: states.ObjectReady, 317 }, 318 addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), 319 ) 320 }) 321 statePath := testStateFile(t, state) 322 323 p := testProvider() 324 ui := new(cli.MockUi) 325 c := &StateMvCommand{ 326 StateMeta{ 327 Meta: Meta{ 328 testingOverrides: metaOverridesForProvider(p), 329 Ui: ui, 330 }, 331 }, 332 } 333 334 args := []string{ 335 "-state", statePath, 336 "test_instance.foo[0]", 337 "test_instance.bar[\"new\"]", 338 } 339 if code := c.Run(args); code != 0 { 340 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 341 } 342 343 // Test it is correct 344 testStateOutput(t, statePath, ` 345 test_instance.bar["new"]: 346 ID = bar 347 provider = provider.test 348 bar = value 349 foo = value 350 `) 351 352 // now move the instance to a new resource in a new module 353 args = []string{ 354 "-state", statePath, 355 "test_instance.bar[\"new\"]", 356 "module.test.test_instance.baz[\"new\"]", 357 } 358 if code := c.Run(args); code != 0 { 359 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 360 } 361 362 // Test it is correct 363 testStateOutput(t, statePath, ` 364 <no state> 365 module.test: 366 test_instance.baz["new"]: 367 ID = bar 368 provider = provider.test 369 bar = value 370 foo = value 371 `) 372 } 373 374 func TestStateMv_differentResourceTypes(t *testing.T) { 375 state := states.BuildState(func(s *states.SyncState) { 376 s.SetResourceInstanceCurrent( 377 addrs.Resource{ 378 Mode: addrs.ManagedResourceMode, 379 Type: "test_instance", 380 Name: "foo", 381 }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance), 382 &states.ResourceInstanceObjectSrc{ 383 AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`), 384 Status: states.ObjectReady, 385 }, 386 addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), 387 ) 388 }) 389 statePath := testStateFile(t, state) 390 391 p := testProvider() 392 ui := new(cli.MockUi) 393 c := &StateMvCommand{ 394 StateMeta{ 395 Meta: Meta{ 396 testingOverrides: metaOverridesForProvider(p), 397 Ui: ui, 398 }, 399 }, 400 } 401 402 args := []string{ 403 "-state", statePath, 404 "test_instance.foo", 405 "test_network.bar", 406 } 407 if code := c.Run(args); code == 0 { 408 t.Fatalf("expected error output, got:\n%s", ui.OutputWriter.String()) 409 } 410 411 if !strings.Contains(ui.ErrorWriter.String(), "resource types don't match") { 412 t.Fatalf("expected initialization error, got:\n%s", ui.ErrorWriter.String()) 413 } 414 } 415 416 // don't modify backend state is we supply a -state flag 417 func TestStateMv_explicitWithBackend(t *testing.T) { 418 td := tempDir(t) 419 copy.CopyDir(testFixturePath("init-backend"), td) 420 defer os.RemoveAll(td) 421 defer testChdir(t, td)() 422 423 backupPath := filepath.Join(td, "backup") 424 425 state := states.BuildState(func(s *states.SyncState) { 426 s.SetResourceInstanceCurrent( 427 addrs.Resource{ 428 Mode: addrs.ManagedResourceMode, 429 Type: "test_instance", 430 Name: "foo", 431 }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance), 432 &states.ResourceInstanceObjectSrc{ 433 AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`), 434 Status: states.ObjectReady, 435 }, 436 addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), 437 ) 438 s.SetResourceInstanceCurrent( 439 addrs.Resource{ 440 Mode: addrs.ManagedResourceMode, 441 Type: "test_instance", 442 Name: "baz", 443 }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance), 444 &states.ResourceInstanceObjectSrc{ 445 AttrsJSON: []byte(`{"id":"foo","foo":"value","bar":"value"}`), 446 Status: states.ObjectReady, 447 }, 448 addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), 449 ) 450 }) 451 statePath := testStateFile(t, state) 452 453 // init our backend 454 ui := new(cli.MockUi) 455 ic := &InitCommand{ 456 Meta: Meta{ 457 testingOverrides: metaOverridesForProvider(testProvider()), 458 Ui: ui, 459 }, 460 } 461 462 args := []string{} 463 if code := ic.Run(args); code != 0 { 464 t.Fatalf("bad: \n%s", ui.ErrorWriter.String()) 465 } 466 467 // only modify statePath 468 p := testProvider() 469 ui = new(cli.MockUi) 470 c := &StateMvCommand{ 471 StateMeta{ 472 Meta: Meta{ 473 testingOverrides: metaOverridesForProvider(p), 474 Ui: ui, 475 }, 476 }, 477 } 478 479 args = []string{ 480 "-backup", backupPath, 481 "-state", statePath, 482 "test_instance.foo", 483 "test_instance.bar", 484 } 485 if code := c.Run(args); code != 0 { 486 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 487 } 488 489 // Test it is correct 490 testStateOutput(t, statePath, testStateMvOutput) 491 } 492 493 func TestStateMv_backupExplicit(t *testing.T) { 494 state := states.BuildState(func(s *states.SyncState) { 495 s.SetResourceInstanceCurrent( 496 addrs.Resource{ 497 Mode: addrs.ManagedResourceMode, 498 Type: "test_instance", 499 Name: "foo", 500 }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance), 501 &states.ResourceInstanceObjectSrc{ 502 AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`), 503 Status: states.ObjectReady, 504 }, 505 addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), 506 ) 507 s.SetResourceInstanceCurrent( 508 addrs.Resource{ 509 Mode: addrs.ManagedResourceMode, 510 Type: "test_instance", 511 Name: "baz", 512 }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance), 513 &states.ResourceInstanceObjectSrc{ 514 AttrsJSON: []byte(`{"id":"foo","foo":"value","bar":"value"}`), 515 Status: states.ObjectReady, 516 Dependencies: []addrs.AbsResource{mustResourceAddr("test_instance.foo")}, 517 }, 518 addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), 519 ) 520 }) 521 statePath := testStateFile(t, state) 522 backupPath := statePath + ".backup.test" 523 524 p := testProvider() 525 ui := new(cli.MockUi) 526 c := &StateMvCommand{ 527 StateMeta{ 528 Meta: Meta{ 529 testingOverrides: metaOverridesForProvider(p), 530 Ui: ui, 531 }, 532 }, 533 } 534 535 args := []string{ 536 "-backup", backupPath, 537 "-state", statePath, 538 "test_instance.foo", 539 "test_instance.bar", 540 } 541 if code := c.Run(args); code != 0 { 542 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 543 } 544 545 // Test it is correct 546 testStateOutput(t, statePath, testStateMvOutput) 547 548 // Test backup 549 testStateOutput(t, backupPath, testStateMvOutputOriginal) 550 } 551 552 func TestStateMv_stateOutNew(t *testing.T) { 553 state := states.BuildState(func(s *states.SyncState) { 554 s.SetResourceInstanceCurrent( 555 addrs.Resource{ 556 Mode: addrs.ManagedResourceMode, 557 Type: "test_instance", 558 Name: "foo", 559 }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance), 560 &states.ResourceInstanceObjectSrc{ 561 AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`), 562 Status: states.ObjectReady, 563 }, 564 addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), 565 ) 566 }) 567 statePath := testStateFile(t, state) 568 stateOutPath := statePath + ".out" 569 570 p := testProvider() 571 ui := new(cli.MockUi) 572 c := &StateMvCommand{ 573 StateMeta{ 574 Meta: Meta{ 575 testingOverrides: metaOverridesForProvider(p), 576 Ui: ui, 577 }, 578 }, 579 } 580 581 args := []string{ 582 "-state", statePath, 583 "-state-out", stateOutPath, 584 "test_instance.foo", 585 "test_instance.bar", 586 } 587 if code := c.Run(args); code != 0 { 588 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 589 } 590 591 // Test it is correct 592 testStateOutput(t, stateOutPath, testStateMvOutput_stateOut) 593 testStateOutput(t, statePath, testStateMvOutput_stateOutSrc) 594 595 // Test we have backups 596 backups := testStateBackups(t, filepath.Dir(statePath)) 597 if len(backups) != 1 { 598 t.Fatalf("bad: %#v", backups) 599 } 600 testStateOutput(t, backups[0], testStateMvOutput_stateOutOriginal) 601 } 602 603 func TestStateMv_stateOutExisting(t *testing.T) { 604 stateSrc := states.BuildState(func(s *states.SyncState) { 605 s.SetResourceInstanceCurrent( 606 addrs.Resource{ 607 Mode: addrs.ManagedResourceMode, 608 Type: "test_instance", 609 Name: "foo", 610 }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance), 611 &states.ResourceInstanceObjectSrc{ 612 AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`), 613 Status: states.ObjectReady, 614 }, 615 addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), 616 ) 617 }) 618 statePath := testStateFile(t, stateSrc) 619 620 stateDst := states.BuildState(func(s *states.SyncState) { 621 s.SetResourceInstanceCurrent( 622 addrs.Resource{ 623 Mode: addrs.ManagedResourceMode, 624 Type: "test_instance", 625 Name: "qux", 626 }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance), 627 &states.ResourceInstanceObjectSrc{ 628 AttrsJSON: []byte(`{"id":"bar"}`), 629 Status: states.ObjectReady, 630 }, 631 addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), 632 ) 633 }) 634 stateOutPath := testStateFile(t, stateDst) 635 636 p := testProvider() 637 ui := new(cli.MockUi) 638 c := &StateMvCommand{ 639 StateMeta{ 640 Meta: Meta{ 641 testingOverrides: metaOverridesForProvider(p), 642 Ui: ui, 643 }, 644 }, 645 } 646 647 args := []string{ 648 "-state", statePath, 649 "-state-out", stateOutPath, 650 "test_instance.foo", 651 "test_instance.bar", 652 } 653 if code := c.Run(args); code != 0 { 654 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 655 } 656 657 // Test it is correct 658 testStateOutput(t, stateOutPath, testStateMvExisting_stateDst) 659 testStateOutput(t, statePath, testStateMvExisting_stateSrc) 660 661 // Test we have backups 662 backups := testStateBackups(t, filepath.Dir(statePath)) 663 if len(backups) != 1 { 664 t.Fatalf("bad: %#v", backups) 665 } 666 testStateOutput(t, backups[0], testStateMvExisting_stateSrcOriginal) 667 668 backups = testStateBackups(t, filepath.Dir(stateOutPath)) 669 if len(backups) != 1 { 670 t.Fatalf("bad: %#v", backups) 671 } 672 testStateOutput(t, backups[0], testStateMvExisting_stateDstOriginal) 673 } 674 675 func TestStateMv_noState(t *testing.T) { 676 tmp, cwd := testCwd(t) 677 defer testFixCwd(t, tmp, cwd) 678 679 p := testProvider() 680 ui := new(cli.MockUi) 681 c := &StateMvCommand{ 682 StateMeta{ 683 Meta: Meta{ 684 testingOverrides: metaOverridesForProvider(p), 685 Ui: ui, 686 }, 687 }, 688 } 689 690 args := []string{"from", "to"} 691 if code := c.Run(args); code != 1 { 692 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 693 } 694 } 695 696 func TestStateMv_stateOutNew_count(t *testing.T) { 697 state := states.BuildState(func(s *states.SyncState) { 698 s.SetResourceInstanceCurrent( 699 addrs.Resource{ 700 Mode: addrs.ManagedResourceMode, 701 Type: "test_instance", 702 Name: "foo", 703 }.Instance(addrs.IntKey(0)).Absolute(addrs.RootModuleInstance), 704 &states.ResourceInstanceObjectSrc{ 705 AttrsJSON: []byte(`{"id":"foo","foo":"value","bar":"value"}`), 706 Status: states.ObjectReady, 707 }, 708 addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), 709 ) 710 s.SetResourceInstanceCurrent( 711 addrs.Resource{ 712 Mode: addrs.ManagedResourceMode, 713 Type: "test_instance", 714 Name: "foo", 715 }.Instance(addrs.IntKey(1)).Absolute(addrs.RootModuleInstance), 716 &states.ResourceInstanceObjectSrc{ 717 AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`), 718 Status: states.ObjectReady, 719 }, 720 addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), 721 ) 722 s.SetResourceInstanceCurrent( 723 addrs.Resource{ 724 Mode: addrs.ManagedResourceMode, 725 Type: "test_instance", 726 Name: "bar", 727 }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance), 728 &states.ResourceInstanceObjectSrc{ 729 AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`), 730 Status: states.ObjectReady, 731 }, 732 addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), 733 ) 734 }) 735 statePath := testStateFile(t, state) 736 stateOutPath := statePath + ".out" 737 738 p := testProvider() 739 ui := new(cli.MockUi) 740 c := &StateMvCommand{ 741 StateMeta{ 742 Meta: Meta{ 743 testingOverrides: metaOverridesForProvider(p), 744 Ui: ui, 745 }, 746 }, 747 } 748 749 args := []string{ 750 "-state", statePath, 751 "-state-out", stateOutPath, 752 "test_instance.foo", 753 "test_instance.bar", 754 } 755 if code := c.Run(args); code != 0 { 756 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 757 } 758 759 // Test it is correct 760 testStateOutput(t, stateOutPath, testStateMvCount_stateOut) 761 testStateOutput(t, statePath, testStateMvCount_stateOutSrc) 762 763 // Test we have backups 764 backups := testStateBackups(t, filepath.Dir(statePath)) 765 if len(backups) != 1 { 766 t.Fatalf("bad: %#v", backups) 767 } 768 testStateOutput(t, backups[0], testStateMvCount_stateOutOriginal) 769 } 770 771 // Modules with more than 10 resources were sorted lexically, causing the 772 // indexes in the new location to change. 773 func TestStateMv_stateOutNew_largeCount(t *testing.T) { 774 state := states.BuildState(func(s *states.SyncState) { 775 // test_instance.foo has 11 instances, all the same except for their ids 776 for i := 0; i < 11; i++ { 777 s.SetResourceInstanceCurrent( 778 addrs.Resource{ 779 Mode: addrs.ManagedResourceMode, 780 Type: "test_instance", 781 Name: "foo", 782 }.Instance(addrs.IntKey(i)).Absolute(addrs.RootModuleInstance), 783 &states.ResourceInstanceObjectSrc{ 784 AttrsJSON: []byte(fmt.Sprintf(`{"id":"foo%d","foo":"value","bar":"value"}`, i)), 785 Status: states.ObjectReady, 786 }, 787 addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), 788 ) 789 } 790 s.SetResourceInstanceCurrent( 791 addrs.Resource{ 792 Mode: addrs.ManagedResourceMode, 793 Type: "test_instance", 794 Name: "bar", 795 }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance), 796 &states.ResourceInstanceObjectSrc{ 797 AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`), 798 Status: states.ObjectReady, 799 }, 800 addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), 801 ) 802 }) 803 statePath := testStateFile(t, state) 804 stateOutPath := statePath + ".out" 805 806 p := testProvider() 807 ui := new(cli.MockUi) 808 c := &StateMvCommand{ 809 StateMeta{ 810 Meta: Meta{ 811 testingOverrides: metaOverridesForProvider(p), 812 Ui: ui, 813 }, 814 }, 815 } 816 817 args := []string{ 818 "-state", statePath, 819 "-state-out", stateOutPath, 820 "test_instance.foo", 821 "test_instance.bar", 822 } 823 if code := c.Run(args); code != 0 { 824 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 825 } 826 827 // Test it is correct 828 testStateOutput(t, stateOutPath, testStateMvLargeCount_stateOut) 829 testStateOutput(t, statePath, testStateMvLargeCount_stateOutSrc) 830 831 // Test we have backups 832 backups := testStateBackups(t, filepath.Dir(statePath)) 833 if len(backups) != 1 { 834 t.Fatalf("bad: %#v", backups) 835 } 836 testStateOutput(t, backups[0], testStateMvLargeCount_stateOutOriginal) 837 } 838 839 func TestStateMv_stateOutNew_nestedModule(t *testing.T) { 840 state := states.BuildState(func(s *states.SyncState) { 841 s.SetResourceInstanceCurrent( 842 addrs.Resource{ 843 Mode: addrs.ManagedResourceMode, 844 Type: "test_instance", 845 Name: "foo", 846 }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance.Child("foo", addrs.NoKey).Child("child1", addrs.NoKey)), 847 &states.ResourceInstanceObjectSrc{ 848 AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`), 849 Status: states.ObjectReady, 850 }, 851 addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), 852 ) 853 s.SetResourceInstanceCurrent( 854 addrs.Resource{ 855 Mode: addrs.ManagedResourceMode, 856 Type: "test_instance", 857 Name: "foo", 858 }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance.Child("foo", addrs.NoKey).Child("child2", addrs.NoKey)), 859 &states.ResourceInstanceObjectSrc{ 860 AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`), 861 Status: states.ObjectReady, 862 }, 863 addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), 864 ) 865 }) 866 867 statePath := testStateFile(t, state) 868 stateOutPath := statePath + ".out" 869 870 p := testProvider() 871 ui := new(cli.MockUi) 872 c := &StateMvCommand{ 873 StateMeta{ 874 Meta: Meta{ 875 testingOverrides: metaOverridesForProvider(p), 876 Ui: ui, 877 }, 878 }, 879 } 880 881 args := []string{ 882 "-state", statePath, 883 "-state-out", stateOutPath, 884 "module.foo", 885 "module.bar", 886 } 887 if code := c.Run(args); code != 0 { 888 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 889 } 890 891 // Test it is correct 892 testStateOutput(t, stateOutPath, testStateMvNestedModule_stateOut) 893 testStateOutput(t, statePath, testStateMvNestedModule_stateOutSrc) 894 895 // Test we have backups 896 backups := testStateBackups(t, filepath.Dir(statePath)) 897 if len(backups) != 1 { 898 t.Fatalf("bad: %#v", backups) 899 } 900 testStateOutput(t, backups[0], testStateMvNestedModule_stateOutOriginal) 901 } 902 903 func TestStateMv_toNewModule(t *testing.T) { 904 state := states.BuildState(func(s *states.SyncState) { 905 s.SetResourceInstanceCurrent( 906 addrs.Resource{ 907 Mode: addrs.ManagedResourceMode, 908 Type: "test_instance", 909 Name: "bar", 910 }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance), 911 &states.ResourceInstanceObjectSrc{ 912 AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`), 913 Status: states.ObjectReady, 914 }, 915 addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), 916 ) 917 }) 918 919 statePath := testStateFile(t, state) 920 stateOutPath1 := statePath + ".out1" 921 stateOutPath2 := statePath + ".out2" 922 923 p := testProvider() 924 ui := new(cli.MockUi) 925 c := &StateMvCommand{ 926 StateMeta{ 927 Meta: Meta{ 928 testingOverrides: metaOverridesForProvider(p), 929 Ui: ui, 930 }, 931 }, 932 } 933 934 args := []string{ 935 "-state", statePath, 936 "-state-out", stateOutPath1, 937 "test_instance.bar", 938 "module.bar.test_instance.bar", 939 } 940 if code := c.Run(args); code != 0 { 941 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 942 } 943 944 // Test it is correct 945 testStateOutput(t, stateOutPath1, testStateMvNewModule_stateOut) 946 testStateOutput(t, statePath, testStateMvNestedModule_stateOutSrc) 947 948 // Test we have backups 949 backups := testStateBackups(t, filepath.Dir(statePath)) 950 if len(backups) != 1 { 951 t.Fatalf("bad: %#v", backups) 952 } 953 testStateOutput(t, backups[0], testStateMvNewModule_stateOutOriginal) 954 955 // now verify we can move the module itself 956 args = []string{ 957 "-state", stateOutPath1, 958 "-state-out", stateOutPath2, 959 "module.bar", 960 "module.foo", 961 } 962 if code := c.Run(args); code != 0 { 963 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 964 } 965 testStateOutput(t, stateOutPath2, testStateMvModuleNewModule_stateOut) 966 } 967 968 func TestStateMv_withinBackend(t *testing.T) { 969 td := tempDir(t) 970 copy.CopyDir(testFixturePath("backend-unchanged"), td) 971 defer os.RemoveAll(td) 972 defer testChdir(t, td)() 973 974 state := states.BuildState(func(s *states.SyncState) { 975 s.SetResourceInstanceCurrent( 976 addrs.Resource{ 977 Mode: addrs.ManagedResourceMode, 978 Type: "test_instance", 979 Name: "foo", 980 }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance), 981 &states.ResourceInstanceObjectSrc{ 982 AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`), 983 Status: states.ObjectReady, 984 }, 985 addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), 986 ) 987 s.SetResourceInstanceCurrent( 988 addrs.Resource{ 989 Mode: addrs.ManagedResourceMode, 990 Type: "test_instance", 991 Name: "baz", 992 }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance), 993 &states.ResourceInstanceObjectSrc{ 994 AttrsJSON: []byte(`{"id":"foo","foo":"value","bar":"value"}`), 995 Status: states.ObjectReady, 996 Dependencies: []addrs.AbsResource{mustResourceAddr("test_instance.foo")}, 997 }, 998 addrs.ProviderConfig{Type: addrs.NewLegacyProvider("test")}.Absolute(addrs.RootModuleInstance), 999 ) 1000 }) 1001 1002 // the local backend state file is "foo" 1003 statePath := "local-state.tfstate" 1004 backupPath := "local-state.backup" 1005 1006 f, err := os.Create(statePath) 1007 if err != nil { 1008 t.Fatal(err) 1009 } 1010 defer f.Close() 1011 1012 if err := writeStateForTesting(state, f); err != nil { 1013 t.Fatal(err) 1014 } 1015 1016 p := testProvider() 1017 ui := new(cli.MockUi) 1018 c := &StateMvCommand{ 1019 StateMeta{ 1020 Meta: Meta{ 1021 testingOverrides: metaOverridesForProvider(p), 1022 Ui: ui, 1023 }, 1024 }, 1025 } 1026 1027 args := []string{ 1028 "-backup", backupPath, 1029 "test_instance.foo", 1030 "test_instance.bar", 1031 } 1032 if code := c.Run(args); code != 0 { 1033 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 1034 } 1035 1036 testStateOutput(t, statePath, testStateMvOutput) 1037 testStateOutput(t, backupPath, testStateMvOutputOriginal) 1038 } 1039 1040 func TestStateMv_fromBackendToLocal(t *testing.T) { 1041 td := tempDir(t) 1042 copy.CopyDir(testFixturePath("backend-unchanged"), td) 1043 defer os.RemoveAll(td) 1044 defer testChdir(t, td)() 1045 1046 state := &terraform.State{ 1047 Modules: []*terraform.ModuleState{ 1048 &terraform.ModuleState{ 1049 Path: []string{"root"}, 1050 Resources: map[string]*terraform.ResourceState{ 1051 "test_instance.foo": &terraform.ResourceState{ 1052 Type: "test_instance", 1053 Primary: &terraform.InstanceState{ 1054 ID: "bar", 1055 Attributes: map[string]string{ 1056 "foo": "value", 1057 "bar": "value", 1058 }, 1059 }, 1060 }, 1061 1062 "test_instance.baz": &terraform.ResourceState{ 1063 Type: "test_instance", 1064 Primary: &terraform.InstanceState{ 1065 ID: "foo", 1066 Attributes: map[string]string{ 1067 "foo": "value", 1068 "bar": "value", 1069 }, 1070 }, 1071 }, 1072 }, 1073 }, 1074 }, 1075 } 1076 1077 // the local backend state file is "foo" 1078 statePath := "local-state.tfstate" 1079 1080 // real "local" state file 1081 statePathOut := "real-local.tfstate" 1082 1083 f, err := os.Create(statePath) 1084 if err != nil { 1085 t.Fatal(err) 1086 } 1087 defer f.Close() 1088 1089 if err := terraform.WriteState(state, f); err != nil { 1090 t.Fatal(err) 1091 } 1092 1093 p := testProvider() 1094 ui := new(cli.MockUi) 1095 c := &StateMvCommand{ 1096 StateMeta{ 1097 Meta: Meta{ 1098 testingOverrides: metaOverridesForProvider(p), 1099 Ui: ui, 1100 }, 1101 }, 1102 } 1103 1104 args := []string{ 1105 "-state-out", statePathOut, 1106 "test_instance.foo", 1107 "test_instance.bar", 1108 } 1109 if code := c.Run(args); code != 0 { 1110 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 1111 } 1112 1113 testStateOutput(t, statePathOut, testStateMvCount_stateOutSrc) 1114 1115 // the backend state should be left with only baz 1116 testStateOutput(t, statePath, testStateMvOriginal_backend) 1117 } 1118 1119 const testStateMvOutputOriginal = ` 1120 test_instance.baz: 1121 ID = foo 1122 provider = provider.test 1123 bar = value 1124 foo = value 1125 1126 Dependencies: 1127 test_instance.foo 1128 test_instance.foo: 1129 ID = bar 1130 provider = provider.test 1131 bar = value 1132 foo = value 1133 ` 1134 1135 const testStateMvOutput = ` 1136 test_instance.bar: 1137 ID = bar 1138 provider = provider.test 1139 bar = value 1140 foo = value 1141 test_instance.baz: 1142 ID = foo 1143 provider = provider.test 1144 bar = value 1145 foo = value 1146 ` 1147 1148 const testStateMvCount_stateOut = ` 1149 test_instance.bar.0: 1150 ID = foo 1151 provider = provider.test 1152 bar = value 1153 foo = value 1154 test_instance.bar.1: 1155 ID = bar 1156 provider = provider.test 1157 bar = value 1158 foo = value 1159 ` 1160 1161 const testStateMvCount_stateOutSrc = ` 1162 test_instance.bar: 1163 ID = bar 1164 provider = provider.test 1165 bar = value 1166 foo = value 1167 ` 1168 1169 const testStateMvCount_stateOutOriginal = ` 1170 test_instance.bar: 1171 ID = bar 1172 provider = provider.test 1173 bar = value 1174 foo = value 1175 test_instance.foo.0: 1176 ID = foo 1177 provider = provider.test 1178 bar = value 1179 foo = value 1180 test_instance.foo.1: 1181 ID = bar 1182 provider = provider.test 1183 bar = value 1184 foo = value 1185 ` 1186 1187 const testStateMvLargeCount_stateOut = ` 1188 test_instance.bar.0: 1189 ID = foo0 1190 provider = provider.test 1191 bar = value 1192 foo = value 1193 test_instance.bar.1: 1194 ID = foo1 1195 provider = provider.test 1196 bar = value 1197 foo = value 1198 test_instance.bar.2: 1199 ID = foo2 1200 provider = provider.test 1201 bar = value 1202 foo = value 1203 test_instance.bar.3: 1204 ID = foo3 1205 provider = provider.test 1206 bar = value 1207 foo = value 1208 test_instance.bar.4: 1209 ID = foo4 1210 provider = provider.test 1211 bar = value 1212 foo = value 1213 test_instance.bar.5: 1214 ID = foo5 1215 provider = provider.test 1216 bar = value 1217 foo = value 1218 test_instance.bar.6: 1219 ID = foo6 1220 provider = provider.test 1221 bar = value 1222 foo = value 1223 test_instance.bar.7: 1224 ID = foo7 1225 provider = provider.test 1226 bar = value 1227 foo = value 1228 test_instance.bar.8: 1229 ID = foo8 1230 provider = provider.test 1231 bar = value 1232 foo = value 1233 test_instance.bar.9: 1234 ID = foo9 1235 provider = provider.test 1236 bar = value 1237 foo = value 1238 test_instance.bar.10: 1239 ID = foo10 1240 provider = provider.test 1241 bar = value 1242 foo = value 1243 ` 1244 1245 const testStateMvLargeCount_stateOutSrc = ` 1246 test_instance.bar: 1247 ID = bar 1248 provider = provider.test 1249 bar = value 1250 foo = value 1251 ` 1252 1253 const testStateMvLargeCount_stateOutOriginal = ` 1254 test_instance.bar: 1255 ID = bar 1256 provider = provider.test 1257 bar = value 1258 foo = value 1259 test_instance.foo.0: 1260 ID = foo0 1261 provider = provider.test 1262 bar = value 1263 foo = value 1264 test_instance.foo.1: 1265 ID = foo1 1266 provider = provider.test 1267 bar = value 1268 foo = value 1269 test_instance.foo.2: 1270 ID = foo2 1271 provider = provider.test 1272 bar = value 1273 foo = value 1274 test_instance.foo.3: 1275 ID = foo3 1276 provider = provider.test 1277 bar = value 1278 foo = value 1279 test_instance.foo.4: 1280 ID = foo4 1281 provider = provider.test 1282 bar = value 1283 foo = value 1284 test_instance.foo.5: 1285 ID = foo5 1286 provider = provider.test 1287 bar = value 1288 foo = value 1289 test_instance.foo.6: 1290 ID = foo6 1291 provider = provider.test 1292 bar = value 1293 foo = value 1294 test_instance.foo.7: 1295 ID = foo7 1296 provider = provider.test 1297 bar = value 1298 foo = value 1299 test_instance.foo.8: 1300 ID = foo8 1301 provider = provider.test 1302 bar = value 1303 foo = value 1304 test_instance.foo.9: 1305 ID = foo9 1306 provider = provider.test 1307 bar = value 1308 foo = value 1309 test_instance.foo.10: 1310 ID = foo10 1311 provider = provider.test 1312 bar = value 1313 foo = value 1314 ` 1315 1316 const testStateMvNestedModule_stateOut = ` 1317 <no state> 1318 module.bar.child1: 1319 test_instance.foo: 1320 ID = bar 1321 provider = provider.test 1322 bar = value 1323 foo = value 1324 module.bar.child2: 1325 test_instance.foo: 1326 ID = bar 1327 provider = provider.test 1328 bar = value 1329 foo = value 1330 ` 1331 1332 const testStateMvNewModule_stateOut = ` 1333 <no state> 1334 module.bar: 1335 test_instance.bar: 1336 ID = bar 1337 provider = provider.test 1338 bar = value 1339 foo = value 1340 ` 1341 1342 const testStateMvModuleNewModule_stateOut = ` 1343 <no state> 1344 module.foo: 1345 test_instance.bar: 1346 ID = bar 1347 provider = provider.test 1348 bar = value 1349 foo = value 1350 ` 1351 1352 const testStateMvNewModule_stateOutOriginal = ` 1353 test_instance.bar: 1354 ID = bar 1355 provider = provider.test 1356 bar = value 1357 foo = value 1358 ` 1359 1360 const testStateMvNestedModule_stateOutSrc = ` 1361 <no state> 1362 ` 1363 1364 const testStateMvNestedModule_stateOutOriginal = ` 1365 <no state> 1366 module.foo.child1: 1367 test_instance.foo: 1368 ID = bar 1369 provider = provider.test 1370 bar = value 1371 foo = value 1372 module.foo.child2: 1373 test_instance.foo: 1374 ID = bar 1375 provider = provider.test 1376 bar = value 1377 foo = value 1378 ` 1379 1380 const testStateMvOutput_stateOut = ` 1381 test_instance.bar: 1382 ID = bar 1383 provider = provider.test 1384 bar = value 1385 foo = value 1386 ` 1387 1388 const testStateMvOutput_stateOutSrc = ` 1389 <no state> 1390 ` 1391 1392 const testStateMvOutput_stateOutOriginal = ` 1393 test_instance.foo: 1394 ID = bar 1395 provider = provider.test 1396 bar = value 1397 foo = value 1398 ` 1399 1400 const testStateMvExisting_stateSrc = ` 1401 <no state> 1402 ` 1403 1404 const testStateMvExisting_stateDst = ` 1405 test_instance.bar: 1406 ID = bar 1407 provider = provider.test 1408 bar = value 1409 foo = value 1410 test_instance.qux: 1411 ID = bar 1412 provider = provider.test 1413 ` 1414 1415 const testStateMvExisting_stateSrcOriginal = ` 1416 test_instance.foo: 1417 ID = bar 1418 provider = provider.test 1419 bar = value 1420 foo = value 1421 ` 1422 1423 const testStateMvExisting_stateDstOriginal = ` 1424 test_instance.qux: 1425 ID = bar 1426 provider = provider.test 1427 ` 1428 1429 const testStateMvOriginal_backend = ` 1430 test_instance.baz: 1431 ID = foo 1432 provider = provider.test 1433 bar = value 1434 foo = value 1435 `