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