kubeform.dev/terraform-backend-sdk@v0.0.0-20220310143633-45f07fe731c5/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/google/go-cmp/cmp" 11 "github.com/mitchellh/cli" 12 13 "kubeform.dev/terraform-backend-sdk/addrs" 14 "kubeform.dev/terraform-backend-sdk/states" 15 ) 16 17 func TestStateMv(t *testing.T) { 18 state := states.BuildState(func(s *states.SyncState) { 19 s.SetResourceInstanceCurrent( 20 addrs.Resource{ 21 Mode: addrs.ManagedResourceMode, 22 Type: "test_instance", 23 Name: "foo", 24 }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance), 25 &states.ResourceInstanceObjectSrc{ 26 AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`), 27 Status: states.ObjectReady, 28 }, 29 addrs.AbsProviderConfig{ 30 Provider: addrs.NewDefaultProvider("test"), 31 Module: addrs.RootModule, 32 }, 33 ) 34 s.SetResourceInstanceCurrent( 35 addrs.Resource{ 36 Mode: addrs.ManagedResourceMode, 37 Type: "test_instance", 38 Name: "baz", 39 }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance), 40 &states.ResourceInstanceObjectSrc{ 41 AttrsJSON: []byte(`{"id":"foo","foo":"value","bar":"value"}`), 42 Status: states.ObjectReady, 43 Dependencies: []addrs.ConfigResource{mustResourceAddr("test_instance.foo")}, 44 }, 45 addrs.AbsProviderConfig{ 46 Provider: addrs.NewDefaultProvider("test"), 47 Module: addrs.RootModule, 48 }, 49 ) 50 }) 51 statePath := testStateFile(t, state) 52 53 p := testProvider() 54 ui := new(cli.MockUi) 55 view, _ := testView(t) 56 c := &StateMvCommand{ 57 StateMeta{ 58 Meta: Meta{ 59 testingOverrides: metaOverridesForProvider(p), 60 Ui: ui, 61 View: view, 62 }, 63 }, 64 } 65 66 args := []string{ 67 "-state", statePath, 68 "test_instance.foo", 69 "test_instance.bar", 70 } 71 if code := c.Run(args); code != 0 { 72 t.Fatalf("return code: %d\n\n%s", code, ui.ErrorWriter.String()) 73 } 74 75 // Test it is correct 76 testStateOutput(t, statePath, testStateMvOutput) 77 78 // Test we have backups 79 backups := testStateBackups(t, filepath.Dir(statePath)) 80 if len(backups) != 1 { 81 t.Fatalf("bad: %#v", backups) 82 } 83 testStateOutput(t, backups[0], testStateMvOutputOriginal) 84 85 // Change the single instance to a counted instance 86 args = []string{ 87 "-state", statePath, 88 "test_instance.bar", 89 "test_instance.bar[0]", 90 } 91 if code := c.Run(args); code != 0 { 92 t.Fatalf("return code: %d\n\n%s", code, ui.ErrorWriter.String()) 93 } 94 95 // extract the resource and verify the mode 96 s := testStateRead(t, statePath) 97 addr, diags := addrs.ParseAbsResourceStr("test_instance.bar") 98 if diags.HasErrors() { 99 t.Fatal(diags.Err()) 100 } 101 for key := range s.Resource(addr).Instances { 102 if _, ok := key.(addrs.IntKey); !ok { 103 t.Fatalf("expected each mode List, got key %q", key) 104 } 105 } 106 107 // change from list to map 108 args = []string{ 109 "-state", statePath, 110 "test_instance.bar[0]", 111 "test_instance.bar[\"baz\"]", 112 } 113 if code := c.Run(args); code != 0 { 114 t.Fatalf("return code: %d\n\n%s", code, ui.ErrorWriter.String()) 115 } 116 117 // extract the resource and verify the mode 118 s = testStateRead(t, statePath) 119 addr, diags = addrs.ParseAbsResourceStr("test_instance.bar") 120 if diags.HasErrors() { 121 t.Fatal(diags.Err()) 122 } 123 for key := range s.Resource(addr).Instances { 124 if _, ok := key.(addrs.StringKey); !ok { 125 t.Fatalf("expected each mode map, found key %q", key) 126 } 127 } 128 129 // change from from map back to single 130 args = []string{ 131 "-state", statePath, 132 "test_instance.bar[\"baz\"]", 133 "test_instance.bar", 134 } 135 if code := c.Run(args); code != 0 { 136 t.Fatalf("return code: %d\n\n%s", code, ui.ErrorWriter.String()) 137 } 138 139 // extract the resource and verify the mode 140 s = testStateRead(t, statePath) 141 addr, diags = addrs.ParseAbsResourceStr("test_instance.bar") 142 if diags.HasErrors() { 143 t.Fatal(diags.Err()) 144 } 145 for key := range s.Resource(addr).Instances { 146 if key != addrs.NoKey { 147 t.Fatalf("expected no each mode, found key %q", key) 148 } 149 } 150 151 } 152 153 func TestStateMv_resourceToInstance(t *testing.T) { 154 // A single resource (no count defined) 155 state := states.BuildState(func(s *states.SyncState) { 156 s.SetResourceInstanceCurrent( 157 addrs.Resource{ 158 Mode: addrs.ManagedResourceMode, 159 Type: "test_instance", 160 Name: "foo", 161 }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance), 162 &states.ResourceInstanceObjectSrc{ 163 AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`), 164 Status: states.ObjectReady, 165 }, 166 addrs.AbsProviderConfig{ 167 Provider: addrs.NewDefaultProvider("test"), 168 Module: addrs.RootModule, 169 }, 170 ) 171 s.SetResourceInstanceCurrent( 172 addrs.Resource{ 173 Mode: addrs.ManagedResourceMode, 174 Type: "test_instance", 175 Name: "baz", 176 }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance), 177 &states.ResourceInstanceObjectSrc{ 178 AttrsJSON: []byte(`{"id":"foo","foo":"value","bar":"value"}`), 179 Status: states.ObjectReady, 180 Dependencies: []addrs.ConfigResource{mustResourceAddr("test_instance.foo")}, 181 }, 182 addrs.AbsProviderConfig{ 183 Provider: addrs.NewDefaultProvider("test"), 184 Module: addrs.RootModule, 185 }, 186 ) 187 s.SetResourceProvider( 188 addrs.Resource{ 189 Mode: addrs.ManagedResourceMode, 190 Type: "test_instance", 191 Name: "bar", 192 }.Absolute(addrs.RootModuleInstance), 193 addrs.AbsProviderConfig{ 194 Provider: addrs.NewDefaultProvider("test"), 195 Module: addrs.RootModule, 196 }, 197 ) 198 }) 199 statePath := testStateFile(t, state) 200 201 p := testProvider() 202 ui := new(cli.MockUi) 203 view, _ := testView(t) 204 c := &StateMvCommand{ 205 StateMeta{ 206 Meta: Meta{ 207 testingOverrides: metaOverridesForProvider(p), 208 Ui: ui, 209 View: view, 210 }, 211 }, 212 } 213 214 args := []string{ 215 "-state", statePath, 216 "test_instance.foo", 217 "test_instance.bar[0]", 218 } 219 if code := c.Run(args); code != 0 { 220 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 221 } 222 223 // Test it is correct 224 testStateOutput(t, statePath, ` 225 test_instance.bar.0: 226 ID = bar 227 provider = provider["registry.terraform.io/hashicorp/test"] 228 bar = value 229 foo = value 230 test_instance.baz: 231 ID = foo 232 provider = provider["registry.terraform.io/hashicorp/test"] 233 bar = value 234 foo = value 235 `) 236 237 // Test we have backups 238 backups := testStateBackups(t, filepath.Dir(statePath)) 239 if len(backups) != 1 { 240 t.Fatalf("bad: %#v", backups) 241 } 242 testStateOutput(t, backups[0], testStateMvOutputOriginal) 243 } 244 245 func TestStateMv_resourceToInstanceErr(t *testing.T) { 246 state := states.BuildState(func(s *states.SyncState) { 247 s.SetResourceInstanceCurrent( 248 addrs.Resource{ 249 Mode: addrs.ManagedResourceMode, 250 Type: "test_instance", 251 Name: "foo", 252 }.Instance(addrs.IntKey(0)).Absolute(addrs.RootModuleInstance), 253 &states.ResourceInstanceObjectSrc{ 254 AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`), 255 Status: states.ObjectReady, 256 }, 257 addrs.AbsProviderConfig{ 258 Provider: addrs.NewDefaultProvider("test"), 259 Module: addrs.RootModule, 260 }, 261 ) 262 s.SetResourceProvider( 263 addrs.Resource{ 264 Mode: addrs.ManagedResourceMode, 265 Type: "test_instance", 266 Name: "bar", 267 }.Absolute(addrs.RootModuleInstance), 268 addrs.AbsProviderConfig{ 269 Provider: addrs.NewDefaultProvider("test"), 270 Module: addrs.RootModule, 271 }, 272 ) 273 }) 274 statePath := testStateFile(t, state) 275 276 p := testProvider() 277 ui := cli.NewMockUi() 278 view, _ := testView(t) 279 280 c := &StateMvCommand{ 281 StateMeta{ 282 Meta: Meta{ 283 testingOverrides: metaOverridesForProvider(p), 284 Ui: ui, 285 View: view, 286 }, 287 }, 288 } 289 290 args := []string{ 291 "-state", statePath, 292 "test_instance.foo", 293 "test_instance.bar[0]", 294 } 295 296 if code := c.Run(args); code == 0 { 297 t.Fatalf("expected error output, got:\n%s", ui.OutputWriter.String()) 298 } 299 300 expectedErr := ` 301 Error: Invalid target address 302 303 Cannot move test_instance.foo to test_instance.bar[0]: the source is a whole 304 resource (not a resource instance) so the target must also be a whole 305 resource. 306 307 ` 308 errOutput := ui.ErrorWriter.String() 309 if errOutput != expectedErr { 310 t.Errorf("wrong output\n%s", cmp.Diff(errOutput, expectedErr)) 311 } 312 } 313 314 func TestStateMv_resourceToInstanceErrInAutomation(t *testing.T) { 315 state := states.BuildState(func(s *states.SyncState) { 316 s.SetResourceInstanceCurrent( 317 addrs.Resource{ 318 Mode: addrs.ManagedResourceMode, 319 Type: "test_instance", 320 Name: "foo", 321 }.Instance(addrs.IntKey(0)).Absolute(addrs.RootModuleInstance), 322 &states.ResourceInstanceObjectSrc{ 323 AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`), 324 Status: states.ObjectReady, 325 }, 326 addrs.AbsProviderConfig{ 327 Provider: addrs.NewDefaultProvider("test"), 328 Module: addrs.RootModule, 329 }, 330 ) 331 s.SetResourceProvider( 332 addrs.Resource{ 333 Mode: addrs.ManagedResourceMode, 334 Type: "test_instance", 335 Name: "bar", 336 }.Absolute(addrs.RootModuleInstance), 337 addrs.AbsProviderConfig{ 338 Provider: addrs.NewDefaultProvider("test"), 339 Module: addrs.RootModule, 340 }, 341 ) 342 }) 343 statePath := testStateFile(t, state) 344 345 p := testProvider() 346 ui := new(cli.MockUi) 347 view, _ := testView(t) 348 c := &StateMvCommand{ 349 StateMeta{ 350 Meta: Meta{ 351 testingOverrides: metaOverridesForProvider(p), 352 Ui: ui, 353 View: view, 354 RunningInAutomation: true, 355 }, 356 }, 357 } 358 359 args := []string{ 360 "-state", statePath, 361 "test_instance.foo", 362 "test_instance.bar[0]", 363 } 364 365 if code := c.Run(args); code == 0 { 366 t.Fatalf("expected error output, got:\n%s", ui.OutputWriter.String()) 367 } 368 369 expectedErr := ` 370 Error: Invalid target address 371 372 Cannot move test_instance.foo to test_instance.bar[0]: the source is a whole 373 resource (not a resource instance) so the target must also be a whole 374 resource. 375 376 ` 377 errOutput := ui.ErrorWriter.String() 378 if errOutput != expectedErr { 379 t.Errorf("Unexpected diff.\ngot:\n%s\nwant:\n%s\n", errOutput, expectedErr) 380 t.Errorf("%s", cmp.Diff(errOutput, expectedErr)) 381 } 382 } 383 384 func TestStateMv_instanceToResource(t *testing.T) { 385 state := states.BuildState(func(s *states.SyncState) { 386 s.SetResourceInstanceCurrent( 387 addrs.Resource{ 388 Mode: addrs.ManagedResourceMode, 389 Type: "test_instance", 390 Name: "foo", 391 }.Instance(addrs.IntKey(0)).Absolute(addrs.RootModuleInstance), 392 &states.ResourceInstanceObjectSrc{ 393 AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`), 394 Status: states.ObjectReady, 395 }, 396 addrs.AbsProviderConfig{ 397 Provider: addrs.NewDefaultProvider("test"), 398 Module: addrs.RootModule, 399 }, 400 ) 401 s.SetResourceInstanceCurrent( 402 addrs.Resource{ 403 Mode: addrs.ManagedResourceMode, 404 Type: "test_instance", 405 Name: "baz", 406 }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance), 407 &states.ResourceInstanceObjectSrc{ 408 AttrsJSON: []byte(`{"id":"foo","foo":"value","bar":"value"}`), 409 Status: states.ObjectReady, 410 }, 411 addrs.AbsProviderConfig{ 412 Provider: addrs.NewDefaultProvider("test"), 413 Module: addrs.RootModule, 414 }, 415 ) 416 }) 417 statePath := testStateFile(t, state) 418 419 p := testProvider() 420 ui := new(cli.MockUi) 421 view, _ := testView(t) 422 c := &StateMvCommand{ 423 StateMeta{ 424 Meta: Meta{ 425 testingOverrides: metaOverridesForProvider(p), 426 Ui: ui, 427 View: view, 428 }, 429 }, 430 } 431 432 args := []string{ 433 "-state", statePath, 434 "test_instance.foo[0]", 435 "test_instance.bar", 436 } 437 if code := c.Run(args); code != 0 { 438 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 439 } 440 441 // Test it is correct 442 testStateOutput(t, statePath, ` 443 test_instance.bar: 444 ID = bar 445 provider = provider["registry.terraform.io/hashicorp/test"] 446 bar = value 447 foo = value 448 test_instance.baz: 449 ID = foo 450 provider = provider["registry.terraform.io/hashicorp/test"] 451 bar = value 452 foo = value 453 `) 454 455 // Test we have backups 456 backups := testStateBackups(t, filepath.Dir(statePath)) 457 if len(backups) != 1 { 458 t.Fatalf("bad: %#v", backups) 459 } 460 testStateOutput(t, backups[0], ` 461 test_instance.baz: 462 ID = foo 463 provider = provider["registry.terraform.io/hashicorp/test"] 464 bar = value 465 foo = value 466 test_instance.foo.0: 467 ID = bar 468 provider = provider["registry.terraform.io/hashicorp/test"] 469 bar = value 470 foo = value 471 `) 472 } 473 474 func TestStateMv_instanceToNewResource(t *testing.T) { 475 state := states.BuildState(func(s *states.SyncState) { 476 s.SetResourceInstanceCurrent( 477 addrs.Resource{ 478 Mode: addrs.ManagedResourceMode, 479 Type: "test_instance", 480 Name: "foo", 481 }.Instance(addrs.IntKey(0)).Absolute(addrs.RootModuleInstance), 482 &states.ResourceInstanceObjectSrc{ 483 AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`), 484 Status: states.ObjectReady, 485 }, 486 addrs.AbsProviderConfig{ 487 Provider: addrs.NewDefaultProvider("test"), 488 Module: addrs.RootModule, 489 }, 490 ) 491 }) 492 statePath := testStateFile(t, state) 493 494 p := testProvider() 495 ui := new(cli.MockUi) 496 view, _ := testView(t) 497 c := &StateMvCommand{ 498 StateMeta{ 499 Meta: Meta{ 500 testingOverrides: metaOverridesForProvider(p), 501 Ui: ui, 502 View: view, 503 }, 504 }, 505 } 506 507 args := []string{ 508 "-state", statePath, 509 "test_instance.foo[0]", 510 "test_instance.bar[\"new\"]", 511 } 512 if code := c.Run(args); code != 0 { 513 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 514 } 515 516 // Test it is correct 517 testStateOutput(t, statePath, ` 518 test_instance.bar["new"]: 519 ID = bar 520 provider = provider["registry.terraform.io/hashicorp/test"] 521 bar = value 522 foo = value 523 `) 524 525 // now move the instance to a new resource in a new module 526 args = []string{ 527 "-state", statePath, 528 "test_instance.bar[\"new\"]", 529 "module.test.test_instance.baz[\"new\"]", 530 } 531 if code := c.Run(args); code != 0 { 532 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 533 } 534 535 // Test it is correct 536 testStateOutput(t, statePath, ` 537 <no state> 538 module.test: 539 test_instance.baz["new"]: 540 ID = bar 541 provider = provider["registry.terraform.io/hashicorp/test"] 542 bar = value 543 foo = value 544 `) 545 } 546 547 func TestStateMv_differentResourceTypes(t *testing.T) { 548 state := states.BuildState(func(s *states.SyncState) { 549 s.SetResourceInstanceCurrent( 550 addrs.Resource{ 551 Mode: addrs.ManagedResourceMode, 552 Type: "test_instance", 553 Name: "foo", 554 }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance), 555 &states.ResourceInstanceObjectSrc{ 556 AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`), 557 Status: states.ObjectReady, 558 }, 559 addrs.AbsProviderConfig{ 560 Provider: addrs.NewDefaultProvider("test"), 561 Module: addrs.RootModule, 562 }, 563 ) 564 }) 565 statePath := testStateFile(t, state) 566 567 p := testProvider() 568 ui := new(cli.MockUi) 569 view, _ := testView(t) 570 c := &StateMvCommand{ 571 StateMeta{ 572 Meta: Meta{ 573 testingOverrides: metaOverridesForProvider(p), 574 Ui: ui, 575 View: view, 576 }, 577 }, 578 } 579 580 args := []string{ 581 "-state", statePath, 582 "test_instance.foo", 583 "test_network.bar", 584 } 585 if code := c.Run(args); code == 0 { 586 t.Fatalf("expected error output, got:\n%s", ui.OutputWriter.String()) 587 } 588 589 gotErr := ui.ErrorWriter.String() 590 wantErr := ` 591 Error: Invalid state move request 592 593 Cannot move test_instance.foo to test_network.bar: resource types don't 594 match. 595 596 ` 597 if gotErr != wantErr { 598 t.Fatalf("expected initialization error\ngot:\n%s\n\nwant:%s", gotErr, wantErr) 599 } 600 } 601 602 // don't modify backend state is we supply a -state flag 603 func TestStateMv_explicitWithBackend(t *testing.T) { 604 td := tempDir(t) 605 testCopyDir(t, testFixturePath("init-backend"), td) 606 defer os.RemoveAll(td) 607 defer testChdir(t, td)() 608 609 backupPath := filepath.Join(td, "backup") 610 611 state := states.BuildState(func(s *states.SyncState) { 612 s.SetResourceInstanceCurrent( 613 addrs.Resource{ 614 Mode: addrs.ManagedResourceMode, 615 Type: "test_instance", 616 Name: "foo", 617 }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance), 618 &states.ResourceInstanceObjectSrc{ 619 AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`), 620 Status: states.ObjectReady, 621 }, 622 addrs.AbsProviderConfig{ 623 Provider: addrs.NewDefaultProvider("test"), 624 Module: addrs.RootModule, 625 }, 626 ) 627 s.SetResourceInstanceCurrent( 628 addrs.Resource{ 629 Mode: addrs.ManagedResourceMode, 630 Type: "test_instance", 631 Name: "baz", 632 }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance), 633 &states.ResourceInstanceObjectSrc{ 634 AttrsJSON: []byte(`{"id":"foo","foo":"value","bar":"value"}`), 635 Status: states.ObjectReady, 636 }, 637 addrs.AbsProviderConfig{ 638 Provider: addrs.NewDefaultProvider("test"), 639 Module: addrs.RootModule, 640 }, 641 ) 642 }) 643 statePath := testStateFile(t, state) 644 645 // init our backend 646 ui := new(cli.MockUi) 647 view, _ := testView(t) 648 ic := &InitCommand{ 649 Meta: Meta{ 650 testingOverrides: metaOverridesForProvider(testProvider()), 651 Ui: ui, 652 View: view, 653 }, 654 } 655 656 args := []string{} 657 if code := ic.Run(args); code != 0 { 658 t.Fatalf("bad: \n%s", ui.ErrorWriter.String()) 659 } 660 661 // only modify statePath 662 p := testProvider() 663 ui = new(cli.MockUi) 664 c := &StateMvCommand{ 665 StateMeta{ 666 Meta: Meta{ 667 testingOverrides: metaOverridesForProvider(p), 668 Ui: ui, 669 View: view, 670 }, 671 }, 672 } 673 674 args = []string{ 675 "-backup", backupPath, 676 "-state", statePath, 677 "test_instance.foo", 678 "test_instance.bar", 679 } 680 if code := c.Run(args); code != 0 { 681 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 682 } 683 684 // Test it is correct 685 testStateOutput(t, statePath, testStateMvOutput) 686 } 687 688 func TestStateMv_backupExplicit(t *testing.T) { 689 state := states.BuildState(func(s *states.SyncState) { 690 s.SetResourceInstanceCurrent( 691 addrs.Resource{ 692 Mode: addrs.ManagedResourceMode, 693 Type: "test_instance", 694 Name: "foo", 695 }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance), 696 &states.ResourceInstanceObjectSrc{ 697 AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`), 698 Status: states.ObjectReady, 699 }, 700 addrs.AbsProviderConfig{ 701 Provider: addrs.NewDefaultProvider("test"), 702 Module: addrs.RootModule, 703 }, 704 ) 705 s.SetResourceInstanceCurrent( 706 addrs.Resource{ 707 Mode: addrs.ManagedResourceMode, 708 Type: "test_instance", 709 Name: "baz", 710 }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance), 711 &states.ResourceInstanceObjectSrc{ 712 AttrsJSON: []byte(`{"id":"foo","foo":"value","bar":"value"}`), 713 Status: states.ObjectReady, 714 Dependencies: []addrs.ConfigResource{mustResourceAddr("test_instance.foo")}, 715 }, 716 addrs.AbsProviderConfig{ 717 Provider: addrs.NewDefaultProvider("test"), 718 Module: addrs.RootModule, 719 }, 720 ) 721 }) 722 statePath := testStateFile(t, state) 723 backupPath := statePath + ".backup.test" 724 725 p := testProvider() 726 ui := new(cli.MockUi) 727 view, _ := testView(t) 728 c := &StateMvCommand{ 729 StateMeta{ 730 Meta: Meta{ 731 testingOverrides: metaOverridesForProvider(p), 732 Ui: ui, 733 View: view, 734 }, 735 }, 736 } 737 738 args := []string{ 739 "-backup", backupPath, 740 "-state", statePath, 741 "test_instance.foo", 742 "test_instance.bar", 743 } 744 if code := c.Run(args); code != 0 { 745 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 746 } 747 748 // Test it is correct 749 testStateOutput(t, statePath, testStateMvOutput) 750 751 // Test backup 752 testStateOutput(t, backupPath, testStateMvOutputOriginal) 753 } 754 755 func TestStateMv_stateOutNew(t *testing.T) { 756 state := states.BuildState(func(s *states.SyncState) { 757 s.SetResourceInstanceCurrent( 758 addrs.Resource{ 759 Mode: addrs.ManagedResourceMode, 760 Type: "test_instance", 761 Name: "foo", 762 }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance), 763 &states.ResourceInstanceObjectSrc{ 764 AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`), 765 Status: states.ObjectReady, 766 }, 767 addrs.AbsProviderConfig{ 768 Provider: addrs.NewDefaultProvider("test"), 769 Module: addrs.RootModule, 770 }, 771 ) 772 }) 773 statePath := testStateFile(t, state) 774 stateOutPath := statePath + ".out" 775 776 p := testProvider() 777 ui := new(cli.MockUi) 778 view, _ := testView(t) 779 c := &StateMvCommand{ 780 StateMeta{ 781 Meta: Meta{ 782 testingOverrides: metaOverridesForProvider(p), 783 Ui: ui, 784 View: view, 785 }, 786 }, 787 } 788 789 args := []string{ 790 "-state", statePath, 791 "-state-out", stateOutPath, 792 "test_instance.foo", 793 "test_instance.bar", 794 } 795 if code := c.Run(args); code != 0 { 796 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 797 } 798 799 // Test it is correct 800 testStateOutput(t, stateOutPath, testStateMvOutput_stateOut) 801 testStateOutput(t, statePath, testStateMvOutput_stateOutSrc) 802 803 // Test we have backups 804 backups := testStateBackups(t, filepath.Dir(statePath)) 805 if len(backups) != 1 { 806 t.Fatalf("bad: %#v", backups) 807 } 808 testStateOutput(t, backups[0], testStateMvOutput_stateOutOriginal) 809 } 810 811 func TestStateMv_stateOutExisting(t *testing.T) { 812 stateSrc := states.BuildState(func(s *states.SyncState) { 813 s.SetResourceInstanceCurrent( 814 addrs.Resource{ 815 Mode: addrs.ManagedResourceMode, 816 Type: "test_instance", 817 Name: "foo", 818 }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance), 819 &states.ResourceInstanceObjectSrc{ 820 AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`), 821 Status: states.ObjectReady, 822 }, 823 addrs.AbsProviderConfig{ 824 Provider: addrs.NewDefaultProvider("test"), 825 Module: addrs.RootModule, 826 }, 827 ) 828 }) 829 statePath := testStateFile(t, stateSrc) 830 831 stateDst := states.BuildState(func(s *states.SyncState) { 832 s.SetResourceInstanceCurrent( 833 addrs.Resource{ 834 Mode: addrs.ManagedResourceMode, 835 Type: "test_instance", 836 Name: "qux", 837 }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance), 838 &states.ResourceInstanceObjectSrc{ 839 AttrsJSON: []byte(`{"id":"bar"}`), 840 Status: states.ObjectReady, 841 }, 842 addrs.AbsProviderConfig{ 843 Provider: addrs.NewDefaultProvider("test"), 844 Module: addrs.RootModule, 845 }, 846 ) 847 }) 848 stateOutPath := testStateFile(t, stateDst) 849 850 p := testProvider() 851 ui := new(cli.MockUi) 852 view, _ := testView(t) 853 c := &StateMvCommand{ 854 StateMeta{ 855 Meta: Meta{ 856 testingOverrides: metaOverridesForProvider(p), 857 Ui: ui, 858 View: view, 859 }, 860 }, 861 } 862 863 args := []string{ 864 "-state", statePath, 865 "-state-out", stateOutPath, 866 "test_instance.foo", 867 "test_instance.bar", 868 } 869 if code := c.Run(args); code != 0 { 870 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 871 } 872 873 // Test it is correct 874 testStateOutput(t, stateOutPath, testStateMvExisting_stateDst) 875 testStateOutput(t, statePath, testStateMvExisting_stateSrc) 876 877 // Test we have backups 878 backups := testStateBackups(t, filepath.Dir(statePath)) 879 if len(backups) != 1 { 880 t.Fatalf("bad: %#v", backups) 881 } 882 testStateOutput(t, backups[0], testStateMvExisting_stateSrcOriginal) 883 884 backups = testStateBackups(t, filepath.Dir(stateOutPath)) 885 if len(backups) != 1 { 886 t.Fatalf("bad: %#v", backups) 887 } 888 testStateOutput(t, backups[0], testStateMvExisting_stateDstOriginal) 889 } 890 891 func TestStateMv_noState(t *testing.T) { 892 tmp, cwd := testCwd(t) 893 defer testFixCwd(t, tmp, cwd) 894 895 p := testProvider() 896 ui := new(cli.MockUi) 897 view, _ := testView(t) 898 c := &StateMvCommand{ 899 StateMeta{ 900 Meta: Meta{ 901 testingOverrides: metaOverridesForProvider(p), 902 Ui: ui, 903 View: view, 904 }, 905 }, 906 } 907 908 args := []string{"from", "to"} 909 if code := c.Run(args); code != 1 { 910 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 911 } 912 } 913 914 func TestStateMv_stateOutNew_count(t *testing.T) { 915 state := states.BuildState(func(s *states.SyncState) { 916 s.SetResourceInstanceCurrent( 917 addrs.Resource{ 918 Mode: addrs.ManagedResourceMode, 919 Type: "test_instance", 920 Name: "foo", 921 }.Instance(addrs.IntKey(0)).Absolute(addrs.RootModuleInstance), 922 &states.ResourceInstanceObjectSrc{ 923 AttrsJSON: []byte(`{"id":"foo","foo":"value","bar":"value"}`), 924 Status: states.ObjectReady, 925 }, 926 addrs.AbsProviderConfig{ 927 Provider: addrs.NewDefaultProvider("test"), 928 Module: addrs.RootModule, 929 }, 930 ) 931 s.SetResourceInstanceCurrent( 932 addrs.Resource{ 933 Mode: addrs.ManagedResourceMode, 934 Type: "test_instance", 935 Name: "foo", 936 }.Instance(addrs.IntKey(1)).Absolute(addrs.RootModuleInstance), 937 &states.ResourceInstanceObjectSrc{ 938 AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`), 939 Status: states.ObjectReady, 940 }, 941 addrs.AbsProviderConfig{ 942 Provider: addrs.NewDefaultProvider("test"), 943 Module: addrs.RootModule, 944 }, 945 ) 946 s.SetResourceInstanceCurrent( 947 addrs.Resource{ 948 Mode: addrs.ManagedResourceMode, 949 Type: "test_instance", 950 Name: "bar", 951 }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance), 952 &states.ResourceInstanceObjectSrc{ 953 AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`), 954 Status: states.ObjectReady, 955 }, 956 addrs.AbsProviderConfig{ 957 Provider: addrs.NewDefaultProvider("test"), 958 Module: addrs.RootModule, 959 }, 960 ) 961 }) 962 statePath := testStateFile(t, state) 963 stateOutPath := statePath + ".out" 964 965 p := testProvider() 966 ui := new(cli.MockUi) 967 view, _ := testView(t) 968 c := &StateMvCommand{ 969 StateMeta{ 970 Meta: Meta{ 971 testingOverrides: metaOverridesForProvider(p), 972 Ui: ui, 973 View: view, 974 }, 975 }, 976 } 977 978 args := []string{ 979 "-state", statePath, 980 "-state-out", stateOutPath, 981 "test_instance.foo", 982 "test_instance.bar", 983 } 984 if code := c.Run(args); code != 0 { 985 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 986 } 987 988 // Test it is correct 989 testStateOutput(t, stateOutPath, testStateMvCount_stateOut) 990 testStateOutput(t, statePath, testStateMvCount_stateOutSrc) 991 992 // Test we have backups 993 backups := testStateBackups(t, filepath.Dir(statePath)) 994 if len(backups) != 1 { 995 t.Fatalf("bad: %#v", backups) 996 } 997 testStateOutput(t, backups[0], testStateMvCount_stateOutOriginal) 998 } 999 1000 // Modules with more than 10 resources were sorted lexically, causing the 1001 // indexes in the new location to change. 1002 func TestStateMv_stateOutNew_largeCount(t *testing.T) { 1003 state := states.BuildState(func(s *states.SyncState) { 1004 // test_instance.foo has 11 instances, all the same except for their ids 1005 for i := 0; i < 11; i++ { 1006 s.SetResourceInstanceCurrent( 1007 addrs.Resource{ 1008 Mode: addrs.ManagedResourceMode, 1009 Type: "test_instance", 1010 Name: "foo", 1011 }.Instance(addrs.IntKey(i)).Absolute(addrs.RootModuleInstance), 1012 &states.ResourceInstanceObjectSrc{ 1013 AttrsJSON: []byte(fmt.Sprintf(`{"id":"foo%d","foo":"value","bar":"value"}`, i)), 1014 Status: states.ObjectReady, 1015 }, 1016 addrs.AbsProviderConfig{ 1017 Provider: addrs.NewDefaultProvider("test"), 1018 Module: addrs.RootModule, 1019 }, 1020 ) 1021 } 1022 s.SetResourceInstanceCurrent( 1023 addrs.Resource{ 1024 Mode: addrs.ManagedResourceMode, 1025 Type: "test_instance", 1026 Name: "bar", 1027 }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance), 1028 &states.ResourceInstanceObjectSrc{ 1029 AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`), 1030 Status: states.ObjectReady, 1031 }, 1032 addrs.AbsProviderConfig{ 1033 Provider: addrs.NewDefaultProvider("test"), 1034 Module: addrs.RootModule, 1035 }, 1036 ) 1037 }) 1038 statePath := testStateFile(t, state) 1039 stateOutPath := statePath + ".out" 1040 1041 p := testProvider() 1042 ui := new(cli.MockUi) 1043 view, _ := testView(t) 1044 c := &StateMvCommand{ 1045 StateMeta{ 1046 Meta: Meta{ 1047 testingOverrides: metaOverridesForProvider(p), 1048 Ui: ui, 1049 View: view, 1050 }, 1051 }, 1052 } 1053 1054 args := []string{ 1055 "-state", statePath, 1056 "-state-out", stateOutPath, 1057 "test_instance.foo", 1058 "test_instance.bar", 1059 } 1060 if code := c.Run(args); code != 0 { 1061 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 1062 } 1063 1064 // Test it is correct 1065 testStateOutput(t, stateOutPath, testStateMvLargeCount_stateOut) 1066 testStateOutput(t, statePath, testStateMvLargeCount_stateOutSrc) 1067 1068 // Test we have backups 1069 backups := testStateBackups(t, filepath.Dir(statePath)) 1070 if len(backups) != 1 { 1071 t.Fatalf("bad: %#v", backups) 1072 } 1073 testStateOutput(t, backups[0], testStateMvLargeCount_stateOutOriginal) 1074 } 1075 1076 func TestStateMv_stateOutNew_nestedModule(t *testing.T) { 1077 state := states.BuildState(func(s *states.SyncState) { 1078 s.SetResourceInstanceCurrent( 1079 addrs.Resource{ 1080 Mode: addrs.ManagedResourceMode, 1081 Type: "test_instance", 1082 Name: "foo", 1083 }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance.Child("foo", addrs.NoKey).Child("child1", addrs.NoKey)), 1084 &states.ResourceInstanceObjectSrc{ 1085 AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`), 1086 Status: states.ObjectReady, 1087 }, 1088 addrs.AbsProviderConfig{ 1089 Provider: addrs.NewDefaultProvider("test"), 1090 Module: addrs.RootModule, 1091 }, 1092 ) 1093 s.SetResourceInstanceCurrent( 1094 addrs.Resource{ 1095 Mode: addrs.ManagedResourceMode, 1096 Type: "test_instance", 1097 Name: "foo", 1098 }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance.Child("foo", addrs.NoKey).Child("child2", addrs.NoKey)), 1099 &states.ResourceInstanceObjectSrc{ 1100 AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`), 1101 Status: states.ObjectReady, 1102 }, 1103 addrs.AbsProviderConfig{ 1104 Provider: addrs.NewDefaultProvider("test"), 1105 Module: addrs.RootModule, 1106 }, 1107 ) 1108 }) 1109 1110 statePath := testStateFile(t, state) 1111 stateOutPath := statePath + ".out" 1112 1113 p := testProvider() 1114 ui := new(cli.MockUi) 1115 view, _ := testView(t) 1116 c := &StateMvCommand{ 1117 StateMeta{ 1118 Meta: Meta{ 1119 testingOverrides: metaOverridesForProvider(p), 1120 Ui: ui, 1121 View: view, 1122 }, 1123 }, 1124 } 1125 1126 args := []string{ 1127 "-state", statePath, 1128 "-state-out", stateOutPath, 1129 "module.foo", 1130 "module.bar", 1131 } 1132 if code := c.Run(args); code != 0 { 1133 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 1134 } 1135 1136 // Test it is correct 1137 testStateOutput(t, stateOutPath, testStateMvNestedModule_stateOut) 1138 testStateOutput(t, statePath, testStateMvNestedModule_stateOutSrc) 1139 1140 // Test we have backups 1141 backups := testStateBackups(t, filepath.Dir(statePath)) 1142 if len(backups) != 1 { 1143 t.Fatalf("bad: %#v", backups) 1144 } 1145 testStateOutput(t, backups[0], testStateMvNestedModule_stateOutOriginal) 1146 } 1147 1148 func TestStateMv_toNewModule(t *testing.T) { 1149 state := states.BuildState(func(s *states.SyncState) { 1150 s.SetResourceInstanceCurrent( 1151 addrs.Resource{ 1152 Mode: addrs.ManagedResourceMode, 1153 Type: "test_instance", 1154 Name: "bar", 1155 }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance), 1156 &states.ResourceInstanceObjectSrc{ 1157 AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`), 1158 Status: states.ObjectReady, 1159 }, 1160 addrs.AbsProviderConfig{ 1161 Provider: addrs.NewDefaultProvider("test"), 1162 Module: addrs.RootModule, 1163 }, 1164 ) 1165 }) 1166 1167 statePath := testStateFile(t, state) 1168 stateOutPath1 := statePath + ".out1" 1169 stateOutPath2 := statePath + ".out2" 1170 1171 p := testProvider() 1172 ui := new(cli.MockUi) 1173 view, _ := testView(t) 1174 c := &StateMvCommand{ 1175 StateMeta{ 1176 Meta: Meta{ 1177 testingOverrides: metaOverridesForProvider(p), 1178 Ui: ui, 1179 View: view, 1180 }, 1181 }, 1182 } 1183 1184 args := []string{ 1185 "-state", statePath, 1186 "-state-out", stateOutPath1, 1187 "test_instance.bar", 1188 "module.bar.test_instance.bar", 1189 } 1190 if code := c.Run(args); code != 0 { 1191 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 1192 } 1193 1194 // Test it is correct 1195 testStateOutput(t, stateOutPath1, testStateMvNewModule_stateOut) 1196 testStateOutput(t, statePath, testStateMvNestedModule_stateOutSrc) 1197 1198 // Test we have backups 1199 backups := testStateBackups(t, filepath.Dir(statePath)) 1200 if len(backups) != 1 { 1201 t.Fatalf("bad: %#v", backups) 1202 } 1203 testStateOutput(t, backups[0], testStateMvNewModule_stateOutOriginal) 1204 1205 // now verify we can move the module itself 1206 args = []string{ 1207 "-state", stateOutPath1, 1208 "-state-out", stateOutPath2, 1209 "module.bar", 1210 "module.foo", 1211 } 1212 if code := c.Run(args); code != 0 { 1213 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 1214 } 1215 testStateOutput(t, stateOutPath2, testStateMvModuleNewModule_stateOut) 1216 } 1217 1218 func TestStateMv_withinBackend(t *testing.T) { 1219 td := tempDir(t) 1220 testCopyDir(t, testFixturePath("backend-unchanged"), td) 1221 defer os.RemoveAll(td) 1222 defer testChdir(t, td)() 1223 1224 state := states.BuildState(func(s *states.SyncState) { 1225 s.SetResourceInstanceCurrent( 1226 addrs.Resource{ 1227 Mode: addrs.ManagedResourceMode, 1228 Type: "test_instance", 1229 Name: "foo", 1230 }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance), 1231 &states.ResourceInstanceObjectSrc{ 1232 AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`), 1233 Status: states.ObjectReady, 1234 }, 1235 addrs.AbsProviderConfig{ 1236 Provider: addrs.NewDefaultProvider("test"), 1237 Module: addrs.RootModule, 1238 }, 1239 ) 1240 s.SetResourceInstanceCurrent( 1241 addrs.Resource{ 1242 Mode: addrs.ManagedResourceMode, 1243 Type: "test_instance", 1244 Name: "baz", 1245 }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance), 1246 &states.ResourceInstanceObjectSrc{ 1247 AttrsJSON: []byte(`{"id":"foo","foo":"value","bar":"value"}`), 1248 Status: states.ObjectReady, 1249 Dependencies: []addrs.ConfigResource{mustResourceAddr("test_instance.foo")}, 1250 }, 1251 addrs.AbsProviderConfig{ 1252 Provider: addrs.NewDefaultProvider("test"), 1253 Module: addrs.RootModule, 1254 }, 1255 ) 1256 }) 1257 1258 // the local backend state file is "foo" 1259 statePath := "local-state.tfstate" 1260 backupPath := "local-state.backup" 1261 1262 f, err := os.Create(statePath) 1263 if err != nil { 1264 t.Fatal(err) 1265 } 1266 defer f.Close() 1267 1268 if err := writeStateForTesting(state, f); err != nil { 1269 t.Fatal(err) 1270 } 1271 1272 p := testProvider() 1273 ui := new(cli.MockUi) 1274 view, _ := testView(t) 1275 c := &StateMvCommand{ 1276 StateMeta{ 1277 Meta: Meta{ 1278 testingOverrides: metaOverridesForProvider(p), 1279 Ui: ui, 1280 View: view, 1281 }, 1282 }, 1283 } 1284 1285 args := []string{ 1286 "-backup", backupPath, 1287 "test_instance.foo", 1288 "test_instance.bar", 1289 } 1290 if code := c.Run(args); code != 0 { 1291 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 1292 } 1293 1294 testStateOutput(t, statePath, testStateMvOutput) 1295 testStateOutput(t, backupPath, testStateMvOutputOriginal) 1296 } 1297 1298 func TestStateMv_fromBackendToLocal(t *testing.T) { 1299 td := tempDir(t) 1300 testCopyDir(t, testFixturePath("backend-unchanged"), td) 1301 defer os.RemoveAll(td) 1302 defer testChdir(t, td)() 1303 1304 state := states.NewState() 1305 state.Module(addrs.RootModuleInstance).SetResourceInstanceCurrent( 1306 mustResourceAddr("test_instance.foo").Resource.Instance(addrs.NoKey), 1307 &states.ResourceInstanceObjectSrc{ 1308 AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`), 1309 Status: states.ObjectReady, 1310 }, 1311 addrs.AbsProviderConfig{ 1312 Provider: addrs.NewDefaultProvider("test"), 1313 Module: addrs.RootModule, 1314 }, 1315 ) 1316 state.Module(addrs.RootModuleInstance).SetResourceInstanceCurrent( 1317 mustResourceAddr("test_instance.baz").Resource.Instance(addrs.NoKey), 1318 &states.ResourceInstanceObjectSrc{ 1319 AttrsJSON: []byte(`{"id":"foo","foo":"value","bar":"value"}`), 1320 Status: states.ObjectReady, 1321 }, 1322 addrs.AbsProviderConfig{ 1323 Provider: addrs.NewDefaultProvider("test"), 1324 Module: addrs.RootModule, 1325 }, 1326 ) 1327 1328 // the local backend state file is "foo" 1329 statePath := "local-state.tfstate" 1330 1331 // real "local" state file 1332 statePathOut := "real-local.tfstate" 1333 1334 f, err := os.Create(statePath) 1335 if err != nil { 1336 t.Fatal(err) 1337 } 1338 defer f.Close() 1339 1340 if err := writeStateForTesting(state, f); err != nil { 1341 t.Fatal(err) 1342 } 1343 1344 p := testProvider() 1345 ui := new(cli.MockUi) 1346 view, _ := testView(t) 1347 c := &StateMvCommand{ 1348 StateMeta{ 1349 Meta: Meta{ 1350 testingOverrides: metaOverridesForProvider(p), 1351 Ui: ui, 1352 View: view, 1353 }, 1354 }, 1355 } 1356 1357 args := []string{ 1358 "-state-out", statePathOut, 1359 "test_instance.foo", 1360 "test_instance.bar", 1361 } 1362 if code := c.Run(args); code != 0 { 1363 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 1364 } 1365 1366 testStateOutput(t, statePathOut, testStateMvCount_stateOutSrc) 1367 1368 // the backend state should be left with only baz 1369 testStateOutput(t, statePath, testStateMvOriginal_backend) 1370 } 1371 1372 // This test covers moving the only resource in a module to a new address in 1373 // that module, which triggers the maybePruneModule functionality. This caused 1374 // a panic report: https://github.com/hashicorp/terraform/issues/25520 1375 func TestStateMv_onlyResourceInModule(t *testing.T) { 1376 state := states.BuildState(func(s *states.SyncState) { 1377 s.SetResourceInstanceCurrent( 1378 addrs.Resource{ 1379 Mode: addrs.ManagedResourceMode, 1380 Type: "test_instance", 1381 Name: "foo", 1382 }.Instance(addrs.IntKey(0)).Absolute(addrs.RootModuleInstance.Child("foo", addrs.NoKey)), 1383 &states.ResourceInstanceObjectSrc{ 1384 AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`), 1385 Status: states.ObjectReady, 1386 }, 1387 addrs.AbsProviderConfig{ 1388 Provider: addrs.NewDefaultProvider("test"), 1389 Module: addrs.RootModule, 1390 }, 1391 ) 1392 }) 1393 1394 statePath := testStateFile(t, state) 1395 testStateOutput(t, statePath, testStateMvOnlyResourceInModule_original) 1396 1397 p := testProvider() 1398 ui := new(cli.MockUi) 1399 view, _ := testView(t) 1400 c := &StateMvCommand{ 1401 StateMeta{ 1402 Meta: Meta{ 1403 testingOverrides: metaOverridesForProvider(p), 1404 Ui: ui, 1405 View: view, 1406 }, 1407 }, 1408 } 1409 1410 args := []string{ 1411 "-state", statePath, 1412 "module.foo.test_instance.foo", 1413 "module.foo.test_instance.bar", 1414 } 1415 if code := c.Run(args); code != 0 { 1416 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 1417 } 1418 1419 // Test it is correct 1420 testStateOutput(t, statePath, testStateMvOnlyResourceInModule_output) 1421 1422 // Test we have backups 1423 backups := testStateBackups(t, filepath.Dir(statePath)) 1424 if len(backups) != 1 { 1425 t.Fatalf("bad: %#v", backups) 1426 } 1427 testStateOutput(t, backups[0], testStateMvOnlyResourceInModule_original) 1428 } 1429 1430 func TestStateMvHelp(t *testing.T) { 1431 c := &StateMvCommand{} 1432 if strings.ContainsRune(c.Help(), '\t') { 1433 t.Fatal("help text contains tab character, which will result in poor formatting") 1434 } 1435 } 1436 1437 const testStateMvOutputOriginal = ` 1438 test_instance.baz: 1439 ID = foo 1440 provider = provider["registry.terraform.io/hashicorp/test"] 1441 bar = value 1442 foo = value 1443 1444 Dependencies: 1445 test_instance.foo 1446 test_instance.foo: 1447 ID = bar 1448 provider = provider["registry.terraform.io/hashicorp/test"] 1449 bar = value 1450 foo = value 1451 ` 1452 1453 const testStateMvOutput = ` 1454 test_instance.bar: 1455 ID = bar 1456 provider = provider["registry.terraform.io/hashicorp/test"] 1457 bar = value 1458 foo = value 1459 test_instance.baz: 1460 ID = foo 1461 provider = provider["registry.terraform.io/hashicorp/test"] 1462 bar = value 1463 foo = value 1464 ` 1465 1466 const testStateMvCount_stateOut = ` 1467 test_instance.bar.0: 1468 ID = foo 1469 provider = provider["registry.terraform.io/hashicorp/test"] 1470 bar = value 1471 foo = value 1472 test_instance.bar.1: 1473 ID = bar 1474 provider = provider["registry.terraform.io/hashicorp/test"] 1475 bar = value 1476 foo = value 1477 ` 1478 1479 const testStateMvCount_stateOutSrc = ` 1480 test_instance.bar: 1481 ID = bar 1482 provider = provider["registry.terraform.io/hashicorp/test"] 1483 bar = value 1484 foo = value 1485 ` 1486 1487 const testStateMvCount_stateOutOriginal = ` 1488 test_instance.bar: 1489 ID = bar 1490 provider = provider["registry.terraform.io/hashicorp/test"] 1491 bar = value 1492 foo = value 1493 test_instance.foo.0: 1494 ID = foo 1495 provider = provider["registry.terraform.io/hashicorp/test"] 1496 bar = value 1497 foo = value 1498 test_instance.foo.1: 1499 ID = bar 1500 provider = provider["registry.terraform.io/hashicorp/test"] 1501 bar = value 1502 foo = value 1503 ` 1504 1505 const testStateMvLargeCount_stateOut = ` 1506 test_instance.bar.0: 1507 ID = foo0 1508 provider = provider["registry.terraform.io/hashicorp/test"] 1509 bar = value 1510 foo = value 1511 test_instance.bar.1: 1512 ID = foo1 1513 provider = provider["registry.terraform.io/hashicorp/test"] 1514 bar = value 1515 foo = value 1516 test_instance.bar.2: 1517 ID = foo2 1518 provider = provider["registry.terraform.io/hashicorp/test"] 1519 bar = value 1520 foo = value 1521 test_instance.bar.3: 1522 ID = foo3 1523 provider = provider["registry.terraform.io/hashicorp/test"] 1524 bar = value 1525 foo = value 1526 test_instance.bar.4: 1527 ID = foo4 1528 provider = provider["registry.terraform.io/hashicorp/test"] 1529 bar = value 1530 foo = value 1531 test_instance.bar.5: 1532 ID = foo5 1533 provider = provider["registry.terraform.io/hashicorp/test"] 1534 bar = value 1535 foo = value 1536 test_instance.bar.6: 1537 ID = foo6 1538 provider = provider["registry.terraform.io/hashicorp/test"] 1539 bar = value 1540 foo = value 1541 test_instance.bar.7: 1542 ID = foo7 1543 provider = provider["registry.terraform.io/hashicorp/test"] 1544 bar = value 1545 foo = value 1546 test_instance.bar.8: 1547 ID = foo8 1548 provider = provider["registry.terraform.io/hashicorp/test"] 1549 bar = value 1550 foo = value 1551 test_instance.bar.9: 1552 ID = foo9 1553 provider = provider["registry.terraform.io/hashicorp/test"] 1554 bar = value 1555 foo = value 1556 test_instance.bar.10: 1557 ID = foo10 1558 provider = provider["registry.terraform.io/hashicorp/test"] 1559 bar = value 1560 foo = value 1561 ` 1562 1563 const testStateMvLargeCount_stateOutSrc = ` 1564 test_instance.bar: 1565 ID = bar 1566 provider = provider["registry.terraform.io/hashicorp/test"] 1567 bar = value 1568 foo = value 1569 ` 1570 1571 const testStateMvLargeCount_stateOutOriginal = ` 1572 test_instance.bar: 1573 ID = bar 1574 provider = provider["registry.terraform.io/hashicorp/test"] 1575 bar = value 1576 foo = value 1577 test_instance.foo.0: 1578 ID = foo0 1579 provider = provider["registry.terraform.io/hashicorp/test"] 1580 bar = value 1581 foo = value 1582 test_instance.foo.1: 1583 ID = foo1 1584 provider = provider["registry.terraform.io/hashicorp/test"] 1585 bar = value 1586 foo = value 1587 test_instance.foo.2: 1588 ID = foo2 1589 provider = provider["registry.terraform.io/hashicorp/test"] 1590 bar = value 1591 foo = value 1592 test_instance.foo.3: 1593 ID = foo3 1594 provider = provider["registry.terraform.io/hashicorp/test"] 1595 bar = value 1596 foo = value 1597 test_instance.foo.4: 1598 ID = foo4 1599 provider = provider["registry.terraform.io/hashicorp/test"] 1600 bar = value 1601 foo = value 1602 test_instance.foo.5: 1603 ID = foo5 1604 provider = provider["registry.terraform.io/hashicorp/test"] 1605 bar = value 1606 foo = value 1607 test_instance.foo.6: 1608 ID = foo6 1609 provider = provider["registry.terraform.io/hashicorp/test"] 1610 bar = value 1611 foo = value 1612 test_instance.foo.7: 1613 ID = foo7 1614 provider = provider["registry.terraform.io/hashicorp/test"] 1615 bar = value 1616 foo = value 1617 test_instance.foo.8: 1618 ID = foo8 1619 provider = provider["registry.terraform.io/hashicorp/test"] 1620 bar = value 1621 foo = value 1622 test_instance.foo.9: 1623 ID = foo9 1624 provider = provider["registry.terraform.io/hashicorp/test"] 1625 bar = value 1626 foo = value 1627 test_instance.foo.10: 1628 ID = foo10 1629 provider = provider["registry.terraform.io/hashicorp/test"] 1630 bar = value 1631 foo = value 1632 ` 1633 1634 const testStateMvNestedModule_stateOut = ` 1635 <no state> 1636 module.bar.child1: 1637 test_instance.foo: 1638 ID = bar 1639 provider = provider["registry.terraform.io/hashicorp/test"] 1640 bar = value 1641 foo = value 1642 module.bar.child2: 1643 test_instance.foo: 1644 ID = bar 1645 provider = provider["registry.terraform.io/hashicorp/test"] 1646 bar = value 1647 foo = value 1648 ` 1649 1650 const testStateMvNewModule_stateOut = ` 1651 <no state> 1652 module.bar: 1653 test_instance.bar: 1654 ID = bar 1655 provider = provider["registry.terraform.io/hashicorp/test"] 1656 bar = value 1657 foo = value 1658 ` 1659 1660 const testStateMvModuleNewModule_stateOut = ` 1661 <no state> 1662 module.foo: 1663 test_instance.bar: 1664 ID = bar 1665 provider = provider["registry.terraform.io/hashicorp/test"] 1666 bar = value 1667 foo = value 1668 ` 1669 1670 const testStateMvNewModule_stateOutOriginal = ` 1671 test_instance.bar: 1672 ID = bar 1673 provider = provider["registry.terraform.io/hashicorp/test"] 1674 bar = value 1675 foo = value 1676 ` 1677 1678 const testStateMvNestedModule_stateOutSrc = ` 1679 <no state> 1680 ` 1681 1682 const testStateMvNestedModule_stateOutOriginal = ` 1683 <no state> 1684 module.foo.child1: 1685 test_instance.foo: 1686 ID = bar 1687 provider = provider["registry.terraform.io/hashicorp/test"] 1688 bar = value 1689 foo = value 1690 module.foo.child2: 1691 test_instance.foo: 1692 ID = bar 1693 provider = provider["registry.terraform.io/hashicorp/test"] 1694 bar = value 1695 foo = value 1696 ` 1697 1698 const testStateMvOutput_stateOut = ` 1699 test_instance.bar: 1700 ID = bar 1701 provider = provider["registry.terraform.io/hashicorp/test"] 1702 bar = value 1703 foo = value 1704 ` 1705 1706 const testStateMvOutput_stateOutSrc = ` 1707 <no state> 1708 ` 1709 1710 const testStateMvOutput_stateOutOriginal = ` 1711 test_instance.foo: 1712 ID = bar 1713 provider = provider["registry.terraform.io/hashicorp/test"] 1714 bar = value 1715 foo = value 1716 ` 1717 1718 const testStateMvExisting_stateSrc = ` 1719 <no state> 1720 ` 1721 1722 const testStateMvExisting_stateDst = ` 1723 test_instance.bar: 1724 ID = bar 1725 provider = provider["registry.terraform.io/hashicorp/test"] 1726 bar = value 1727 foo = value 1728 test_instance.qux: 1729 ID = bar 1730 provider = provider["registry.terraform.io/hashicorp/test"] 1731 ` 1732 1733 const testStateMvExisting_stateSrcOriginal = ` 1734 test_instance.foo: 1735 ID = bar 1736 provider = provider["registry.terraform.io/hashicorp/test"] 1737 bar = value 1738 foo = value 1739 ` 1740 1741 const testStateMvExisting_stateDstOriginal = ` 1742 test_instance.qux: 1743 ID = bar 1744 provider = provider["registry.terraform.io/hashicorp/test"] 1745 ` 1746 1747 const testStateMvOriginal_backend = ` 1748 test_instance.baz: 1749 ID = foo 1750 provider = provider["registry.terraform.io/hashicorp/test"] 1751 bar = value 1752 foo = value 1753 ` 1754 1755 const testStateMvOnlyResourceInModule_original = ` 1756 <no state> 1757 module.foo: 1758 test_instance.foo.0: 1759 ID = bar 1760 provider = provider["registry.terraform.io/hashicorp/test"] 1761 bar = value 1762 foo = value 1763 ` 1764 1765 const testStateMvOnlyResourceInModule_output = ` 1766 <no state> 1767 module.foo: 1768 test_instance.bar.0: 1769 ID = bar 1770 provider = provider["registry.terraform.io/hashicorp/test"] 1771 bar = value 1772 foo = value 1773 `