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