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