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