github.com/archgrove/terraform@v0.9.5-0.20170502093151-adb789f0f8d2/command/state_mv_test.go (about) 1 package command 2 3 import ( 4 "os" 5 "path/filepath" 6 "testing" 7 8 "github.com/hashicorp/terraform/terraform" 9 "github.com/mitchellh/cli" 10 ) 11 12 func TestStateMv(t *testing.T) { 13 state := &terraform.State{ 14 Modules: []*terraform.ModuleState{ 15 &terraform.ModuleState{ 16 Path: []string{"root"}, 17 Resources: map[string]*terraform.ResourceState{ 18 "test_instance.foo": &terraform.ResourceState{ 19 Type: "test_instance", 20 Primary: &terraform.InstanceState{ 21 ID: "bar", 22 Attributes: map[string]string{ 23 "foo": "value", 24 "bar": "value", 25 }, 26 }, 27 }, 28 29 "test_instance.baz": &terraform.ResourceState{ 30 Type: "test_instance", 31 Primary: &terraform.InstanceState{ 32 ID: "foo", 33 Attributes: map[string]string{ 34 "foo": "value", 35 "bar": "value", 36 }, 37 }, 38 }, 39 }, 40 }, 41 }, 42 } 43 44 statePath := testStateFile(t, state) 45 46 p := testProvider() 47 ui := new(cli.MockUi) 48 c := &StateMvCommand{ 49 Meta: Meta{ 50 ContextOpts: testCtxConfig(p), 51 Ui: ui, 52 }, 53 } 54 55 args := []string{ 56 "-state", statePath, 57 "test_instance.foo", 58 "test_instance.bar", 59 } 60 if code := c.Run(args); code != 0 { 61 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 62 } 63 64 // Test it is correct 65 testStateOutput(t, statePath, testStateMvOutput) 66 67 // Test we have backups 68 backups := testStateBackups(t, filepath.Dir(statePath)) 69 if len(backups) != 1 { 70 t.Fatalf("bad: %#v", backups) 71 } 72 testStateOutput(t, backups[0], testStateMvOutputOriginal) 73 } 74 75 func TestStateMv_backupExplicit(t *testing.T) { 76 td := tempDir(t) 77 defer os.RemoveAll(td) 78 backupPath := filepath.Join(td, "backup") 79 80 state := &terraform.State{ 81 Modules: []*terraform.ModuleState{ 82 &terraform.ModuleState{ 83 Path: []string{"root"}, 84 Resources: map[string]*terraform.ResourceState{ 85 "test_instance.foo": &terraform.ResourceState{ 86 Type: "test_instance", 87 Primary: &terraform.InstanceState{ 88 ID: "bar", 89 Attributes: map[string]string{ 90 "foo": "value", 91 "bar": "value", 92 }, 93 }, 94 }, 95 96 "test_instance.baz": &terraform.ResourceState{ 97 Type: "test_instance", 98 Primary: &terraform.InstanceState{ 99 ID: "foo", 100 Attributes: map[string]string{ 101 "foo": "value", 102 "bar": "value", 103 }, 104 }, 105 }, 106 }, 107 }, 108 }, 109 } 110 111 statePath := testStateFile(t, state) 112 113 p := testProvider() 114 ui := new(cli.MockUi) 115 c := &StateMvCommand{ 116 Meta: Meta{ 117 ContextOpts: testCtxConfig(p), 118 Ui: ui, 119 }, 120 } 121 122 args := []string{ 123 "-backup", backupPath, 124 "-state", statePath, 125 "test_instance.foo", 126 "test_instance.bar", 127 } 128 if code := c.Run(args); code != 0 { 129 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 130 } 131 132 // Test it is correct 133 testStateOutput(t, statePath, testStateMvOutput) 134 135 // Test we have backups 136 backups := testStateBackups(t, filepath.Dir(statePath)) 137 if len(backups) != 1 { 138 t.Fatalf("bad: %#v", backups) 139 } 140 testStateOutput(t, backups[0], testStateMvOutputOriginal) 141 testStateOutput(t, backupPath, testStateMvOutputOriginal) 142 } 143 144 func TestStateMv_stateOutNew(t *testing.T) { 145 state := &terraform.State{ 146 Modules: []*terraform.ModuleState{ 147 &terraform.ModuleState{ 148 Path: []string{"root"}, 149 Resources: map[string]*terraform.ResourceState{ 150 "test_instance.foo": &terraform.ResourceState{ 151 Type: "test_instance", 152 Primary: &terraform.InstanceState{ 153 ID: "bar", 154 Attributes: map[string]string{ 155 "foo": "value", 156 "bar": "value", 157 }, 158 }, 159 }, 160 }, 161 }, 162 }, 163 } 164 165 statePath := testStateFile(t, state) 166 stateOutPath := statePath + ".out" 167 168 p := testProvider() 169 ui := new(cli.MockUi) 170 c := &StateMvCommand{ 171 Meta: Meta{ 172 ContextOpts: testCtxConfig(p), 173 Ui: ui, 174 }, 175 } 176 177 args := []string{ 178 "-state", statePath, 179 "-state-out", stateOutPath, 180 "test_instance.foo", 181 "test_instance.bar", 182 } 183 if code := c.Run(args); code != 0 { 184 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 185 } 186 187 // Test it is correct 188 testStateOutput(t, stateOutPath, testStateMvOutput_stateOut) 189 testStateOutput(t, statePath, testStateMvOutput_stateOutSrc) 190 191 // Test we have backups 192 backups := testStateBackups(t, filepath.Dir(statePath)) 193 if len(backups) != 1 { 194 t.Fatalf("bad: %#v", backups) 195 } 196 testStateOutput(t, backups[0], testStateMvOutput_stateOutOriginal) 197 } 198 199 func TestStateMv_stateOutExisting(t *testing.T) { 200 stateSrc := &terraform.State{ 201 Modules: []*terraform.ModuleState{ 202 &terraform.ModuleState{ 203 Path: []string{"root"}, 204 Resources: map[string]*terraform.ResourceState{ 205 "test_instance.foo": &terraform.ResourceState{ 206 Type: "test_instance", 207 Primary: &terraform.InstanceState{ 208 ID: "bar", 209 Attributes: map[string]string{ 210 "foo": "value", 211 "bar": "value", 212 }, 213 }, 214 }, 215 }, 216 }, 217 }, 218 } 219 220 statePath := testStateFile(t, stateSrc) 221 222 stateDst := &terraform.State{ 223 Modules: []*terraform.ModuleState{ 224 &terraform.ModuleState{ 225 Path: []string{"root"}, 226 Resources: map[string]*terraform.ResourceState{ 227 "test_instance.qux": &terraform.ResourceState{ 228 Type: "test_instance", 229 Primary: &terraform.InstanceState{ 230 ID: "bar", 231 }, 232 }, 233 }, 234 }, 235 }, 236 } 237 238 stateOutPath := testStateFile(t, stateDst) 239 240 p := testProvider() 241 ui := new(cli.MockUi) 242 c := &StateMvCommand{ 243 Meta: Meta{ 244 ContextOpts: testCtxConfig(p), 245 Ui: ui, 246 }, 247 } 248 249 args := []string{ 250 "-state", statePath, 251 "-state-out", stateOutPath, 252 "test_instance.foo", 253 "test_instance.bar", 254 } 255 if code := c.Run(args); code != 0 { 256 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 257 } 258 259 // Test it is correct 260 testStateOutput(t, stateOutPath, testStateMvExisting_stateDst) 261 testStateOutput(t, statePath, testStateMvExisting_stateSrc) 262 263 // Test we have backups 264 backups := testStateBackups(t, filepath.Dir(statePath)) 265 if len(backups) != 1 { 266 t.Fatalf("bad: %#v", backups) 267 } 268 testStateOutput(t, backups[0], testStateMvExisting_stateSrcOriginal) 269 270 backups = testStateBackups(t, filepath.Dir(stateOutPath)) 271 if len(backups) != 1 { 272 t.Fatalf("bad: %#v", backups) 273 } 274 testStateOutput(t, backups[0], testStateMvExisting_stateDstOriginal) 275 } 276 277 func TestStateMv_noState(t *testing.T) { 278 tmp, cwd := testCwd(t) 279 defer testFixCwd(t, tmp, cwd) 280 281 p := testProvider() 282 ui := new(cli.MockUi) 283 c := &StateMvCommand{ 284 Meta: Meta{ 285 ContextOpts: testCtxConfig(p), 286 Ui: ui, 287 }, 288 } 289 290 args := []string{"from", "to"} 291 if code := c.Run(args); code != 1 { 292 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 293 } 294 } 295 296 func TestStateMv_stateOutNew_count(t *testing.T) { 297 state := &terraform.State{ 298 Modules: []*terraform.ModuleState{ 299 &terraform.ModuleState{ 300 Path: []string{"root"}, 301 Resources: map[string]*terraform.ResourceState{ 302 "test_instance.foo.0": &terraform.ResourceState{ 303 Type: "test_instance", 304 Primary: &terraform.InstanceState{ 305 ID: "foo", 306 Attributes: map[string]string{ 307 "foo": "value", 308 "bar": "value", 309 }, 310 }, 311 }, 312 313 "test_instance.foo.1": &terraform.ResourceState{ 314 Type: "test_instance", 315 Primary: &terraform.InstanceState{ 316 ID: "bar", 317 Attributes: map[string]string{ 318 "foo": "value", 319 "bar": "value", 320 }, 321 }, 322 }, 323 324 "test_instance.bar": &terraform.ResourceState{ 325 Type: "test_instance", 326 Primary: &terraform.InstanceState{ 327 ID: "bar", 328 Attributes: map[string]string{ 329 "foo": "value", 330 "bar": "value", 331 }, 332 }, 333 }, 334 }, 335 }, 336 }, 337 } 338 339 statePath := testStateFile(t, state) 340 stateOutPath := statePath + ".out" 341 342 p := testProvider() 343 ui := new(cli.MockUi) 344 c := &StateMvCommand{ 345 Meta: Meta{ 346 ContextOpts: testCtxConfig(p), 347 Ui: ui, 348 }, 349 } 350 351 args := []string{ 352 "-state", statePath, 353 "-state-out", stateOutPath, 354 "test_instance.foo", 355 "test_instance.bar", 356 } 357 if code := c.Run(args); code != 0 { 358 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 359 } 360 361 // Test it is correct 362 testStateOutput(t, stateOutPath, testStateMvCount_stateOut) 363 testStateOutput(t, statePath, testStateMvCount_stateOutSrc) 364 365 // Test we have backups 366 backups := testStateBackups(t, filepath.Dir(statePath)) 367 if len(backups) != 1 { 368 t.Fatalf("bad: %#v", backups) 369 } 370 testStateOutput(t, backups[0], testStateMvCount_stateOutOriginal) 371 } 372 373 // Modules with more than 10 resources were sorted lexically, causing the 374 // indexes in the new location to change. 375 func TestStateMv_stateOutNew_largeCount(t *testing.T) { 376 state := &terraform.State{ 377 Modules: []*terraform.ModuleState{ 378 &terraform.ModuleState{ 379 Path: []string{"root"}, 380 Resources: map[string]*terraform.ResourceState{ 381 "test_instance.foo.0": &terraform.ResourceState{ 382 Type: "test_instance", 383 Primary: &terraform.InstanceState{ 384 ID: "foo0", 385 Attributes: map[string]string{ 386 "foo": "value", 387 "bar": "value", 388 }, 389 }, 390 }, 391 392 "test_instance.foo.1": &terraform.ResourceState{ 393 Type: "test_instance", 394 Primary: &terraform.InstanceState{ 395 ID: "foo1", 396 Attributes: map[string]string{ 397 "foo": "value", 398 "bar": "value", 399 }, 400 }, 401 }, 402 403 "test_instance.foo.2": &terraform.ResourceState{ 404 Type: "test_instance", 405 Primary: &terraform.InstanceState{ 406 ID: "foo2", 407 Attributes: map[string]string{ 408 "foo": "value", 409 "bar": "value", 410 }, 411 }, 412 }, 413 414 "test_instance.foo.3": &terraform.ResourceState{ 415 Type: "test_instance", 416 Primary: &terraform.InstanceState{ 417 ID: "foo3", 418 Attributes: map[string]string{ 419 "foo": "value", 420 "bar": "value", 421 }, 422 }, 423 }, 424 425 "test_instance.foo.4": &terraform.ResourceState{ 426 Type: "test_instance", 427 Primary: &terraform.InstanceState{ 428 ID: "foo4", 429 Attributes: map[string]string{ 430 "foo": "value", 431 "bar": "value", 432 }, 433 }, 434 }, 435 436 "test_instance.foo.5": &terraform.ResourceState{ 437 Type: "test_instance", 438 Primary: &terraform.InstanceState{ 439 ID: "foo5", 440 Attributes: map[string]string{ 441 "foo": "value", 442 "bar": "value", 443 }, 444 }, 445 }, 446 447 "test_instance.foo.6": &terraform.ResourceState{ 448 Type: "test_instance", 449 Primary: &terraform.InstanceState{ 450 ID: "foo6", 451 Attributes: map[string]string{ 452 "foo": "value", 453 "bar": "value", 454 }, 455 }, 456 }, 457 458 "test_instance.foo.7": &terraform.ResourceState{ 459 Type: "test_instance", 460 Primary: &terraform.InstanceState{ 461 ID: "foo7", 462 Attributes: map[string]string{ 463 "foo": "value", 464 "bar": "value", 465 }, 466 }, 467 }, 468 469 "test_instance.foo.8": &terraform.ResourceState{ 470 Type: "test_instance", 471 Primary: &terraform.InstanceState{ 472 ID: "foo8", 473 Attributes: map[string]string{ 474 "foo": "value", 475 "bar": "value", 476 }, 477 }, 478 }, 479 480 "test_instance.foo.9": &terraform.ResourceState{ 481 Type: "test_instance", 482 Primary: &terraform.InstanceState{ 483 ID: "foo9", 484 Attributes: map[string]string{ 485 "foo": "value", 486 "bar": "value", 487 }, 488 }, 489 }, 490 491 "test_instance.foo.10": &terraform.ResourceState{ 492 Type: "test_instance", 493 Primary: &terraform.InstanceState{ 494 ID: "foo10", 495 Attributes: map[string]string{ 496 "foo": "value", 497 "bar": "value", 498 }, 499 }, 500 }, 501 502 "test_instance.bar": &terraform.ResourceState{ 503 Type: "test_instance", 504 Primary: &terraform.InstanceState{ 505 ID: "bar", 506 Attributes: map[string]string{ 507 "foo": "value", 508 "bar": "value", 509 }, 510 }, 511 }, 512 }, 513 }, 514 }, 515 } 516 517 statePath := testStateFile(t, state) 518 stateOutPath := statePath + ".out" 519 520 p := testProvider() 521 ui := new(cli.MockUi) 522 c := &StateMvCommand{ 523 Meta: Meta{ 524 ContextOpts: testCtxConfig(p), 525 Ui: ui, 526 }, 527 } 528 529 args := []string{ 530 "-state", statePath, 531 "-state-out", stateOutPath, 532 "test_instance.foo", 533 "test_instance.bar", 534 } 535 if code := c.Run(args); code != 0 { 536 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 537 } 538 539 // Test it is correct 540 testStateOutput(t, stateOutPath, testStateMvLargeCount_stateOut) 541 testStateOutput(t, statePath, testStateMvLargeCount_stateOutSrc) 542 543 // Test we have backups 544 backups := testStateBackups(t, filepath.Dir(statePath)) 545 if len(backups) != 1 { 546 t.Fatalf("bad: %#v", backups) 547 } 548 testStateOutput(t, backups[0], testStateMvLargeCount_stateOutOriginal) 549 } 550 551 func TestStateMv_stateOutNew_nestedModule(t *testing.T) { 552 state := &terraform.State{ 553 Modules: []*terraform.ModuleState{ 554 &terraform.ModuleState{ 555 Path: []string{"root"}, 556 Resources: map[string]*terraform.ResourceState{}, 557 }, 558 559 &terraform.ModuleState{ 560 Path: []string{"root", "foo"}, 561 Resources: map[string]*terraform.ResourceState{}, 562 }, 563 564 &terraform.ModuleState{ 565 Path: []string{"root", "foo", "child1"}, 566 Resources: map[string]*terraform.ResourceState{ 567 "test_instance.foo": &terraform.ResourceState{ 568 Type: "test_instance", 569 Primary: &terraform.InstanceState{ 570 ID: "bar", 571 Attributes: map[string]string{ 572 "foo": "value", 573 "bar": "value", 574 }, 575 }, 576 }, 577 }, 578 }, 579 580 &terraform.ModuleState{ 581 Path: []string{"root", "foo", "child2"}, 582 Resources: map[string]*terraform.ResourceState{ 583 "test_instance.foo": &terraform.ResourceState{ 584 Type: "test_instance", 585 Primary: &terraform.InstanceState{ 586 ID: "bar", 587 Attributes: map[string]string{ 588 "foo": "value", 589 "bar": "value", 590 }, 591 }, 592 }, 593 }, 594 }, 595 }, 596 } 597 598 statePath := testStateFile(t, state) 599 stateOutPath := statePath + ".out" 600 601 p := testProvider() 602 ui := new(cli.MockUi) 603 c := &StateMvCommand{ 604 Meta: Meta{ 605 ContextOpts: testCtxConfig(p), 606 Ui: ui, 607 }, 608 } 609 610 args := []string{ 611 "-state", statePath, 612 "-state-out", stateOutPath, 613 "module.foo", 614 "module.bar", 615 } 616 if code := c.Run(args); code != 0 { 617 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 618 } 619 620 // Test it is correct 621 testStateOutput(t, stateOutPath, testStateMvNestedModule_stateOut) 622 testStateOutput(t, statePath, testStateMvNestedModule_stateOutSrc) 623 624 // Test we have backups 625 backups := testStateBackups(t, filepath.Dir(statePath)) 626 if len(backups) != 1 { 627 t.Fatalf("bad: %#v", backups) 628 } 629 testStateOutput(t, backups[0], testStateMvNestedModule_stateOutOriginal) 630 } 631 632 const testStateMvOutputOriginal = ` 633 test_instance.baz: 634 ID = foo 635 bar = value 636 foo = value 637 test_instance.foo: 638 ID = bar 639 bar = value 640 foo = value 641 ` 642 643 const testStateMvOutput = ` 644 test_instance.bar: 645 ID = bar 646 bar = value 647 foo = value 648 test_instance.baz: 649 ID = foo 650 bar = value 651 foo = value 652 ` 653 654 const testStateMvCount_stateOut = ` 655 test_instance.bar.0: 656 ID = foo 657 bar = value 658 foo = value 659 test_instance.bar.1: 660 ID = bar 661 bar = value 662 foo = value 663 ` 664 665 const testStateMvCount_stateOutSrc = ` 666 test_instance.bar: 667 ID = bar 668 bar = value 669 foo = value 670 ` 671 672 const testStateMvCount_stateOutOriginal = ` 673 test_instance.bar: 674 ID = bar 675 bar = value 676 foo = value 677 test_instance.foo.0: 678 ID = foo 679 bar = value 680 foo = value 681 test_instance.foo.1: 682 ID = bar 683 bar = value 684 foo = value 685 ` 686 687 const testStateMvLargeCount_stateOut = ` 688 test_instance.bar.0: 689 ID = foo0 690 bar = value 691 foo = value 692 test_instance.bar.1: 693 ID = foo1 694 bar = value 695 foo = value 696 test_instance.bar.2: 697 ID = foo2 698 bar = value 699 foo = value 700 test_instance.bar.3: 701 ID = foo3 702 bar = value 703 foo = value 704 test_instance.bar.4: 705 ID = foo4 706 bar = value 707 foo = value 708 test_instance.bar.5: 709 ID = foo5 710 bar = value 711 foo = value 712 test_instance.bar.6: 713 ID = foo6 714 bar = value 715 foo = value 716 test_instance.bar.7: 717 ID = foo7 718 bar = value 719 foo = value 720 test_instance.bar.8: 721 ID = foo8 722 bar = value 723 foo = value 724 test_instance.bar.9: 725 ID = foo9 726 bar = value 727 foo = value 728 test_instance.bar.10: 729 ID = foo10 730 bar = value 731 foo = value 732 ` 733 734 const testStateMvLargeCount_stateOutSrc = ` 735 test_instance.bar: 736 ID = bar 737 bar = value 738 foo = value 739 ` 740 741 const testStateMvLargeCount_stateOutOriginal = ` 742 test_instance.bar: 743 ID = bar 744 bar = value 745 foo = value 746 test_instance.foo.0: 747 ID = foo0 748 bar = value 749 foo = value 750 test_instance.foo.1: 751 ID = foo1 752 bar = value 753 foo = value 754 test_instance.foo.2: 755 ID = foo2 756 bar = value 757 foo = value 758 test_instance.foo.3: 759 ID = foo3 760 bar = value 761 foo = value 762 test_instance.foo.4: 763 ID = foo4 764 bar = value 765 foo = value 766 test_instance.foo.5: 767 ID = foo5 768 bar = value 769 foo = value 770 test_instance.foo.6: 771 ID = foo6 772 bar = value 773 foo = value 774 test_instance.foo.7: 775 ID = foo7 776 bar = value 777 foo = value 778 test_instance.foo.8: 779 ID = foo8 780 bar = value 781 foo = value 782 test_instance.foo.9: 783 ID = foo9 784 bar = value 785 foo = value 786 test_instance.foo.10: 787 ID = foo10 788 bar = value 789 foo = value 790 ` 791 792 const testStateMvNestedModule_stateOut = ` 793 <no state> 794 module.bar: 795 <no state> 796 module.bar.child1: 797 test_instance.foo: 798 ID = bar 799 bar = value 800 foo = value 801 module.bar.child2: 802 test_instance.foo: 803 ID = bar 804 bar = value 805 foo = value 806 ` 807 808 const testStateMvNestedModule_stateOutSrc = ` 809 <no state> 810 ` 811 812 const testStateMvNestedModule_stateOutOriginal = ` 813 <no state> 814 module.foo: 815 <no state> 816 module.foo.child1: 817 test_instance.foo: 818 ID = bar 819 bar = value 820 foo = value 821 module.foo.child2: 822 test_instance.foo: 823 ID = bar 824 bar = value 825 foo = value 826 ` 827 828 const testStateMvOutput_stateOut = ` 829 test_instance.bar: 830 ID = bar 831 bar = value 832 foo = value 833 ` 834 835 const testStateMvOutput_stateOutSrc = ` 836 <no state> 837 ` 838 839 const testStateMvOutput_stateOutOriginal = ` 840 test_instance.foo: 841 ID = bar 842 bar = value 843 foo = value 844 ` 845 846 const testStateMvExisting_stateSrc = ` 847 <no state> 848 ` 849 850 const testStateMvExisting_stateDst = ` 851 test_instance.bar: 852 ID = bar 853 bar = value 854 foo = value 855 test_instance.qux: 856 ID = bar 857 ` 858 859 const testStateMvExisting_stateSrcOriginal = ` 860 test_instance.foo: 861 ID = bar 862 bar = value 863 foo = value 864 ` 865 866 const testStateMvExisting_stateDstOriginal = ` 867 test_instance.qux: 868 ID = bar 869 `