github.com/nevins-b/terraform@v0.3.8-0.20170215184714-bbae22007d5a/command/meta_backend_test.go (about) 1 package command 2 3 import ( 4 "io/ioutil" 5 "os" 6 "path/filepath" 7 "strings" 8 "testing" 9 10 "github.com/hashicorp/terraform/helper/copy" 11 "github.com/hashicorp/terraform/state" 12 "github.com/hashicorp/terraform/terraform" 13 "github.com/mitchellh/cli" 14 ) 15 16 // Test empty directory with no config/state creates a local state. 17 func TestMetaBackend_emptyDir(t *testing.T) { 18 // Create a temporary working directory that is empty 19 td := tempDir(t) 20 os.MkdirAll(td, 0755) 21 defer os.RemoveAll(td) 22 defer testChdir(t, td)() 23 24 // Get the backend 25 m := testMetaBackend(t, nil) 26 b, err := m.Backend(&BackendOpts{Init: true}) 27 if err != nil { 28 t.Fatalf("bad: %s", err) 29 } 30 31 // Write some state 32 s, err := b.State() 33 if err != nil { 34 t.Fatalf("bad: %s", err) 35 } 36 s.WriteState(testState()) 37 if err := s.PersistState(); err != nil { 38 t.Fatalf("bad: %s", err) 39 } 40 41 // Verify it exists where we expect it to 42 if isEmptyState(DefaultStateFilename) { 43 t.Fatalf("no state was written") 44 } 45 46 // Verify no backup since it was empty to start 47 if !isEmptyState(DefaultStateFilename + DefaultBackupExtension) { 48 t.Fatal("backup state should be empty") 49 } 50 51 // Verify no backend state was made 52 if !isEmptyState(filepath.Join(m.DataDir(), DefaultStateFilename)) { 53 t.Fatal("backend state should be empty") 54 } 55 } 56 57 // check for no state. Either the file doesn't exist, or is empty 58 func isEmptyState(path string) bool { 59 fi, err := os.Stat(path) 60 if os.IsNotExist(err) { 61 return true 62 } 63 64 if fi.Size() == 0 { 65 return true 66 } 67 68 return false 69 } 70 71 // Test a directory with a legacy state and no config continues to 72 // use the legacy state. 73 func TestMetaBackend_emptyWithDefaultState(t *testing.T) { 74 // Create a temporary working directory that is empty 75 td := tempDir(t) 76 os.MkdirAll(td, 0755) 77 defer os.RemoveAll(td) 78 defer testChdir(t, td)() 79 80 // Write the legacy state 81 statePath := DefaultStateFilename 82 { 83 f, err := os.Create(statePath) 84 if err != nil { 85 t.Fatalf("err: %s", err) 86 } 87 err = terraform.WriteState(testState(), f) 88 f.Close() 89 if err != nil { 90 t.Fatalf("err: %s", err) 91 } 92 } 93 94 // Get the backend 95 m := testMetaBackend(t, nil) 96 b, err := m.Backend(&BackendOpts{Init: true}) 97 if err != nil { 98 t.Fatalf("bad: %s", err) 99 } 100 101 // Check the state 102 s, err := b.State() 103 if err != nil { 104 t.Fatalf("bad: %s", err) 105 } 106 if actual := s.State().String(); actual != testState().String() { 107 t.Fatalf("bad: %s", actual) 108 } 109 110 // Verify it exists where we expect it to 111 if _, err := os.Stat(DefaultStateFilename); err != nil { 112 t.Fatalf("err: %s", err) 113 } 114 115 stateName := filepath.Join(m.DataDir(), DefaultStateFilename) 116 if !isEmptyState(stateName) { 117 t.Fatal("expected no state at", stateName) 118 } 119 120 // Write some state 121 next := testState() 122 next.Modules[0].Outputs["foo"] = &terraform.OutputState{Value: "bar"} 123 s.WriteState(testState()) 124 if err := s.PersistState(); err != nil { 125 t.Fatalf("bad: %s", err) 126 } 127 128 // Verify a backup was made since we're modifying a pre-existing state 129 if isEmptyState(DefaultStateFilename + DefaultBackupExtension) { 130 t.Fatal("backup state should not be empty") 131 } 132 } 133 134 // Test an empty directory with an explicit state path (outside the dir) 135 func TestMetaBackend_emptyWithExplicitState(t *testing.T) { 136 // Create a temporary working directory that is empty 137 td := tempDir(t) 138 os.MkdirAll(td, 0755) 139 defer os.RemoveAll(td) 140 defer testChdir(t, td)() 141 142 // Create another directory to store our state 143 stateDir := tempDir(t) 144 os.MkdirAll(stateDir, 0755) 145 defer os.RemoveAll(stateDir) 146 147 // Write the legacy state 148 statePath := filepath.Join(stateDir, "foo") 149 { 150 f, err := os.Create(statePath) 151 if err != nil { 152 t.Fatalf("err: %s", err) 153 } 154 err = terraform.WriteState(testState(), f) 155 f.Close() 156 if err != nil { 157 t.Fatalf("err: %s", err) 158 } 159 } 160 161 // Setup the meta 162 m := testMetaBackend(t, nil) 163 m.statePath = statePath 164 165 // Get the backend 166 b, err := m.Backend(&BackendOpts{Init: true}) 167 if err != nil { 168 t.Fatalf("bad: %s", err) 169 } 170 171 // Check the state 172 s, err := b.State() 173 if err != nil { 174 t.Fatalf("bad: %s", err) 175 } 176 if actual := s.State().String(); actual != testState().String() { 177 t.Fatalf("bad: %s", actual) 178 } 179 180 // Verify neither defaults exist 181 if _, err := os.Stat(DefaultStateFilename); err == nil { 182 t.Fatal("file should not exist") 183 } 184 185 stateName := filepath.Join(m.DataDir(), DefaultStateFilename) 186 if !isEmptyState(stateName) { 187 t.Fatal("expected no state at", stateName) 188 } 189 190 // Write some state 191 next := testState() 192 next.Modules[0].Outputs["foo"] = &terraform.OutputState{Value: "bar"} 193 s.WriteState(testState()) 194 if err := s.PersistState(); err != nil { 195 t.Fatalf("bad: %s", err) 196 } 197 198 // Verify a backup was made since we're modifying a pre-existing state 199 if isEmptyState(statePath + DefaultBackupExtension) { 200 t.Fatal("backup state should not be empty") 201 } 202 } 203 204 // Empty directory with legacy remote state 205 func TestMetaBackend_emptyLegacyRemote(t *testing.T) { 206 // Create a temporary working directory that is empty 207 td := tempDir(t) 208 os.MkdirAll(td, 0755) 209 defer os.RemoveAll(td) 210 defer testChdir(t, td)() 211 212 // Create some legacy remote state 213 legacyState := testState() 214 _, srv := testRemoteState(t, legacyState, 200) 215 defer srv.Close() 216 statePath := testStateFileRemote(t, legacyState) 217 218 // Setup the meta 219 m := testMetaBackend(t, nil) 220 221 // Get the backend 222 b, err := m.Backend(&BackendOpts{Init: true}) 223 if err != nil { 224 t.Fatalf("bad: %s", err) 225 } 226 227 // Check the state 228 s, err := b.State() 229 if err != nil { 230 t.Fatalf("bad: %s", err) 231 } 232 if err := s.RefreshState(); err != nil { 233 t.Fatalf("bad: %s", err) 234 } 235 state := s.State() 236 if actual := state.String(); actual != legacyState.String() { 237 t.Fatalf("bad: %s", actual) 238 } 239 240 // Verify we didn't setup the backend state 241 if !state.Backend.Empty() { 242 t.Fatal("shouldn't configure backend") 243 } 244 245 // Verify the default paths don't exist 246 if _, err := os.Stat(DefaultStateFilename); err == nil { 247 t.Fatal("file should not exist") 248 } 249 250 // Verify a backup doesn't exist 251 if _, err := os.Stat(DefaultStateFilename + DefaultBackupExtension); err == nil { 252 t.Fatal("file should not exist") 253 } 254 if _, err := os.Stat(statePath + DefaultBackupExtension); err == nil { 255 t.Fatal("file should not exist") 256 } 257 } 258 259 // Newly configured backend 260 func TestMetaBackend_configureNew(t *testing.T) { 261 // Create a temporary working directory that is empty 262 td := tempDir(t) 263 copy.CopyDir(testFixturePath("backend-new"), td) 264 defer os.RemoveAll(td) 265 defer testChdir(t, td)() 266 267 // Setup the meta 268 m := testMetaBackend(t, nil) 269 270 // Get the backend 271 b, err := m.Backend(&BackendOpts{Init: true}) 272 if err != nil { 273 t.Fatalf("bad: %s", err) 274 } 275 276 // Check the state 277 s, err := b.State() 278 if err != nil { 279 t.Fatalf("bad: %s", err) 280 } 281 if err := s.RefreshState(); err != nil { 282 t.Fatalf("bad: %s", err) 283 } 284 state := s.State() 285 if state != nil { 286 t.Fatal("state should be nil") 287 } 288 289 // Write some state 290 state = terraform.NewState() 291 state.Lineage = "changing" 292 s.WriteState(state) 293 if err := s.PersistState(); err != nil { 294 t.Fatalf("bad: %s", err) 295 } 296 297 // Verify the state is where we expect 298 { 299 f, err := os.Open("local-state.tfstate") 300 if err != nil { 301 t.Fatalf("err: %s", err) 302 } 303 actual, err := terraform.ReadState(f) 304 f.Close() 305 if err != nil { 306 t.Fatalf("err: %s", err) 307 } 308 309 if actual.Lineage != state.Lineage { 310 t.Fatalf("bad: %#v", actual) 311 } 312 } 313 314 // Verify the default paths don't exist 315 if _, err := os.Stat(DefaultStateFilename); err == nil { 316 t.Fatal("file should not exist") 317 } 318 319 // Verify a backup doesn't exist 320 if _, err := os.Stat(DefaultStateFilename + DefaultBackupExtension); err == nil { 321 t.Fatal("file should not exist") 322 } 323 } 324 325 // Newly configured backend with prior local state and no remote state 326 func TestMetaBackend_configureNewWithState(t *testing.T) { 327 // Create a temporary working directory that is empty 328 td := tempDir(t) 329 copy.CopyDir(testFixturePath("backend-new-migrate"), td) 330 defer os.RemoveAll(td) 331 defer testChdir(t, td)() 332 333 // Ask input 334 defer testInteractiveInput(t, []string{"yes"})() 335 336 // Setup the meta 337 m := testMetaBackend(t, nil) 338 339 // Get the backend 340 b, err := m.Backend(&BackendOpts{Init: true}) 341 if err != nil { 342 t.Fatalf("bad: %s", err) 343 } 344 345 // Check the state 346 s, err := b.State() 347 if err != nil { 348 t.Fatalf("bad: %s", err) 349 } 350 if err := s.RefreshState(); err != nil { 351 t.Fatalf("bad: %s", err) 352 } 353 state := s.State() 354 if state == nil { 355 t.Fatal("state is nil") 356 } 357 358 if state.Lineage != "backend-new-migrate" { 359 t.Fatalf("bad: %#v", state) 360 } 361 362 // Write some state 363 state = terraform.NewState() 364 state.Lineage = "changing" 365 s.WriteState(state) 366 if err := s.PersistState(); err != nil { 367 t.Fatalf("bad: %s", err) 368 } 369 370 // Verify the state is where we expect 371 { 372 f, err := os.Open("local-state.tfstate") 373 if err != nil { 374 t.Fatalf("err: %s", err) 375 } 376 actual, err := terraform.ReadState(f) 377 f.Close() 378 if err != nil { 379 t.Fatalf("err: %s", err) 380 } 381 382 if actual.Lineage != state.Lineage { 383 t.Fatalf("bad: %#v", actual) 384 } 385 } 386 387 // Verify the default paths don't exist 388 if !isEmptyState(DefaultStateFilename) { 389 data, _ := ioutil.ReadFile(DefaultStateFilename) 390 391 t.Fatal("state should not exist, but contains:\n", string(data)) 392 } 393 394 // Verify a backup does exist 395 if isEmptyState(DefaultStateFilename + DefaultBackupExtension) { 396 t.Fatal("backup state is empty or missing") 397 } 398 } 399 400 // Newly configured backend with prior local state and no remote state, 401 // but opting to not migrate. 402 func TestMetaBackend_configureNewWithStateNoMigrate(t *testing.T) { 403 // Create a temporary working directory that is empty 404 td := tempDir(t) 405 copy.CopyDir(testFixturePath("backend-new-migrate"), td) 406 defer os.RemoveAll(td) 407 defer testChdir(t, td)() 408 409 // Ask input 410 defer testInteractiveInput(t, []string{"no"})() 411 412 // Setup the meta 413 m := testMetaBackend(t, nil) 414 415 // Get the backend 416 b, err := m.Backend(&BackendOpts{Init: true}) 417 if err != nil { 418 t.Fatalf("bad: %s", err) 419 } 420 421 // Check the state 422 s, err := b.State() 423 if err != nil { 424 t.Fatalf("bad: %s", err) 425 } 426 if err := s.RefreshState(); err != nil { 427 t.Fatalf("bad: %s", err) 428 } 429 if state := s.State(); state != nil { 430 t.Fatal("state is not nil") 431 } 432 433 // Verify the default paths don't exist 434 if !isEmptyState(DefaultStateFilename) { 435 data, _ := ioutil.ReadFile(DefaultStateFilename) 436 437 t.Fatal("state should not exist, but contains:\n", string(data)) 438 } 439 440 // Verify a backup does exist 441 if isEmptyState(DefaultStateFilename + DefaultBackupExtension) { 442 t.Fatal("backup state is empty or missing") 443 } 444 } 445 446 // Newly configured backend with prior local state and remote state 447 func TestMetaBackend_configureNewWithStateExisting(t *testing.T) { 448 // Create a temporary working directory that is empty 449 td := tempDir(t) 450 copy.CopyDir(testFixturePath("backend-new-migrate-existing"), td) 451 defer os.RemoveAll(td) 452 defer testChdir(t, td)() 453 454 // Ask input 455 defer testInteractiveInput(t, []string{"yes"})() 456 457 // Setup the meta 458 m := testMetaBackend(t, nil) 459 460 // Get the backend 461 b, err := m.Backend(&BackendOpts{Init: true}) 462 if err != nil { 463 t.Fatalf("bad: %s", err) 464 } 465 466 // Check the state 467 s, err := b.State() 468 if err != nil { 469 t.Fatalf("bad: %s", err) 470 } 471 if err := s.RefreshState(); err != nil { 472 t.Fatalf("bad: %s", err) 473 } 474 state := s.State() 475 if state == nil { 476 t.Fatal("state is nil") 477 } 478 if state.Lineage != "local" { 479 t.Fatalf("bad: %#v", state) 480 } 481 482 // Write some state 483 state = terraform.NewState() 484 state.Lineage = "changing" 485 s.WriteState(state) 486 if err := s.PersistState(); err != nil { 487 t.Fatalf("bad: %s", err) 488 } 489 490 // Verify the state is where we expect 491 { 492 f, err := os.Open("local-state.tfstate") 493 if err != nil { 494 t.Fatalf("err: %s", err) 495 } 496 actual, err := terraform.ReadState(f) 497 f.Close() 498 if err != nil { 499 t.Fatalf("err: %s", err) 500 } 501 502 if actual.Lineage != state.Lineage { 503 t.Fatalf("bad: %#v", actual) 504 } 505 } 506 507 // Verify the default paths don't exist 508 if !isEmptyState(DefaultStateFilename) { 509 data, _ := ioutil.ReadFile(DefaultStateFilename) 510 511 t.Fatal("state should not exist, but contains:\n", string(data)) 512 } 513 514 // Verify a backup does exist 515 if isEmptyState(DefaultStateFilename + DefaultBackupExtension) { 516 t.Fatal("backup state is empty or missing") 517 } 518 } 519 520 // Newly configured backend with prior local state and remote state 521 func TestMetaBackend_configureNewWithStateExistingNoMigrate(t *testing.T) { 522 // Create a temporary working directory that is empty 523 td := tempDir(t) 524 copy.CopyDir(testFixturePath("backend-new-migrate-existing"), td) 525 defer os.RemoveAll(td) 526 defer testChdir(t, td)() 527 528 // Ask input 529 defer testInteractiveInput(t, []string{"no"})() 530 531 // Setup the meta 532 m := testMetaBackend(t, nil) 533 534 // Get the backend 535 b, err := m.Backend(&BackendOpts{Init: true}) 536 if err != nil { 537 t.Fatalf("bad: %s", err) 538 } 539 540 // Check the state 541 s, err := b.State() 542 if err != nil { 543 t.Fatalf("bad: %s", err) 544 } 545 if err := s.RefreshState(); err != nil { 546 t.Fatalf("bad: %s", err) 547 } 548 state := s.State() 549 if state == nil { 550 t.Fatal("state is nil") 551 } 552 if state.Lineage != "remote" { 553 t.Fatalf("bad: %#v", state) 554 } 555 556 // Write some state 557 state = terraform.NewState() 558 state.Lineage = "changing" 559 s.WriteState(state) 560 if err := s.PersistState(); err != nil { 561 t.Fatalf("bad: %s", err) 562 } 563 564 // Verify the state is where we expect 565 { 566 f, err := os.Open("local-state.tfstate") 567 if err != nil { 568 t.Fatalf("err: %s", err) 569 } 570 actual, err := terraform.ReadState(f) 571 f.Close() 572 if err != nil { 573 t.Fatalf("err: %s", err) 574 } 575 576 if actual.Lineage != state.Lineage { 577 t.Fatalf("bad: %#v", actual) 578 } 579 } 580 581 // Verify the default paths don't exist 582 if !isEmptyState(DefaultStateFilename) { 583 data, _ := ioutil.ReadFile(DefaultStateFilename) 584 585 t.Fatal("state should not exist, but contains:\n", string(data)) 586 } 587 588 // Verify a backup does exist 589 if isEmptyState(DefaultStateFilename + DefaultBackupExtension) { 590 t.Fatal("backup state is empty or missing") 591 } 592 } 593 594 // Newly configured backend with lgacy 595 func TestMetaBackend_configureNewLegacy(t *testing.T) { 596 // Create a temporary working directory that is empty 597 td := tempDir(t) 598 copy.CopyDir(testFixturePath("backend-new-legacy"), td) 599 defer os.RemoveAll(td) 600 defer testChdir(t, td)() 601 602 // Ask input 603 defer testInteractiveInput(t, []string{"no"})() 604 605 // Setup the meta 606 m := testMetaBackend(t, nil) 607 608 // Get the backend 609 b, err := m.Backend(&BackendOpts{Init: true}) 610 if err != nil { 611 t.Fatalf("bad: %s", err) 612 } 613 614 // Check the state 615 s, err := b.State() 616 if err != nil { 617 t.Fatalf("bad: %s", err) 618 } 619 if err := s.RefreshState(); err != nil { 620 t.Fatalf("bad: %s", err) 621 } 622 state := s.State() 623 if state != nil { 624 t.Fatal("state should be nil") 625 } 626 627 // Verify we have no configured legacy 628 { 629 path := filepath.Join(m.DataDir(), DefaultStateFilename) 630 f, err := os.Open(path) 631 if err != nil { 632 t.Fatalf("err: %s", err) 633 } 634 actual, err := terraform.ReadState(f) 635 f.Close() 636 if err != nil { 637 t.Fatalf("err: %s", err) 638 } 639 640 if !actual.Remote.Empty() { 641 t.Fatalf("bad: %#v", actual) 642 } 643 if actual.Backend.Empty() { 644 t.Fatalf("bad: %#v", actual) 645 } 646 } 647 648 // Write some state 649 state = terraform.NewState() 650 state.Lineage = "changing" 651 s.WriteState(state) 652 if err := s.PersistState(); err != nil { 653 t.Fatalf("bad: %s", err) 654 } 655 656 // Verify the state is where we expect 657 { 658 f, err := os.Open("local-state.tfstate") 659 if err != nil { 660 t.Fatalf("err: %s", err) 661 } 662 actual, err := terraform.ReadState(f) 663 f.Close() 664 if err != nil { 665 t.Fatalf("err: %s", err) 666 } 667 668 if actual.Lineage != state.Lineage { 669 t.Fatalf("bad: %#v", actual) 670 } 671 } 672 673 // Verify the default paths don't exist 674 if !isEmptyState(DefaultStateFilename) { 675 data, _ := ioutil.ReadFile(DefaultStateFilename) 676 677 t.Fatal("state should not exist, but contains:\n", string(data)) 678 } 679 680 // Verify a backup doesn't exist 681 if !isEmptyState(DefaultStateFilename + DefaultBackupExtension) { 682 data, _ := ioutil.ReadFile(DefaultStateFilename) 683 684 t.Fatal("backup should be empty, but contains:\n", string(data)) 685 } 686 } 687 688 // Newly configured backend with legacy 689 func TestMetaBackend_configureNewLegacyCopy(t *testing.T) { 690 // Create a temporary working directory that is empty 691 td := tempDir(t) 692 copy.CopyDir(testFixturePath("backend-new-legacy"), td) 693 defer os.RemoveAll(td) 694 defer testChdir(t, td)() 695 696 // Ask input 697 defer testInteractiveInput(t, []string{"yes", "yes"})() 698 699 // Setup the meta 700 m := testMetaBackend(t, nil) 701 702 // Get the backend 703 b, err := m.Backend(&BackendOpts{Init: true}) 704 if err != nil { 705 t.Fatalf("bad: %s", err) 706 } 707 708 // Check the state 709 s, err := b.State() 710 if err != nil { 711 t.Fatalf("bad: %s", err) 712 } 713 if err := s.RefreshState(); err != nil { 714 t.Fatalf("bad: %s", err) 715 } 716 state := s.State() 717 if state == nil { 718 t.Fatal("nil state") 719 } 720 if state.Lineage != "backend-new-legacy" { 721 t.Fatalf("bad: %#v", state) 722 } 723 724 // Verify we have no configured legacy 725 { 726 path := filepath.Join(m.DataDir(), DefaultStateFilename) 727 f, err := os.Open(path) 728 if err != nil { 729 t.Fatalf("err: %s", err) 730 } 731 actual, err := terraform.ReadState(f) 732 f.Close() 733 if err != nil { 734 t.Fatalf("err: %s", err) 735 } 736 737 if !actual.Remote.Empty() { 738 t.Fatalf("bad: %#v", actual) 739 } 740 if actual.Backend.Empty() { 741 t.Fatalf("bad: %#v", actual) 742 } 743 } 744 745 // Write some state 746 state = terraform.NewState() 747 state.Lineage = "changing" 748 s.WriteState(state) 749 if err := s.PersistState(); err != nil { 750 t.Fatalf("bad: %s", err) 751 } 752 753 // Verify the state is where we expect 754 { 755 f, err := os.Open("local-state.tfstate") 756 if err != nil { 757 t.Fatalf("err: %s", err) 758 } 759 actual, err := terraform.ReadState(f) 760 f.Close() 761 if err != nil { 762 t.Fatalf("err: %s", err) 763 } 764 765 if actual.Lineage != state.Lineage { 766 t.Fatalf("bad: %#v", actual) 767 } 768 } 769 770 // Verify the default paths don't exist 771 if _, err := os.Stat(DefaultStateFilename); err == nil { 772 t.Fatal("file should not exist") 773 } 774 775 // Verify a backup doesn't exist 776 if _, err := os.Stat(DefaultStateFilename + DefaultBackupExtension); err == nil { 777 t.Fatal("file should not exist") 778 } 779 } 780 781 // Saved backend state matching config 782 func TestMetaBackend_configuredUnchanged(t *testing.T) { 783 defer testChdir(t, testFixturePath("backend-unchanged"))() 784 785 // Setup the meta 786 m := testMetaBackend(t, nil) 787 788 // Get the backend 789 b, err := m.Backend(&BackendOpts{Init: true}) 790 if err != nil { 791 t.Fatalf("bad: %s", err) 792 } 793 794 // Check the state 795 s, err := b.State() 796 if err != nil { 797 t.Fatalf("bad: %s", err) 798 } 799 if err := s.RefreshState(); err != nil { 800 t.Fatalf("bad: %s", err) 801 } 802 state := s.State() 803 if state == nil { 804 t.Fatal("nil state") 805 } 806 if state.Lineage != "configuredUnchanged" { 807 t.Fatalf("bad: %#v", state) 808 } 809 810 // Verify the default paths don't exist 811 if _, err := os.Stat(DefaultStateFilename); err == nil { 812 t.Fatal("file should not exist") 813 } 814 815 // Verify a backup doesn't exist 816 if _, err := os.Stat(DefaultStateFilename + DefaultBackupExtension); err == nil { 817 t.Fatal("file should not exist") 818 } 819 } 820 821 // Changing a configured backend 822 func TestMetaBackend_configuredChange(t *testing.T) { 823 // Create a temporary working directory that is empty 824 td := tempDir(t) 825 copy.CopyDir(testFixturePath("backend-change"), td) 826 defer os.RemoveAll(td) 827 defer testChdir(t, td)() 828 829 // Ask input 830 defer testInteractiveInput(t, []string{"no"})() 831 832 // Setup the meta 833 m := testMetaBackend(t, nil) 834 835 // Get the backend 836 b, err := m.Backend(&BackendOpts{Init: true}) 837 if err != nil { 838 t.Fatalf("bad: %s", err) 839 } 840 841 // Check the state 842 s, err := b.State() 843 if err != nil { 844 t.Fatalf("bad: %s", err) 845 } 846 if err := s.RefreshState(); err != nil { 847 t.Fatalf("bad: %s", err) 848 } 849 state := s.State() 850 if state != nil { 851 t.Fatal("state should be nil") 852 } 853 854 // Verify the default paths don't exist 855 if _, err := os.Stat(DefaultStateFilename); err == nil { 856 t.Fatal("file should not exist") 857 } 858 859 // Verify a backup doesn't exist 860 if _, err := os.Stat(DefaultStateFilename + DefaultBackupExtension); err == nil { 861 t.Fatal("file should not exist") 862 } 863 864 // Write some state 865 state = terraform.NewState() 866 state.Lineage = "changing" 867 s.WriteState(state) 868 if err := s.PersistState(); err != nil { 869 t.Fatalf("bad: %s", err) 870 } 871 872 // Verify the state is where we expect 873 { 874 f, err := os.Open("local-state-2.tfstate") 875 if err != nil { 876 t.Fatalf("err: %s", err) 877 } 878 actual, err := terraform.ReadState(f) 879 f.Close() 880 if err != nil { 881 t.Fatalf("err: %s", err) 882 } 883 884 if actual.Lineage != state.Lineage { 885 t.Fatalf("bad: %#v", actual) 886 } 887 } 888 889 // Verify no local state 890 if _, err := os.Stat(DefaultStateFilename); err == nil { 891 t.Fatal("file should not exist") 892 } 893 894 // Verify no local backup 895 if _, err := os.Stat(DefaultStateFilename + DefaultBackupExtension); err == nil { 896 t.Fatal("file should not exist") 897 } 898 } 899 900 // Changing a configured backend, copying state 901 func TestMetaBackend_configuredChangeCopy(t *testing.T) { 902 // Create a temporary working directory that is empty 903 td := tempDir(t) 904 copy.CopyDir(testFixturePath("backend-change"), td) 905 defer os.RemoveAll(td) 906 defer testChdir(t, td)() 907 908 // Ask input 909 defer testInteractiveInput(t, []string{"yes", "yes"})() 910 911 // Setup the meta 912 m := testMetaBackend(t, nil) 913 914 // Get the backend 915 b, err := m.Backend(&BackendOpts{Init: true}) 916 if err != nil { 917 t.Fatalf("bad: %s", err) 918 } 919 920 // Check the state 921 s, err := b.State() 922 if err != nil { 923 t.Fatalf("bad: %s", err) 924 } 925 if err := s.RefreshState(); err != nil { 926 t.Fatalf("bad: %s", err) 927 } 928 state := s.State() 929 if state == nil { 930 t.Fatal("state should not be nil") 931 } 932 if state.Lineage != "backend-change" { 933 t.Fatalf("bad: %#v", state) 934 } 935 936 // Verify no local state 937 if _, err := os.Stat(DefaultStateFilename); err == nil { 938 t.Fatal("file should not exist") 939 } 940 941 // Verify no local backup 942 if _, err := os.Stat(DefaultStateFilename + DefaultBackupExtension); err == nil { 943 t.Fatal("file should not exist") 944 } 945 } 946 947 // Unsetting a saved backend 948 func TestMetaBackend_configuredUnset(t *testing.T) { 949 // Create a temporary working directory that is empty 950 td := tempDir(t) 951 copy.CopyDir(testFixturePath("backend-unset"), td) 952 defer os.RemoveAll(td) 953 defer testChdir(t, td)() 954 955 // Ask input 956 defer testInteractiveInput(t, []string{"no"})() 957 958 // Setup the meta 959 m := testMetaBackend(t, nil) 960 961 // Get the backend 962 b, err := m.Backend(&BackendOpts{Init: true}) 963 if err != nil { 964 t.Fatalf("bad: %s", err) 965 } 966 967 // Check the state 968 s, err := b.State() 969 if err != nil { 970 t.Fatalf("bad: %s", err) 971 } 972 if err := s.RefreshState(); err != nil { 973 t.Fatalf("bad: %s", err) 974 } 975 state := s.State() 976 if state != nil { 977 t.Fatal("state should be nil") 978 } 979 980 // Verify the default paths don't exist 981 if !isEmptyState(DefaultStateFilename) { 982 data, _ := ioutil.ReadFile(DefaultStateFilename) 983 t.Fatal("state should not exist, but contains:\n", string(data)) 984 } 985 986 // Verify a backup doesn't exist 987 if !isEmptyState(DefaultStateFilename + DefaultBackupExtension) { 988 data, _ := ioutil.ReadFile(DefaultStateFilename + DefaultBackupExtension) 989 t.Fatal("backup should not exist, but contains:\n", string(data)) 990 } 991 992 // Verify we have no configured backend/legacy 993 path := filepath.Join(m.DataDir(), DefaultStateFilename) 994 if _, err := os.Stat(path); err == nil { 995 f, err := os.Open(path) 996 if err != nil { 997 t.Fatalf("err: %s", err) 998 } 999 actual, err := terraform.ReadState(f) 1000 f.Close() 1001 if err != nil { 1002 t.Fatalf("err: %s", err) 1003 } 1004 1005 if !actual.Remote.Empty() { 1006 t.Fatalf("bad: %#v", actual) 1007 } 1008 if !actual.Backend.Empty() { 1009 t.Fatalf("bad: %#v", actual) 1010 } 1011 } 1012 1013 // Write some state 1014 s.WriteState(testState()) 1015 if err := s.PersistState(); err != nil { 1016 t.Fatalf("bad: %s", err) 1017 } 1018 1019 // Verify it exists where we expect it to 1020 if isEmptyState(DefaultStateFilename) { 1021 t.Fatal(DefaultStateFilename, "is empty") 1022 } 1023 1024 // Verify no backup since it was empty to start 1025 if !isEmptyState(DefaultStateFilename + DefaultBackupExtension) { 1026 data, _ := ioutil.ReadFile(DefaultStateFilename + DefaultBackupExtension) 1027 t.Fatal("backup state should be empty, but contains:\n", string(data)) 1028 } 1029 } 1030 1031 // Unsetting a saved backend and copying the remote state 1032 func TestMetaBackend_configuredUnsetCopy(t *testing.T) { 1033 // Create a temporary working directory that is empty 1034 td := tempDir(t) 1035 copy.CopyDir(testFixturePath("backend-unset"), td) 1036 defer os.RemoveAll(td) 1037 defer testChdir(t, td)() 1038 1039 // Ask input 1040 defer testInteractiveInput(t, []string{"yes", "yes"})() 1041 1042 // Setup the meta 1043 m := testMetaBackend(t, nil) 1044 1045 // Get the backend 1046 b, err := m.Backend(&BackendOpts{Init: true}) 1047 if err != nil { 1048 t.Fatalf("bad: %s", err) 1049 } 1050 1051 // Check the state 1052 s, err := b.State() 1053 if err != nil { 1054 t.Fatalf("bad: %s", err) 1055 } 1056 if err := s.RefreshState(); err != nil { 1057 t.Fatalf("bad: %s", err) 1058 } 1059 state := s.State() 1060 if state == nil { 1061 t.Fatal("state is nil") 1062 } 1063 if state.Lineage != "configuredUnset" { 1064 t.Fatalf("bad: %#v", state) 1065 } 1066 1067 // Verify a backup doesn't exist 1068 if !isEmptyState(DefaultStateFilename + DefaultBackupExtension) { 1069 t.Fatalf("backup state should be empty") 1070 } 1071 1072 // Verify we have no configured backend/legacy 1073 path := filepath.Join(m.DataDir(), DefaultStateFilename) 1074 if _, err := os.Stat(path); err == nil { 1075 f, err := os.Open(path) 1076 if err != nil { 1077 t.Fatalf("err: %s", err) 1078 } 1079 actual, err := terraform.ReadState(f) 1080 f.Close() 1081 if err != nil { 1082 t.Fatalf("err: %s", err) 1083 } 1084 1085 if !actual.Remote.Empty() { 1086 t.Fatalf("bad: %#v", actual) 1087 } 1088 if !actual.Backend.Empty() { 1089 t.Fatalf("bad: %#v", actual) 1090 } 1091 } 1092 1093 // Write some state 1094 s.WriteState(testState()) 1095 if err := s.PersistState(); err != nil { 1096 t.Fatalf("bad: %s", err) 1097 } 1098 1099 // Verify it exists where we expect it to 1100 if _, err := os.Stat(DefaultStateFilename); err != nil { 1101 t.Fatalf("err: %s", err) 1102 } 1103 1104 // Verify a backup since it wasn't empty to start 1105 if isEmptyState(DefaultStateFilename + DefaultBackupExtension) { 1106 t.Fatal("backup is empty") 1107 } 1108 } 1109 1110 // Saved backend state matching config, with legacy 1111 func TestMetaBackend_configuredUnchangedLegacy(t *testing.T) { 1112 // Create a temporary working directory that is empty 1113 td := tempDir(t) 1114 copy.CopyDir(testFixturePath("backend-unchanged-with-legacy"), td) 1115 defer os.RemoveAll(td) 1116 defer testChdir(t, td)() 1117 1118 // Ask input 1119 defer testInteractiveInput(t, []string{"no"})() 1120 1121 // Setup the meta 1122 m := testMetaBackend(t, nil) 1123 1124 // Get the backend 1125 b, err := m.Backend(&BackendOpts{Init: true}) 1126 if err != nil { 1127 t.Fatalf("bad: %s", err) 1128 } 1129 1130 // Check the state 1131 s, err := b.State() 1132 if err != nil { 1133 t.Fatalf("bad: %s", err) 1134 } 1135 if err := s.RefreshState(); err != nil { 1136 t.Fatalf("bad: %s", err) 1137 } 1138 state := s.State() 1139 if state == nil { 1140 t.Fatal("state is nil") 1141 } 1142 if state.Lineage != "configured" { 1143 t.Fatalf("bad: %#v", state) 1144 } 1145 1146 // Verify the default paths don't exist 1147 if _, err := os.Stat(DefaultStateFilename); err == nil { 1148 t.Fatalf("err: %s", err) 1149 } 1150 1151 // Verify a backup doesn't exist 1152 if _, err := os.Stat(DefaultStateFilename + DefaultBackupExtension); err == nil { 1153 t.Fatal("file should not exist") 1154 } 1155 1156 // Verify we have no configured legacy 1157 { 1158 path := filepath.Join(m.DataDir(), DefaultStateFilename) 1159 f, err := os.Open(path) 1160 if err != nil { 1161 t.Fatalf("err: %s", err) 1162 } 1163 actual, err := terraform.ReadState(f) 1164 f.Close() 1165 if err != nil { 1166 t.Fatalf("err: %s", err) 1167 } 1168 1169 if !actual.Remote.Empty() { 1170 t.Fatalf("bad: %#v", actual) 1171 } 1172 if actual.Backend.Empty() { 1173 t.Fatalf("bad: %#v", actual) 1174 } 1175 } 1176 1177 // Write some state 1178 state = terraform.NewState() 1179 state.Lineage = "changing" 1180 s.WriteState(state) 1181 if err := s.PersistState(); err != nil { 1182 t.Fatalf("bad: %s", err) 1183 } 1184 1185 // Verify the state is where we expect 1186 { 1187 f, err := os.Open("local-state.tfstate") 1188 if err != nil { 1189 t.Fatalf("err: %s", err) 1190 } 1191 actual, err := terraform.ReadState(f) 1192 f.Close() 1193 if err != nil { 1194 t.Fatalf("err: %s", err) 1195 } 1196 1197 if actual.Lineage != state.Lineage { 1198 t.Fatalf("bad: %#v", actual) 1199 } 1200 } 1201 1202 // Verify no local state 1203 if _, err := os.Stat(DefaultStateFilename); err == nil { 1204 t.Fatal("file should not exist") 1205 } 1206 1207 // Verify no local backup 1208 if _, err := os.Stat(DefaultStateFilename + DefaultBackupExtension); err == nil { 1209 t.Fatal("file should not exist") 1210 } 1211 } 1212 1213 // Saved backend state matching config, with legacy 1214 func TestMetaBackend_configuredUnchangedLegacyCopy(t *testing.T) { 1215 // Create a temporary working directory that is empty 1216 td := tempDir(t) 1217 copy.CopyDir(testFixturePath("backend-unchanged-with-legacy"), td) 1218 defer os.RemoveAll(td) 1219 defer testChdir(t, td)() 1220 1221 // Ask input 1222 defer testInteractiveInput(t, []string{"yes", "yes"})() 1223 1224 // Setup the meta 1225 m := testMetaBackend(t, nil) 1226 1227 // Get the backend 1228 b, err := m.Backend(&BackendOpts{Init: true}) 1229 if err != nil { 1230 t.Fatalf("bad: %s", err) 1231 } 1232 1233 // Check the state 1234 s, err := b.State() 1235 if err != nil { 1236 t.Fatalf("bad: %s", err) 1237 } 1238 if err := s.RefreshState(); err != nil { 1239 t.Fatalf("bad: %s", err) 1240 } 1241 state := s.State() 1242 if state == nil { 1243 t.Fatal("state is nil") 1244 } 1245 if state.Lineage != "backend-unchanged-with-legacy" { 1246 t.Fatalf("bad: %#v", state) 1247 } 1248 1249 // Verify the default paths don't exist 1250 if _, err := os.Stat(DefaultStateFilename); err == nil { 1251 t.Fatal("file should not exist") 1252 } 1253 1254 // Verify a backup doesn't exist 1255 if _, err := os.Stat(DefaultStateFilename + DefaultBackupExtension); err == nil { 1256 t.Fatal("file should not exist") 1257 } 1258 1259 // Verify we have no configured legacy 1260 { 1261 path := filepath.Join(m.DataDir(), DefaultStateFilename) 1262 f, err := os.Open(path) 1263 if err != nil { 1264 t.Fatalf("err: %s", err) 1265 } 1266 actual, err := terraform.ReadState(f) 1267 f.Close() 1268 if err != nil { 1269 t.Fatalf("err: %s", err) 1270 } 1271 1272 if !actual.Remote.Empty() { 1273 t.Fatalf("bad: %#v", actual) 1274 } 1275 if actual.Backend.Empty() { 1276 t.Fatalf("bad: %#v", actual) 1277 } 1278 } 1279 1280 // Write some state 1281 state = terraform.NewState() 1282 state.Lineage = "changing" 1283 s.WriteState(state) 1284 if err := s.PersistState(); err != nil { 1285 t.Fatalf("bad: %s", err) 1286 } 1287 1288 // Verify the state is where we expect 1289 { 1290 f, err := os.Open("local-state.tfstate") 1291 if err != nil { 1292 t.Fatalf("err: %s", err) 1293 } 1294 actual, err := terraform.ReadState(f) 1295 f.Close() 1296 if err != nil { 1297 t.Fatalf("err: %s", err) 1298 } 1299 1300 if actual.Lineage != state.Lineage { 1301 t.Fatalf("bad: %#v", actual) 1302 } 1303 } 1304 1305 // Verify no local state 1306 if _, err := os.Stat(DefaultStateFilename); err == nil { 1307 t.Fatal("file should not exist") 1308 } 1309 1310 // Verify no local backup 1311 if _, err := os.Stat(DefaultStateFilename + DefaultBackupExtension); err == nil { 1312 t.Fatal("file should not exist") 1313 } 1314 } 1315 1316 // Saved backend state, new config, legacy remote state 1317 func TestMetaBackend_configuredChangedLegacy(t *testing.T) { 1318 // Create a temporary working directory that is empty 1319 td := tempDir(t) 1320 copy.CopyDir(testFixturePath("backend-changed-with-legacy"), td) 1321 defer os.RemoveAll(td) 1322 defer testChdir(t, td)() 1323 1324 // Ask input 1325 defer testInteractiveInput(t, []string{"no", "no"})() 1326 1327 // Setup the meta 1328 m := testMetaBackend(t, nil) 1329 1330 // Get the backend 1331 b, err := m.Backend(&BackendOpts{Init: true}) 1332 if err != nil { 1333 t.Fatalf("bad: %s", err) 1334 } 1335 1336 // Check the state 1337 s, err := b.State() 1338 if err != nil { 1339 t.Fatalf("bad: %s", err) 1340 } 1341 if err := s.RefreshState(); err != nil { 1342 t.Fatalf("bad: %s", err) 1343 } 1344 state := s.State() 1345 if state != nil { 1346 t.Fatal("state should be nil") 1347 } 1348 1349 // Verify the default paths don't exist 1350 if _, err := os.Stat(DefaultStateFilename); err == nil { 1351 t.Fatal("file should not exist") 1352 } 1353 1354 // Verify a backup doesn't exist 1355 if _, err := os.Stat(DefaultStateFilename + DefaultBackupExtension); err == nil { 1356 t.Fatal("file should not exist") 1357 } 1358 1359 // Verify we have no configured legacy 1360 { 1361 path := filepath.Join(m.DataDir(), DefaultStateFilename) 1362 f, err := os.Open(path) 1363 if err != nil { 1364 t.Fatalf("err: %s", err) 1365 } 1366 actual, err := terraform.ReadState(f) 1367 f.Close() 1368 if err != nil { 1369 t.Fatalf("err: %s", err) 1370 } 1371 1372 if !actual.Remote.Empty() { 1373 t.Fatalf("bad: %#v", actual) 1374 } 1375 if actual.Backend.Empty() { 1376 t.Fatalf("bad: %#v", actual) 1377 } 1378 } 1379 1380 // Write some state 1381 state = terraform.NewState() 1382 state.Lineage = "changing" 1383 s.WriteState(state) 1384 if err := s.PersistState(); err != nil { 1385 t.Fatalf("bad: %s", err) 1386 } 1387 1388 // Verify the state is where we expect 1389 { 1390 f, err := os.Open("local-state-2.tfstate") 1391 if err != nil { 1392 t.Fatalf("err: %s", err) 1393 } 1394 actual, err := terraform.ReadState(f) 1395 f.Close() 1396 if err != nil { 1397 t.Fatalf("err: %s", err) 1398 } 1399 1400 if actual.Lineage != state.Lineage { 1401 t.Fatalf("bad: %#v", actual) 1402 } 1403 } 1404 1405 // Verify no local state 1406 if _, err := os.Stat(DefaultStateFilename); err == nil { 1407 t.Fatal("file should not exist") 1408 } 1409 1410 // Verify no local backup 1411 if _, err := os.Stat(DefaultStateFilename + DefaultBackupExtension); err == nil { 1412 t.Fatal("file should not exist") 1413 } 1414 } 1415 1416 // Saved backend state, new config, legacy remote state 1417 func TestMetaBackend_configuredChangedLegacyCopyBackend(t *testing.T) { 1418 // Create a temporary working directory that is empty 1419 td := tempDir(t) 1420 copy.CopyDir(testFixturePath("backend-changed-with-legacy"), td) 1421 defer os.RemoveAll(td) 1422 defer testChdir(t, td)() 1423 1424 // Ask input 1425 defer testInteractiveInput(t, []string{"yes", "yes", "no"})() 1426 1427 // Setup the meta 1428 m := testMetaBackend(t, nil) 1429 1430 // Get the backend 1431 b, err := m.Backend(&BackendOpts{Init: true}) 1432 if err != nil { 1433 t.Fatalf("bad: %s", err) 1434 } 1435 1436 // Check the state 1437 s, err := b.State() 1438 if err != nil { 1439 t.Fatalf("bad: %s", err) 1440 } 1441 if err := s.RefreshState(); err != nil { 1442 t.Fatalf("bad: %s", err) 1443 } 1444 state := s.State() 1445 if state == nil { 1446 t.Fatal("state is nil") 1447 } 1448 if state.Lineage != "configured" { 1449 t.Fatalf("bad: %#v", state) 1450 } 1451 1452 // Verify the default paths don't exist 1453 if _, err := os.Stat(DefaultStateFilename); err == nil { 1454 t.Fatal("file should not exist") 1455 } 1456 1457 // Verify a backup doesn't exist 1458 if _, err := os.Stat(DefaultStateFilename + DefaultBackupExtension); err == nil { 1459 t.Fatal("file should not exist") 1460 } 1461 1462 // Verify we have no configured legacy 1463 { 1464 path := filepath.Join(m.DataDir(), DefaultStateFilename) 1465 f, err := os.Open(path) 1466 if err != nil { 1467 t.Fatalf("err: %s", err) 1468 } 1469 actual, err := terraform.ReadState(f) 1470 f.Close() 1471 if err != nil { 1472 t.Fatalf("err: %s", err) 1473 } 1474 1475 if !actual.Remote.Empty() { 1476 t.Fatalf("bad: %#v", actual) 1477 } 1478 if actual.Backend.Empty() { 1479 t.Fatalf("bad: %#v", actual) 1480 } 1481 } 1482 1483 // Write some state 1484 state = terraform.NewState() 1485 state.Lineage = "changing" 1486 s.WriteState(state) 1487 if err := s.PersistState(); err != nil { 1488 t.Fatalf("bad: %s", err) 1489 } 1490 1491 // Verify the state is where we expect 1492 { 1493 f, err := os.Open("local-state-2.tfstate") 1494 if err != nil { 1495 t.Fatalf("err: %s", err) 1496 } 1497 actual, err := terraform.ReadState(f) 1498 f.Close() 1499 if err != nil { 1500 t.Fatalf("err: %s", err) 1501 } 1502 1503 if actual.Lineage != state.Lineage { 1504 t.Fatalf("bad: %#v", actual) 1505 } 1506 } 1507 1508 // Verify no local state 1509 if _, err := os.Stat(DefaultStateFilename); err == nil { 1510 t.Fatal("file should not exist") 1511 } 1512 1513 // Verify no local backup 1514 if _, err := os.Stat(DefaultStateFilename + DefaultBackupExtension); err == nil { 1515 t.Fatal("file should not exist") 1516 } 1517 } 1518 1519 // Saved backend state, new config, legacy remote state 1520 func TestMetaBackend_configuredChangedLegacyCopyLegacy(t *testing.T) { 1521 // Create a temporary working directory that is empty 1522 td := tempDir(t) 1523 copy.CopyDir(testFixturePath("backend-changed-with-legacy"), td) 1524 defer os.RemoveAll(td) 1525 defer testChdir(t, td)() 1526 1527 // Ask input 1528 defer testInteractiveInput(t, []string{"no", "yes", "yes"})() 1529 1530 // Setup the meta 1531 m := testMetaBackend(t, nil) 1532 1533 // Get the backend 1534 b, err := m.Backend(&BackendOpts{Init: true}) 1535 if err != nil { 1536 t.Fatalf("bad: %s", err) 1537 } 1538 1539 // Check the state 1540 s, err := b.State() 1541 if err != nil { 1542 t.Fatalf("bad: %s", err) 1543 } 1544 if err := s.RefreshState(); err != nil { 1545 t.Fatalf("bad: %s", err) 1546 } 1547 state := s.State() 1548 if state == nil { 1549 t.Fatal("state is nil") 1550 } 1551 if state.Lineage != "legacy" { 1552 t.Fatalf("bad: %#v", state) 1553 } 1554 1555 // Verify the default paths don't exist 1556 if _, err := os.Stat(DefaultStateFilename); err == nil { 1557 t.Fatal("file should not exist") 1558 } 1559 1560 // Verify a backup doesn't exist 1561 if _, err := os.Stat(DefaultStateFilename + DefaultBackupExtension); err == nil { 1562 t.Fatal("file should not exist") 1563 } 1564 1565 // Verify we have no configured legacy 1566 { 1567 path := filepath.Join(m.DataDir(), DefaultStateFilename) 1568 f, err := os.Open(path) 1569 if err != nil { 1570 t.Fatalf("err: %s", err) 1571 } 1572 actual, err := terraform.ReadState(f) 1573 f.Close() 1574 if err != nil { 1575 t.Fatalf("err: %s", err) 1576 } 1577 1578 if !actual.Remote.Empty() { 1579 t.Fatalf("bad: %#v", actual) 1580 } 1581 if actual.Backend.Empty() { 1582 t.Fatalf("bad: %#v", actual) 1583 } 1584 } 1585 1586 // Write some state 1587 state = terraform.NewState() 1588 state.Lineage = "changing" 1589 s.WriteState(state) 1590 if err := s.PersistState(); err != nil { 1591 t.Fatalf("bad: %s", err) 1592 } 1593 1594 // Verify the state is where we expect 1595 { 1596 f, err := os.Open("local-state-2.tfstate") 1597 if err != nil { 1598 t.Fatalf("err: %s", err) 1599 } 1600 actual, err := terraform.ReadState(f) 1601 f.Close() 1602 if err != nil { 1603 t.Fatalf("err: %s", err) 1604 } 1605 1606 if actual.Lineage != state.Lineage { 1607 t.Fatalf("bad: %#v", actual) 1608 } 1609 } 1610 1611 // Verify no local state 1612 if _, err := os.Stat(DefaultStateFilename); err == nil { 1613 t.Fatal("file should not exist") 1614 } 1615 1616 // Verify no local backup 1617 if _, err := os.Stat(DefaultStateFilename + DefaultBackupExtension); err == nil { 1618 t.Fatal("file should not exist") 1619 } 1620 } 1621 1622 // Saved backend state, new config, legacy remote state 1623 func TestMetaBackend_configuredChangedLegacyCopyBoth(t *testing.T) { 1624 // Create a temporary working directory that is empty 1625 td := tempDir(t) 1626 copy.CopyDir(testFixturePath("backend-changed-with-legacy"), td) 1627 defer os.RemoveAll(td) 1628 defer testChdir(t, td)() 1629 1630 // Ask input 1631 defer testInteractiveInput(t, []string{"yes", "yes", "yes", "yes"})() 1632 1633 // Setup the meta 1634 m := testMetaBackend(t, nil) 1635 1636 // Get the backend 1637 b, err := m.Backend(&BackendOpts{Init: true}) 1638 if err != nil { 1639 t.Fatalf("bad: %s", err) 1640 } 1641 1642 // Check the state 1643 s, err := b.State() 1644 if err != nil { 1645 t.Fatalf("bad: %s", err) 1646 } 1647 if err := s.RefreshState(); err != nil { 1648 t.Fatalf("bad: %s", err) 1649 } 1650 state := s.State() 1651 if state == nil { 1652 t.Fatal("state is nil") 1653 } 1654 if state.Lineage != "legacy" { 1655 t.Fatalf("bad: %#v", state) 1656 } 1657 1658 // Verify the default paths don't exist 1659 if _, err := os.Stat(DefaultStateFilename); err == nil { 1660 t.Fatal("file should not exist") 1661 } 1662 1663 // Verify a backup doesn't exist 1664 if _, err := os.Stat(DefaultStateFilename + DefaultBackupExtension); err == nil { 1665 t.Fatal("file should not exist") 1666 } 1667 1668 // Verify we have no configured legacy 1669 { 1670 path := filepath.Join(m.DataDir(), DefaultStateFilename) 1671 f, err := os.Open(path) 1672 if err != nil { 1673 t.Fatalf("err: %s", err) 1674 } 1675 actual, err := terraform.ReadState(f) 1676 f.Close() 1677 if err != nil { 1678 t.Fatalf("err: %s", err) 1679 } 1680 1681 if !actual.Remote.Empty() { 1682 t.Fatalf("bad: %#v", actual) 1683 } 1684 if actual.Backend.Empty() { 1685 t.Fatalf("bad: %#v", actual) 1686 } 1687 } 1688 1689 // Write some state 1690 state = terraform.NewState() 1691 state.Lineage = "changing" 1692 s.WriteState(state) 1693 if err := s.PersistState(); err != nil { 1694 t.Fatalf("bad: %s", err) 1695 } 1696 1697 // Verify the state is where we expect 1698 { 1699 f, err := os.Open("local-state-2.tfstate") 1700 if err != nil { 1701 t.Fatalf("err: %s", err) 1702 } 1703 actual, err := terraform.ReadState(f) 1704 f.Close() 1705 if err != nil { 1706 t.Fatalf("err: %s", err) 1707 } 1708 1709 if actual.Lineage != state.Lineage { 1710 t.Fatalf("bad: %#v", actual) 1711 } 1712 } 1713 1714 // Verify no local state 1715 if _, err := os.Stat(DefaultStateFilename); err == nil { 1716 t.Fatal("file should not exist") 1717 } 1718 1719 // Verify no local backup 1720 if _, err := os.Stat(DefaultStateFilename + DefaultBackupExtension); err == nil { 1721 t.Fatal("file should not exist") 1722 } 1723 } 1724 1725 // Saved backend state, unset config, legacy remote state 1726 func TestMetaBackend_configuredUnsetWithLegacyNoCopy(t *testing.T) { 1727 // Create a temporary working directory that is empty 1728 td := tempDir(t) 1729 copy.CopyDir(testFixturePath("backend-unset-with-legacy"), td) 1730 defer os.RemoveAll(td) 1731 defer testChdir(t, td)() 1732 1733 // Ask input 1734 defer testInteractiveInput(t, []string{"no", "no"})() 1735 1736 // Setup the meta 1737 m := testMetaBackend(t, nil) 1738 1739 // Get the backend 1740 b, err := m.Backend(&BackendOpts{Init: true}) 1741 if err != nil { 1742 t.Fatalf("bad: %s", err) 1743 } 1744 1745 // Check the state 1746 s, err := b.State() 1747 if err != nil { 1748 t.Fatalf("bad: %s", err) 1749 } 1750 if err := s.RefreshState(); err != nil { 1751 t.Fatalf("bad: %s", err) 1752 } 1753 state := s.State() 1754 if state != nil { 1755 t.Fatal("state should be nil") 1756 } 1757 1758 // Verify the default paths dont exist since we had no state 1759 if !isEmptyState(DefaultStateFilename) { 1760 t.Fatal("state should be empty") 1761 } 1762 1763 // Verify a backup doesn't exist 1764 if !isEmptyState(DefaultStateFilename + DefaultBackupExtension) { 1765 t.Fatal("backup should be empty") 1766 } 1767 1768 // Verify we have no configured backend/legacy 1769 path := filepath.Join(m.DataDir(), DefaultStateFilename) 1770 if _, err := os.Stat(path); err == nil { 1771 f, err := os.Open(path) 1772 if err != nil { 1773 t.Fatalf("err: %s", err) 1774 } 1775 actual, err := terraform.ReadState(f) 1776 f.Close() 1777 if err != nil { 1778 t.Fatalf("err: %s", err) 1779 } 1780 1781 if !actual.Remote.Empty() { 1782 t.Fatalf("bad: %#v", actual) 1783 } 1784 if !actual.Backend.Empty() { 1785 t.Fatalf("bad: %#v", actual) 1786 } 1787 } 1788 1789 // Write some state 1790 state = terraform.NewState() 1791 state.Lineage = "changing" 1792 s.WriteState(state) 1793 if err := s.PersistState(); err != nil { 1794 t.Fatalf("bad: %s", err) 1795 } 1796 1797 // Verify the state is where we expect 1798 { 1799 f, err := os.Open(DefaultStateFilename) 1800 if err != nil { 1801 t.Fatalf("err: %s", err) 1802 } 1803 actual, err := terraform.ReadState(f) 1804 f.Close() 1805 if err != nil { 1806 t.Fatalf("err: %s", err) 1807 } 1808 1809 if actual.Lineage != state.Lineage { 1810 t.Fatalf("bad: %#v", actual) 1811 } 1812 } 1813 } 1814 1815 // Saved backend state, unset config, legacy remote state 1816 func TestMetaBackend_configuredUnsetWithLegacyCopyBackend(t *testing.T) { 1817 // Create a temporary working directory that is empty 1818 td := tempDir(t) 1819 copy.CopyDir(testFixturePath("backend-unset-with-legacy"), td) 1820 defer os.RemoveAll(td) 1821 defer testChdir(t, td)() 1822 1823 // Ask input 1824 defer testInteractiveInput(t, []string{"yes", "yes", "no"})() 1825 1826 // Setup the meta 1827 m := testMetaBackend(t, nil) 1828 1829 // Get the backend 1830 b, err := m.Backend(&BackendOpts{Init: true}) 1831 if err != nil { 1832 t.Fatalf("bad: %s", err) 1833 } 1834 1835 // Check the state 1836 s, err := b.State() 1837 if err != nil { 1838 t.Fatalf("bad: %s", err) 1839 } 1840 if err := s.RefreshState(); err != nil { 1841 t.Fatalf("bad: %s", err) 1842 } 1843 state := s.State() 1844 if state == nil { 1845 t.Fatal("state is nil") 1846 } 1847 if state.Lineage != "backend" { 1848 t.Fatalf("bad: %#v", state) 1849 } 1850 1851 // Verify the default paths exist 1852 if isEmptyState(DefaultStateFilename) { 1853 t.Fatalf("default state was empty") 1854 } 1855 1856 // Verify a backup doesn't exist 1857 if !isEmptyState(DefaultStateFilename + DefaultBackupExtension) { 1858 t.Fatal("backupstate should be empty") 1859 } 1860 1861 // Verify we have no configured backend/legacy 1862 path := filepath.Join(m.DataDir(), DefaultStateFilename) 1863 if _, err := os.Stat(path); err == nil { 1864 f, err := os.Open(path) 1865 if err != nil { 1866 t.Fatalf("err: %s", err) 1867 } 1868 actual, err := terraform.ReadState(f) 1869 f.Close() 1870 if err != nil { 1871 t.Fatalf("err: %s", err) 1872 } 1873 1874 if !actual.Remote.Empty() { 1875 t.Fatalf("bad: %#v", actual) 1876 } 1877 if !actual.Backend.Empty() { 1878 t.Fatalf("bad: %#v", actual) 1879 } 1880 } 1881 1882 // Write some state 1883 state = terraform.NewState() 1884 state.Lineage = "changing" 1885 s.WriteState(state) 1886 if err := s.PersistState(); err != nil { 1887 t.Fatalf("bad: %s", err) 1888 } 1889 1890 // Verify the state is where we expect 1891 { 1892 f, err := os.Open(DefaultStateFilename) 1893 if err != nil { 1894 t.Fatalf("err: %s", err) 1895 } 1896 actual, err := terraform.ReadState(f) 1897 f.Close() 1898 if err != nil { 1899 t.Fatalf("err: %s", err) 1900 } 1901 1902 if actual.Lineage != state.Lineage { 1903 t.Fatalf("bad: %#v", actual) 1904 } 1905 } 1906 1907 // Verify a local backup 1908 if isEmptyState(DefaultStateFilename + DefaultBackupExtension) { 1909 t.Fatal("backup is empty") 1910 } 1911 } 1912 1913 // Saved backend state, unset config, legacy remote state 1914 func TestMetaBackend_configuredUnsetWithLegacyCopyLegacy(t *testing.T) { 1915 // Create a temporary working directory that is empty 1916 td := tempDir(t) 1917 copy.CopyDir(testFixturePath("backend-unset-with-legacy"), td) 1918 defer os.RemoveAll(td) 1919 defer testChdir(t, td)() 1920 1921 // Ask input 1922 defer testInteractiveInput(t, []string{"no", "yes", "yes"})() 1923 1924 // Setup the meta 1925 m := testMetaBackend(t, nil) 1926 1927 // Get the backend 1928 b, err := m.Backend(&BackendOpts{Init: true}) 1929 if err != nil { 1930 t.Fatalf("bad: %s", err) 1931 } 1932 1933 // Check the state 1934 s, err := b.State() 1935 if err != nil { 1936 t.Fatalf("bad: %s", err) 1937 } 1938 if err := s.RefreshState(); err != nil { 1939 t.Fatalf("bad: %s", err) 1940 } 1941 state := s.State() 1942 if state == nil { 1943 t.Fatal("state is nil") 1944 } 1945 if state.Lineage != "legacy" { 1946 t.Fatalf("bad: %#v", state) 1947 } 1948 1949 // Verify the default paths exist 1950 if isEmptyState(DefaultStateFilename) { 1951 t.Fatalf("default state was empty") 1952 } 1953 1954 // Verify a backup doesn't exist 1955 if !isEmptyState(DefaultStateFilename + DefaultBackupExtension) { 1956 t.Fatal("backupstate should be empty") 1957 } 1958 1959 // Verify we have no configured backend/legacy 1960 path := filepath.Join(m.DataDir(), DefaultStateFilename) 1961 if _, err := os.Stat(path); err == nil { 1962 f, err := os.Open(path) 1963 if err != nil { 1964 t.Fatalf("err: %s", err) 1965 } 1966 actual, err := terraform.ReadState(f) 1967 f.Close() 1968 if err != nil { 1969 t.Fatalf("err: %s", err) 1970 } 1971 1972 if !actual.Remote.Empty() { 1973 t.Fatalf("bad: %#v", actual) 1974 } 1975 if !actual.Backend.Empty() { 1976 t.Fatalf("bad: %#v", actual) 1977 } 1978 } 1979 1980 // Write some state 1981 state = terraform.NewState() 1982 state.Lineage = "changing" 1983 s.WriteState(state) 1984 if err := s.PersistState(); err != nil { 1985 t.Fatalf("bad: %s", err) 1986 } 1987 1988 // Verify the state is where we expect 1989 { 1990 f, err := os.Open(DefaultStateFilename) 1991 if err != nil { 1992 t.Fatalf("err: %s", err) 1993 } 1994 actual, err := terraform.ReadState(f) 1995 f.Close() 1996 if err != nil { 1997 t.Fatalf("err: %s", err) 1998 } 1999 2000 if actual.Lineage != state.Lineage { 2001 t.Fatalf("bad: %#v", actual) 2002 } 2003 } 2004 2005 // Verify a local backup 2006 if isEmptyState(DefaultStateFilename + DefaultBackupExtension) { 2007 t.Fatal("backup is empty") 2008 } 2009 } 2010 2011 // Saved backend state, unset config, legacy remote state 2012 func TestMetaBackend_configuredUnsetWithLegacyCopyBoth(t *testing.T) { 2013 // Create a temporary working directory that is empty 2014 td := tempDir(t) 2015 copy.CopyDir(testFixturePath("backend-unset-with-legacy"), td) 2016 defer os.RemoveAll(td) 2017 defer testChdir(t, td)() 2018 2019 // Ask input 2020 defer testInteractiveInput(t, []string{"yes", "yes", "yes", "yes"})() 2021 2022 // Setup the meta 2023 m := testMetaBackend(t, nil) 2024 2025 // Get the backend 2026 b, err := m.Backend(&BackendOpts{Init: true}) 2027 if err != nil { 2028 t.Fatalf("bad: %s", err) 2029 } 2030 2031 // Check the state 2032 s, err := b.State() 2033 if err != nil { 2034 t.Fatalf("bad: %s", err) 2035 } 2036 if err := s.RefreshState(); err != nil { 2037 t.Fatalf("bad: %s", err) 2038 } 2039 state := s.State() 2040 if state == nil { 2041 t.Fatal("state is nil") 2042 } 2043 if state.Lineage != "legacy" { 2044 t.Fatalf("bad: %#v", state) 2045 } 2046 2047 // Verify the default paths exist 2048 if isEmptyState(DefaultStateFilename) { 2049 t.Fatal("state is empty") 2050 } 2051 2052 // Verify a backup exists 2053 if isEmptyState(DefaultStateFilename + DefaultBackupExtension) { 2054 t.Fatal("backup is empty") 2055 } 2056 2057 // Verify we have no configured backend/legacy 2058 path := filepath.Join(m.DataDir(), DefaultStateFilename) 2059 if _, err := os.Stat(path); err == nil { 2060 f, err := os.Open(path) 2061 if err != nil { 2062 t.Fatalf("err: %s", err) 2063 } 2064 actual, err := terraform.ReadState(f) 2065 f.Close() 2066 if err != nil { 2067 t.Fatalf("err: %s", err) 2068 } 2069 2070 if !actual.Remote.Empty() { 2071 t.Fatalf("bad: %#v", actual) 2072 } 2073 if !actual.Backend.Empty() { 2074 t.Fatalf("bad: %#v", actual) 2075 } 2076 } 2077 2078 // Write some state 2079 state = terraform.NewState() 2080 state.Lineage = "changing" 2081 s.WriteState(state) 2082 if err := s.PersistState(); err != nil { 2083 t.Fatalf("bad: %s", err) 2084 } 2085 2086 // Verify the state is where we expect 2087 { 2088 f, err := os.Open(DefaultStateFilename) 2089 if err != nil { 2090 t.Fatalf("err: %s", err) 2091 } 2092 actual, err := terraform.ReadState(f) 2093 f.Close() 2094 if err != nil { 2095 t.Fatalf("err: %s", err) 2096 } 2097 2098 if actual.Lineage != state.Lineage { 2099 t.Fatalf("bad: %#v", actual) 2100 } 2101 } 2102 2103 // Verify a local backup 2104 if isEmptyState(DefaultStateFilename + DefaultBackupExtension) { 2105 t.Fatal("backup is empty") 2106 } 2107 } 2108 2109 // A plan that has no backend config 2110 func TestMetaBackend_planLocal(t *testing.T) { 2111 // Create a temporary working directory that is empty 2112 td := tempDir(t) 2113 copy.CopyDir(testFixturePath("backend-plan-local"), td) 2114 defer os.RemoveAll(td) 2115 defer testChdir(t, td)() 2116 2117 // Create the plan 2118 plan := &terraform.Plan{ 2119 Module: testModule(t, "backend-plan-local"), 2120 State: nil, 2121 } 2122 2123 // Setup the meta 2124 m := testMetaBackend(t, nil) 2125 2126 // Get the backend 2127 b, err := m.Backend(&BackendOpts{Plan: plan}) 2128 if err != nil { 2129 t.Fatalf("bad: %s", err) 2130 } 2131 2132 // Check the state 2133 s, err := b.State() 2134 if err != nil { 2135 t.Fatalf("bad: %s", err) 2136 } 2137 if err := s.RefreshState(); err != nil { 2138 t.Fatalf("bad: %s", err) 2139 } 2140 state := s.State() 2141 if state != nil { 2142 t.Fatalf("state should be nil: %#v", state) 2143 } 2144 2145 // Verify the default path doens't exist 2146 if !isEmptyState(DefaultStateFilename) { 2147 t.Fatal("expected empty state") 2148 } 2149 2150 // Verify a backup doesn't exists 2151 if !isEmptyState(DefaultStateFilename + DefaultBackupExtension) { 2152 t.Fatal("expected empty backup") 2153 } 2154 2155 // Verify we have no configured backend/legacy 2156 path := filepath.Join(m.DataDir(), DefaultStateFilename) 2157 if _, err := os.Stat(path); err == nil { 2158 t.Fatalf("should not have backend configured") 2159 } 2160 2161 // Write some state 2162 state = terraform.NewState() 2163 state.Lineage = "changing" 2164 s.WriteState(state) 2165 if err := s.PersistState(); err != nil { 2166 t.Fatalf("bad: %s", err) 2167 } 2168 2169 // Verify the state is where we expect 2170 { 2171 f, err := os.Open(DefaultStateFilename) 2172 if err != nil { 2173 t.Fatalf("err: %s", err) 2174 } 2175 actual, err := terraform.ReadState(f) 2176 f.Close() 2177 if err != nil { 2178 t.Fatalf("err: %s", err) 2179 } 2180 2181 if actual.Lineage != state.Lineage { 2182 t.Fatalf("bad: %#v", actual) 2183 } 2184 } 2185 2186 // Verify no local backup 2187 if !isEmptyState(DefaultStateFilename + DefaultBackupExtension) { 2188 t.Fatalf("backup state should be empty") 2189 } 2190 } 2191 2192 // A plan with a custom state save path 2193 func TestMetaBackend_planLocalStatePath(t *testing.T) { 2194 // Create a temporary working directory that is empty 2195 td := tempDir(t) 2196 copy.CopyDir(testFixturePath("backend-plan-local"), td) 2197 defer os.RemoveAll(td) 2198 defer testChdir(t, td)() 2199 2200 // Create our state 2201 original := testState() 2202 original.Lineage = "hello" 2203 2204 // Create the plan 2205 plan := &terraform.Plan{ 2206 Module: testModule(t, "backend-plan-local"), 2207 State: original, 2208 } 2209 2210 // Create an alternate output path 2211 statePath := "foo.tfstate" 2212 2213 // put a initial state there that needs to be backed up 2214 err := (&state.LocalState{Path: statePath}).WriteState(original) 2215 if err != nil { 2216 t.Fatal(err) 2217 } 2218 2219 // Setup the meta 2220 m := testMetaBackend(t, nil) 2221 m.stateOutPath = statePath 2222 2223 // Get the backend 2224 b, err := m.Backend(&BackendOpts{Plan: plan}) 2225 if err != nil { 2226 t.Fatalf("bad: %s", err) 2227 } 2228 2229 // Check the state 2230 s, err := b.State() 2231 if err != nil { 2232 t.Fatalf("bad: %s", err) 2233 } 2234 if err := s.RefreshState(); err != nil { 2235 t.Fatalf("bad: %s", err) 2236 } 2237 state := s.State() 2238 if state == nil { 2239 t.Fatal("state is nil") 2240 } 2241 if state.Lineage != "hello" { 2242 t.Fatalf("bad: %#v", state) 2243 } 2244 2245 // Verify the default path doesn't exist 2246 if _, err := os.Stat(DefaultStateFilename); err == nil { 2247 t.Fatalf("err: %s", err) 2248 } 2249 2250 // Verify a backup doesn't exists 2251 if _, err := os.Stat(DefaultStateFilename + DefaultBackupExtension); err == nil { 2252 t.Fatal("file should not exist") 2253 } 2254 2255 // Verify we have no configured backend/legacy 2256 path := filepath.Join(m.DataDir(), DefaultStateFilename) 2257 if _, err := os.Stat(path); err == nil { 2258 t.Fatalf("should not have backend configured") 2259 } 2260 2261 // Write some state 2262 state = terraform.NewState() 2263 state.Lineage = "changing" 2264 s.WriteState(state) 2265 if err := s.PersistState(); err != nil { 2266 t.Fatalf("bad: %s", err) 2267 } 2268 2269 // Verify the state is where we expect 2270 { 2271 f, err := os.Open(statePath) 2272 if err != nil { 2273 t.Fatalf("err: %s", err) 2274 } 2275 actual, err := terraform.ReadState(f) 2276 f.Close() 2277 if err != nil { 2278 t.Fatalf("err: %s", err) 2279 } 2280 2281 if actual.Lineage != state.Lineage { 2282 t.Fatalf("bad: %#v", actual) 2283 } 2284 } 2285 2286 // Verify we have a backup 2287 if isEmptyState(statePath + DefaultBackupExtension) { 2288 t.Fatal("backup is empty") 2289 } 2290 } 2291 2292 // A plan that has no backend config, matching local state 2293 func TestMetaBackend_planLocalMatch(t *testing.T) { 2294 // Create a temporary working directory that is empty 2295 td := tempDir(t) 2296 copy.CopyDir(testFixturePath("backend-plan-local-match"), td) 2297 defer os.RemoveAll(td) 2298 defer testChdir(t, td)() 2299 2300 // Create the plan 2301 plan := &terraform.Plan{ 2302 Module: testModule(t, "backend-plan-local-match"), 2303 State: testStateRead(t, DefaultStateFilename), 2304 } 2305 2306 // Setup the meta 2307 m := testMetaBackend(t, nil) 2308 2309 // Get the backend 2310 b, err := m.Backend(&BackendOpts{Plan: plan}) 2311 if err != nil { 2312 t.Fatalf("bad: %s", err) 2313 } 2314 2315 // Check the state 2316 s, err := b.State() 2317 if err != nil { 2318 t.Fatalf("bad: %s", err) 2319 } 2320 if err := s.RefreshState(); err != nil { 2321 t.Fatalf("bad: %s", err) 2322 } 2323 state := s.State() 2324 if state == nil { 2325 t.Fatal("should is nil") 2326 } 2327 if state.Lineage != "hello" { 2328 t.Fatalf("bad: %#v", state) 2329 } 2330 2331 // Verify the default path 2332 if isEmptyState(DefaultStateFilename) { 2333 t.Fatal("state is empty") 2334 } 2335 2336 // Verify a backup exists 2337 if _, err := os.Stat(DefaultStateFilename + DefaultBackupExtension); err != nil { 2338 t.Fatalf("err: %s", err) 2339 } 2340 2341 // Verify we have no configured backend/legacy 2342 path := filepath.Join(m.DataDir(), DefaultStateFilename) 2343 if _, err := os.Stat(path); err == nil { 2344 t.Fatalf("should not have backend configured") 2345 } 2346 2347 // Write some state 2348 state = terraform.NewState() 2349 state.Lineage = "changing" 2350 s.WriteState(state) 2351 if err := s.PersistState(); err != nil { 2352 t.Fatalf("bad: %s", err) 2353 } 2354 2355 // Verify the state is where we expect 2356 { 2357 f, err := os.Open(DefaultStateFilename) 2358 if err != nil { 2359 t.Fatalf("err: %s", err) 2360 } 2361 actual, err := terraform.ReadState(f) 2362 f.Close() 2363 if err != nil { 2364 t.Fatalf("err: %s", err) 2365 } 2366 2367 if actual.Lineage != state.Lineage { 2368 t.Fatalf("bad: %#v", actual) 2369 } 2370 } 2371 2372 // Verify local backup 2373 if isEmptyState(DefaultStateFilename + DefaultBackupExtension) { 2374 t.Fatal("backup is empty") 2375 } 2376 } 2377 2378 // A plan that has no backend config, mismatched lineage 2379 func TestMetaBackend_planLocalMismatchLineage(t *testing.T) { 2380 // Create a temporary working directory that is empty 2381 td := tempDir(t) 2382 copy.CopyDir(testFixturePath("backend-plan-local-mismatch-lineage"), td) 2383 defer os.RemoveAll(td) 2384 defer testChdir(t, td)() 2385 2386 // Save the original 2387 original := testStateRead(t, DefaultStateFilename) 2388 2389 // Change the lineage 2390 planState := testStateRead(t, DefaultStateFilename) 2391 planState.Lineage = "bad" 2392 2393 // Create the plan 2394 plan := &terraform.Plan{ 2395 Module: testModule(t, "backend-plan-local-mismatch-lineage"), 2396 State: planState, 2397 } 2398 2399 // Setup the meta 2400 m := testMetaBackend(t, nil) 2401 2402 // Get the backend 2403 _, err := m.Backend(&BackendOpts{Plan: plan}) 2404 if err == nil { 2405 t.Fatal("should have error") 2406 } 2407 if !strings.Contains(err.Error(), "lineage") { 2408 t.Fatalf("bad: %s", err) 2409 } 2410 2411 // Verify our local state didn't change 2412 actual := testStateRead(t, DefaultStateFilename) 2413 if !actual.Equal(original) { 2414 t.Fatalf("bad: %#v", actual) 2415 } 2416 2417 // Verify a backup doesn't exists 2418 if _, err := os.Stat(DefaultStateFilename + DefaultBackupExtension); err == nil { 2419 t.Fatal("file should not exist") 2420 } 2421 2422 // Verify we have no configured backend/legacy 2423 path := filepath.Join(m.DataDir(), DefaultStateFilename) 2424 if _, err := os.Stat(path); err == nil { 2425 t.Fatalf("should not have backend configured") 2426 } 2427 } 2428 2429 // A plan that has no backend config, newer local 2430 func TestMetaBackend_planLocalNewer(t *testing.T) { 2431 // Create a temporary working directory that is empty 2432 td := tempDir(t) 2433 copy.CopyDir(testFixturePath("backend-plan-local-newer"), td) 2434 defer os.RemoveAll(td) 2435 defer testChdir(t, td)() 2436 2437 // Save the original 2438 original := testStateRead(t, DefaultStateFilename) 2439 2440 // Change the serial 2441 planState := testStateRead(t, DefaultStateFilename) 2442 planState.Serial = 7 2443 planState.RootModule().Dependencies = []string{"foo"} 2444 2445 // Create the plan 2446 plan := &terraform.Plan{ 2447 Module: testModule(t, "backend-plan-local-newer"), 2448 State: planState, 2449 } 2450 2451 // Setup the meta 2452 m := testMetaBackend(t, nil) 2453 2454 // Get the backend 2455 _, err := m.Backend(&BackendOpts{Plan: plan}) 2456 if err == nil { 2457 t.Fatal("should have error") 2458 } 2459 if !strings.Contains(err.Error(), "older") { 2460 t.Fatalf("bad: %s", err) 2461 } 2462 2463 // Verify our local state didn't change 2464 actual := testStateRead(t, DefaultStateFilename) 2465 if !actual.Equal(original) { 2466 t.Fatalf("bad: %#v", actual) 2467 } 2468 2469 // Verify a backup doesn't exists 2470 if _, err := os.Stat(DefaultStateFilename + DefaultBackupExtension); err == nil { 2471 t.Fatal("file should not exist") 2472 } 2473 2474 // Verify we have no configured backend/legacy 2475 path := filepath.Join(m.DataDir(), DefaultStateFilename) 2476 if _, err := os.Stat(path); err == nil { 2477 t.Fatalf("should not have backend configured") 2478 } 2479 } 2480 2481 // A plan that has a backend in an empty dir 2482 func TestMetaBackend_planBackendEmptyDir(t *testing.T) { 2483 // Create a temporary working directory that is empty 2484 td := tempDir(t) 2485 copy.CopyDir(testFixturePath("backend-plan-backend-empty"), td) 2486 defer os.RemoveAll(td) 2487 defer testChdir(t, td)() 2488 2489 // Get the state for the plan by getting the real state and 2490 // adding the backend config to it. 2491 original := testStateRead(t, filepath.Join( 2492 testFixturePath("backend-plan-backend-empty-config"), 2493 "local-state.tfstate")) 2494 backendState := testStateRead(t, filepath.Join( 2495 testFixturePath("backend-plan-backend-empty-config"), 2496 DefaultDataDir, DefaultStateFilename)) 2497 planState := original.DeepCopy() 2498 planState.Backend = backendState.Backend 2499 2500 // Create the plan 2501 plan := &terraform.Plan{ 2502 Module: testModule(t, "backend-plan-backend-empty-config"), 2503 State: planState, 2504 } 2505 2506 // Setup the meta 2507 m := testMetaBackend(t, nil) 2508 2509 // Get the backend 2510 b, err := m.Backend(&BackendOpts{Plan: plan}) 2511 if err != nil { 2512 t.Fatalf("bad: %s", err) 2513 } 2514 2515 // Check the state 2516 s, err := b.State() 2517 if err != nil { 2518 t.Fatalf("bad: %s", err) 2519 } 2520 if err := s.RefreshState(); err != nil { 2521 t.Fatalf("bad: %s", err) 2522 } 2523 state := s.State() 2524 if state == nil { 2525 t.Fatal("should is nil") 2526 } 2527 if state.Lineage != "hello" { 2528 t.Fatalf("bad: %#v", state) 2529 } 2530 2531 // Verify the default path doesn't exist 2532 if !isEmptyState(DefaultStateFilename) { 2533 t.Fatal("state is not empty") 2534 } 2535 2536 // Verify a backup doesn't exist 2537 if !isEmptyState(DefaultStateFilename + DefaultBackupExtension) { 2538 t.Fatal("backup is not empty") 2539 } 2540 2541 // Verify we have no configured backend/legacy 2542 path := filepath.Join(m.DataDir(), DefaultStateFilename) 2543 if _, err := os.Stat(path); err == nil { 2544 t.Fatalf("should not have backend configured") 2545 } 2546 2547 // Write some state 2548 state = terraform.NewState() 2549 state.Lineage = "changing" 2550 s.WriteState(state) 2551 if err := s.PersistState(); err != nil { 2552 t.Fatalf("bad: %s", err) 2553 } 2554 2555 // Verify the state is where we expect 2556 { 2557 f, err := os.Open("local-state.tfstate") 2558 if err != nil { 2559 t.Fatalf("err: %s", err) 2560 } 2561 actual, err := terraform.ReadState(f) 2562 f.Close() 2563 if err != nil { 2564 t.Fatalf("err: %s", err) 2565 } 2566 2567 if actual.Lineage != state.Lineage { 2568 t.Fatalf("bad: %#v", actual) 2569 } 2570 } 2571 2572 // Verify no default path 2573 if _, err := os.Stat(DefaultStateFilename); err == nil { 2574 t.Fatal("file should not exist") 2575 } 2576 2577 // Verify no local backup 2578 if _, err := os.Stat(DefaultStateFilename + DefaultBackupExtension); err == nil { 2579 t.Fatal("file should not exist") 2580 } 2581 } 2582 2583 // A plan that has a backend with matching state 2584 func TestMetaBackend_planBackendMatch(t *testing.T) { 2585 // Create a temporary working directory that is empty 2586 td := tempDir(t) 2587 copy.CopyDir(testFixturePath("backend-plan-backend-match"), td) 2588 defer os.RemoveAll(td) 2589 defer testChdir(t, td)() 2590 2591 // Get the state for the plan by getting the real state and 2592 // adding the backend config to it. 2593 original := testStateRead(t, filepath.Join( 2594 testFixturePath("backend-plan-backend-empty-config"), 2595 "local-state.tfstate")) 2596 backendState := testStateRead(t, filepath.Join( 2597 testFixturePath("backend-plan-backend-empty-config"), 2598 DefaultDataDir, DefaultStateFilename)) 2599 planState := original.DeepCopy() 2600 planState.Backend = backendState.Backend 2601 2602 // Create the plan 2603 plan := &terraform.Plan{ 2604 Module: testModule(t, "backend-plan-backend-empty-config"), 2605 State: planState, 2606 } 2607 2608 // Setup the meta 2609 m := testMetaBackend(t, nil) 2610 2611 // Get the backend 2612 b, err := m.Backend(&BackendOpts{Plan: plan}) 2613 if err != nil { 2614 t.Fatalf("bad: %s", err) 2615 } 2616 2617 // Check the state 2618 s, err := b.State() 2619 if err != nil { 2620 t.Fatalf("bad: %s", err) 2621 } 2622 if err := s.RefreshState(); err != nil { 2623 t.Fatalf("bad: %s", err) 2624 } 2625 state := s.State() 2626 if state == nil { 2627 t.Fatal("should is nil") 2628 } 2629 if state.Lineage != "hello" { 2630 t.Fatalf("bad: %#v", state) 2631 } 2632 2633 // Verify the default path exists 2634 if _, err := os.Stat(DefaultStateFilename); err == nil { 2635 t.Fatal("file should not exist") 2636 } 2637 2638 // Verify a backup doesn't exist 2639 if _, err := os.Stat(DefaultStateFilename + DefaultBackupExtension); err == nil { 2640 t.Fatal("file should not exist") 2641 } 2642 2643 // Verify we have no configured backend/legacy 2644 path := filepath.Join(m.DataDir(), DefaultStateFilename) 2645 if _, err := os.Stat(path); err == nil { 2646 t.Fatalf("should not have backend configured") 2647 } 2648 2649 // Write some state 2650 state = terraform.NewState() 2651 state.Lineage = "changing" 2652 s.WriteState(state) 2653 if err := s.PersistState(); err != nil { 2654 t.Fatalf("bad: %s", err) 2655 } 2656 2657 // Verify the state is where we expect 2658 { 2659 f, err := os.Open("local-state.tfstate") 2660 if err != nil { 2661 t.Fatalf("err: %s", err) 2662 } 2663 actual, err := terraform.ReadState(f) 2664 f.Close() 2665 if err != nil { 2666 t.Fatalf("err: %s", err) 2667 } 2668 2669 if actual.Lineage != state.Lineage { 2670 t.Fatalf("bad: %#v", actual) 2671 } 2672 } 2673 2674 // Verify no default path 2675 if _, err := os.Stat(DefaultStateFilename); err == nil { 2676 t.Fatal("file should not exist") 2677 } 2678 2679 // Verify no local backup 2680 if _, err := os.Stat(DefaultStateFilename + DefaultBackupExtension); err == nil { 2681 t.Fatal("file should not exist") 2682 } 2683 } 2684 2685 // A plan that has a backend with mismatching lineage 2686 func TestMetaBackend_planBackendMismatchLineage(t *testing.T) { 2687 // Create a temporary working directory that is empty 2688 td := tempDir(t) 2689 copy.CopyDir(testFixturePath("backend-plan-backend-mismatch"), td) 2690 defer os.RemoveAll(td) 2691 defer testChdir(t, td)() 2692 2693 // Get the state for the plan by getting the real state and 2694 // adding the backend config to it. 2695 original := testStateRead(t, filepath.Join( 2696 testFixturePath("backend-plan-backend-empty-config"), 2697 "local-state.tfstate")) 2698 backendState := testStateRead(t, filepath.Join( 2699 testFixturePath("backend-plan-backend-empty-config"), 2700 DefaultDataDir, DefaultStateFilename)) 2701 planState := original.DeepCopy() 2702 planState.Backend = backendState.Backend 2703 2704 // Get the real original 2705 original = testStateRead(t, "local-state.tfstate") 2706 2707 // Create the plan 2708 plan := &terraform.Plan{ 2709 Module: testModule(t, "backend-plan-backend-empty-config"), 2710 State: planState, 2711 } 2712 2713 // Setup the meta 2714 m := testMetaBackend(t, nil) 2715 2716 // Get the backend 2717 _, err := m.Backend(&BackendOpts{Plan: plan}) 2718 if err == nil { 2719 t.Fatal("should have error") 2720 } 2721 if !strings.Contains(err.Error(), "lineage") { 2722 t.Fatalf("bad: %s", err) 2723 } 2724 2725 // Verify our local state didn't change 2726 actual := testStateRead(t, "local-state.tfstate") 2727 if !actual.Equal(original) { 2728 t.Fatalf("bad: %#v", actual) 2729 } 2730 2731 // Verify a backup doesn't exist 2732 if _, err := os.Stat(DefaultStateFilename + DefaultBackupExtension); err == nil { 2733 t.Fatal("file should not exist") 2734 } 2735 2736 // Verify we have no configured backend/legacy 2737 path := filepath.Join(m.DataDir(), DefaultStateFilename) 2738 if _, err := os.Stat(path); err == nil { 2739 t.Fatalf("should not have backend configured") 2740 } 2741 2742 // Verify we have no default state 2743 if _, err := os.Stat(DefaultStateFilename); err == nil { 2744 t.Fatal("file should not exist") 2745 } 2746 } 2747 2748 // A plan that has a legacy remote state 2749 func TestMetaBackend_planLegacy(t *testing.T) { 2750 // Create a temporary working directory that is empty 2751 td := tempDir(t) 2752 copy.CopyDir(testFixturePath("backend-plan-legacy"), td) 2753 defer os.RemoveAll(td) 2754 defer testChdir(t, td)() 2755 2756 // Get the state for the plan by getting the real state and 2757 // adding the backend config to it. 2758 original := testStateRead(t, filepath.Join( 2759 testFixturePath("backend-plan-legacy-data"), "local-state.tfstate")) 2760 dataState := testStateRead(t, filepath.Join( 2761 testFixturePath("backend-plan-legacy-data"), "state.tfstate")) 2762 planState := original.DeepCopy() 2763 planState.Remote = dataState.Remote 2764 2765 // Create the plan 2766 plan := &terraform.Plan{ 2767 Module: testModule(t, "backend-plan-legacy-data"), 2768 State: planState, 2769 } 2770 2771 // Setup the meta 2772 m := testMetaBackend(t, nil) 2773 2774 // Get the backend 2775 b, err := m.Backend(&BackendOpts{Plan: plan}) 2776 if err != nil { 2777 t.Fatalf("err: %s", err) 2778 } 2779 2780 // Check the state 2781 s, err := b.State() 2782 if err != nil { 2783 t.Fatalf("bad: %s", err) 2784 } 2785 if err := s.RefreshState(); err != nil { 2786 t.Fatalf("bad: %s", err) 2787 } 2788 state := s.State() 2789 if state == nil { 2790 t.Fatal("should is nil") 2791 } 2792 if state.Lineage != "hello" { 2793 t.Fatalf("bad: %#v", state) 2794 } 2795 2796 // Verify the default path 2797 if _, err := os.Stat(DefaultStateFilename); err == nil { 2798 t.Fatal("file should not exist") 2799 } 2800 2801 // Verify a backup doesn't exist 2802 if _, err := os.Stat(DefaultStateFilename + DefaultBackupExtension); err == nil { 2803 t.Fatal("file should not exist") 2804 } 2805 2806 // Verify we have no configured backend/legacy 2807 path := filepath.Join(m.DataDir(), DefaultStateFilename) 2808 if _, err := os.Stat(path); err == nil { 2809 t.Fatalf("should not have backend configured") 2810 } 2811 2812 // Write some state 2813 state = terraform.NewState() 2814 state.Lineage = "changing" 2815 s.WriteState(state) 2816 if err := s.PersistState(); err != nil { 2817 t.Fatalf("bad: %s", err) 2818 } 2819 2820 // Verify the state is where we expect 2821 { 2822 f, err := os.Open("local-state.tfstate") 2823 if err != nil { 2824 t.Fatalf("err: %s", err) 2825 } 2826 actual, err := terraform.ReadState(f) 2827 f.Close() 2828 if err != nil { 2829 t.Fatalf("err: %s", err) 2830 } 2831 2832 if actual.Lineage != state.Lineage { 2833 t.Fatalf("bad: %#v", actual) 2834 } 2835 } 2836 2837 // Verify no default path 2838 if _, err := os.Stat(DefaultStateFilename); err == nil { 2839 t.Fatal("file should not exist") 2840 } 2841 2842 // Verify no local backup 2843 if _, err := os.Stat(DefaultStateFilename + DefaultBackupExtension); err == nil { 2844 t.Fatal("file should not exist") 2845 } 2846 } 2847 2848 func testMetaBackend(t *testing.T, args []string) *Meta { 2849 var m Meta 2850 m.Ui = new(cli.MockUi) 2851 m.process(args, true) 2852 f := m.flagSet("test") 2853 if err := f.Parse(args); err != nil { 2854 t.Fatalf("bad: %s", err) 2855 } 2856 2857 return &m 2858 }