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