github.com/satishshettar/terraform@v0.11.12-beta1/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 // Reconfiguring with an already configured backend. 987 // This should ignore the existing backend config, and configure the new 988 // backend is if this is the first time. 989 func TestMetaBackend_reconfigureChange(t *testing.T) { 990 // Create a temporary working directory that is empty 991 td := tempDir(t) 992 copy.CopyDir(testFixturePath("backend-change-single-to-single"), td) 993 defer os.RemoveAll(td) 994 defer testChdir(t, td)() 995 996 // Register the single-state backend 997 backendInit.Set("local-single", backendLocal.TestNewLocalSingle) 998 defer backendInit.Set("local-single", nil) 999 1000 // Setup the meta 1001 m := testMetaBackend(t, nil) 1002 1003 // this should not ask for input 1004 m.input = false 1005 1006 // cli flag -reconfigure 1007 m.reconfigure = true 1008 1009 // Get the backend 1010 b, err := m.Backend(&BackendOpts{Init: true}) 1011 if err != nil { 1012 t.Fatalf("bad: %s", err) 1013 } 1014 1015 // Check the state 1016 s, err := b.State(backend.DefaultStateName) 1017 if err != nil { 1018 t.Fatalf("bad: %s", err) 1019 } 1020 if err := s.RefreshState(); err != nil { 1021 t.Fatalf("bad: %s", err) 1022 } 1023 newState := s.State() 1024 if newState != nil || !newState.Empty() { 1025 t.Fatal("state should be nil/empty after forced reconfiguration") 1026 } 1027 1028 // verify that the old state is still there 1029 s = (&state.LocalState{Path: "local-state.tfstate"}) 1030 if err := s.RefreshState(); err != nil { 1031 t.Fatal(err) 1032 } 1033 oldState := s.State() 1034 if oldState == nil || oldState.Empty() { 1035 t.Fatal("original state should be untouched") 1036 } 1037 } 1038 1039 // Changing a configured backend, copying state 1040 func TestMetaBackend_configuredChangeCopy(t *testing.T) { 1041 // Create a temporary working directory that is empty 1042 td := tempDir(t) 1043 copy.CopyDir(testFixturePath("backend-change"), td) 1044 defer os.RemoveAll(td) 1045 defer testChdir(t, td)() 1046 1047 // Ask input 1048 defer testInteractiveInput(t, []string{"yes", "yes"})() 1049 1050 // Setup the meta 1051 m := testMetaBackend(t, nil) 1052 1053 // Get the backend 1054 b, err := m.Backend(&BackendOpts{Init: true}) 1055 if err != nil { 1056 t.Fatalf("bad: %s", err) 1057 } 1058 1059 // Check the state 1060 s, err := b.State(backend.DefaultStateName) 1061 if err != nil { 1062 t.Fatalf("bad: %s", err) 1063 } 1064 if err := s.RefreshState(); err != nil { 1065 t.Fatalf("bad: %s", err) 1066 } 1067 state := s.State() 1068 if state == nil { 1069 t.Fatal("state should not be nil") 1070 } 1071 if state.Lineage != "backend-change" { 1072 t.Fatalf("bad: %#v", state) 1073 } 1074 1075 // Verify no local state 1076 if _, err := os.Stat(DefaultStateFilename); err == nil { 1077 t.Fatal("file should not exist") 1078 } 1079 1080 // Verify no local backup 1081 if _, err := os.Stat(DefaultStateFilename + DefaultBackupExtension); err == nil { 1082 t.Fatal("file should not exist") 1083 } 1084 } 1085 1086 // Changing a configured backend that supports only single states to another 1087 // backend that only supports single states. 1088 func TestMetaBackend_configuredChangeCopy_singleState(t *testing.T) { 1089 // Create a temporary working directory that is empty 1090 td := tempDir(t) 1091 copy.CopyDir(testFixturePath("backend-change-single-to-single"), td) 1092 defer os.RemoveAll(td) 1093 defer testChdir(t, td)() 1094 1095 // Register the single-state backend 1096 backendInit.Set("local-single", backendLocal.TestNewLocalSingle) 1097 defer backendInit.Set("local-single", nil) 1098 1099 // Ask input 1100 defer testInputMap(t, map[string]string{ 1101 "backend-migrate-copy-to-empty": "yes", 1102 })() 1103 1104 // Setup the meta 1105 m := testMetaBackend(t, nil) 1106 1107 // Get the backend 1108 b, err := m.Backend(&BackendOpts{Init: true}) 1109 if err != nil { 1110 t.Fatalf("bad: %s", err) 1111 } 1112 1113 // Check the state 1114 s, err := b.State(backend.DefaultStateName) 1115 if err != nil { 1116 t.Fatalf("bad: %s", err) 1117 } 1118 if err := s.RefreshState(); err != nil { 1119 t.Fatalf("bad: %s", err) 1120 } 1121 state := s.State() 1122 if state == nil { 1123 t.Fatal("state should not be nil") 1124 } 1125 if state.Lineage != "backend-change" { 1126 t.Fatalf("bad: %#v", state) 1127 } 1128 1129 // Verify no local state 1130 if _, err := os.Stat(DefaultStateFilename); err == nil { 1131 t.Fatal("file should not exist") 1132 } 1133 1134 // Verify no local backup 1135 if _, err := os.Stat(DefaultStateFilename + DefaultBackupExtension); err == nil { 1136 t.Fatal("file should not exist") 1137 } 1138 } 1139 1140 // Changing a configured backend that supports multi-state to a 1141 // backend that only supports single states. The multi-state only has 1142 // a default state. 1143 func TestMetaBackend_configuredChangeCopy_multiToSingleDefault(t *testing.T) { 1144 // Create a temporary working directory that is empty 1145 td := tempDir(t) 1146 copy.CopyDir(testFixturePath("backend-change-multi-default-to-single"), td) 1147 defer os.RemoveAll(td) 1148 defer testChdir(t, td)() 1149 1150 // Register the single-state backend 1151 backendInit.Set("local-single", backendLocal.TestNewLocalSingle) 1152 defer backendInit.Set("local-single", nil) 1153 1154 // Ask input 1155 defer testInputMap(t, map[string]string{ 1156 "backend-migrate-copy-to-empty": "yes", 1157 })() 1158 1159 // Setup the meta 1160 m := testMetaBackend(t, nil) 1161 1162 // Get the backend 1163 b, err := m.Backend(&BackendOpts{Init: true}) 1164 if err != nil { 1165 t.Fatalf("bad: %s", err) 1166 } 1167 1168 // Check the state 1169 s, err := b.State(backend.DefaultStateName) 1170 if err != nil { 1171 t.Fatalf("bad: %s", err) 1172 } 1173 if err := s.RefreshState(); err != nil { 1174 t.Fatalf("bad: %s", err) 1175 } 1176 state := s.State() 1177 if state == nil { 1178 t.Fatal("state should not be nil") 1179 } 1180 if state.Lineage != "backend-change" { 1181 t.Fatalf("bad: %#v", state) 1182 } 1183 1184 // Verify no local state 1185 if _, err := os.Stat(DefaultStateFilename); err == nil { 1186 t.Fatal("file should not exist") 1187 } 1188 1189 // Verify no local backup 1190 if _, err := os.Stat(DefaultStateFilename + DefaultBackupExtension); err == nil { 1191 t.Fatal("file should not exist") 1192 } 1193 } 1194 1195 // Changing a configured backend that supports multi-state to a 1196 // backend that only supports single states. 1197 func TestMetaBackend_configuredChangeCopy_multiToSingle(t *testing.T) { 1198 // Create a temporary working directory that is empty 1199 td := tempDir(t) 1200 copy.CopyDir(testFixturePath("backend-change-multi-to-single"), td) 1201 defer os.RemoveAll(td) 1202 defer testChdir(t, td)() 1203 1204 // Register the single-state backend 1205 backendInit.Set("local-single", backendLocal.TestNewLocalSingle) 1206 defer backendInit.Set("local-single", nil) 1207 1208 // Ask input 1209 defer testInputMap(t, map[string]string{ 1210 "backend-migrate-multistate-to-single": "yes", 1211 "backend-migrate-copy-to-empty": "yes", 1212 })() 1213 1214 // Setup the meta 1215 m := testMetaBackend(t, nil) 1216 1217 // Get the backend 1218 b, err := m.Backend(&BackendOpts{Init: true}) 1219 if err != nil { 1220 t.Fatalf("bad: %s", err) 1221 } 1222 1223 // Check the state 1224 s, err := b.State(backend.DefaultStateName) 1225 if err != nil { 1226 t.Fatalf("bad: %s", err) 1227 } 1228 if err := s.RefreshState(); err != nil { 1229 t.Fatalf("bad: %s", err) 1230 } 1231 state := s.State() 1232 if state == nil { 1233 t.Fatal("state should not be nil") 1234 } 1235 if state.Lineage != "backend-change" { 1236 t.Fatalf("bad: %#v", state) 1237 } 1238 1239 // Verify no local state 1240 if _, err := os.Stat(DefaultStateFilename); err == nil { 1241 t.Fatal("file should not exist") 1242 } 1243 1244 // Verify no local backup 1245 if _, err := os.Stat(DefaultStateFilename + DefaultBackupExtension); err == nil { 1246 t.Fatal("file should not exist") 1247 } 1248 1249 // Verify existing workspaces exist 1250 envPath := filepath.Join(backendLocal.DefaultWorkspaceDir, "env2", backendLocal.DefaultStateFilename) 1251 if _, err := os.Stat(envPath); err != nil { 1252 t.Fatal("env should exist") 1253 } 1254 1255 // Verify we are now in the default env, or we may not be able to access the new backend 1256 if env := m.Workspace(); env != backend.DefaultStateName { 1257 t.Fatal("using non-default env with single-env backend") 1258 } 1259 } 1260 1261 // Changing a configured backend that supports multi-state to a 1262 // backend that only supports single states. 1263 func TestMetaBackend_configuredChangeCopy_multiToSingleCurrentEnv(t *testing.T) { 1264 // Create a temporary working directory that is empty 1265 td := tempDir(t) 1266 copy.CopyDir(testFixturePath("backend-change-multi-to-single"), td) 1267 defer os.RemoveAll(td) 1268 defer testChdir(t, td)() 1269 1270 // Register the single-state backend 1271 backendInit.Set("local-single", backendLocal.TestNewLocalSingle) 1272 defer backendInit.Set("local-single", nil) 1273 1274 // Ask input 1275 defer testInputMap(t, map[string]string{ 1276 "backend-migrate-multistate-to-single": "yes", 1277 "backend-migrate-copy-to-empty": "yes", 1278 })() 1279 1280 // Setup the meta 1281 m := testMetaBackend(t, nil) 1282 1283 // Change env 1284 if err := m.SetWorkspace("env2"); err != nil { 1285 t.Fatalf("bad: %s", err) 1286 } 1287 1288 // Get the backend 1289 b, err := m.Backend(&BackendOpts{Init: true}) 1290 if err != nil { 1291 t.Fatalf("bad: %s", err) 1292 } 1293 1294 // Check the state 1295 s, err := b.State(backend.DefaultStateName) 1296 if err != nil { 1297 t.Fatalf("bad: %s", err) 1298 } 1299 if err := s.RefreshState(); err != nil { 1300 t.Fatalf("bad: %s", err) 1301 } 1302 state := s.State() 1303 if state == nil { 1304 t.Fatal("state should not be nil") 1305 } 1306 if state.Lineage != "backend-change-env2" { 1307 t.Fatalf("bad: %#v", state) 1308 } 1309 1310 // Verify no local state 1311 if _, err := os.Stat(DefaultStateFilename); err == nil { 1312 t.Fatal("file should not exist") 1313 } 1314 1315 // Verify no local backup 1316 if _, err := os.Stat(DefaultStateFilename + DefaultBackupExtension); err == nil { 1317 t.Fatal("file should not exist") 1318 } 1319 1320 // Verify existing workspaces exist 1321 envPath := filepath.Join(backendLocal.DefaultWorkspaceDir, "env2", backendLocal.DefaultStateFilename) 1322 if _, err := os.Stat(envPath); err != nil { 1323 t.Fatal("env should exist") 1324 } 1325 } 1326 1327 // Changing a configured backend that supports multi-state to a 1328 // backend that also supports multi-state. 1329 func TestMetaBackend_configuredChangeCopy_multiToMulti(t *testing.T) { 1330 // Create a temporary working directory that is empty 1331 td := tempDir(t) 1332 copy.CopyDir(testFixturePath("backend-change-multi-to-multi"), td) 1333 defer os.RemoveAll(td) 1334 defer testChdir(t, td)() 1335 1336 // Ask input 1337 defer testInputMap(t, map[string]string{ 1338 "backend-migrate-multistate-to-multistate": "yes", 1339 })() 1340 1341 // Setup the meta 1342 m := testMetaBackend(t, nil) 1343 1344 // Get the backend 1345 b, err := m.Backend(&BackendOpts{Init: true}) 1346 if err != nil { 1347 t.Fatalf("bad: %s", err) 1348 } 1349 1350 // Check resulting states 1351 states, err := b.States() 1352 if err != nil { 1353 t.Fatalf("bad: %s", err) 1354 } 1355 1356 sort.Strings(states) 1357 expected := []string{"default", "env2"} 1358 if !reflect.DeepEqual(states, expected) { 1359 t.Fatalf("bad: %#v", states) 1360 } 1361 1362 { 1363 // Check the default state 1364 s, err := b.State(backend.DefaultStateName) 1365 if err != nil { 1366 t.Fatalf("bad: %s", err) 1367 } 1368 if err := s.RefreshState(); err != nil { 1369 t.Fatalf("bad: %s", err) 1370 } 1371 state := s.State() 1372 if state == nil { 1373 t.Fatal("state should not be nil") 1374 } 1375 if state.Lineage != "backend-change" { 1376 t.Fatalf("bad: %#v", state) 1377 } 1378 } 1379 1380 { 1381 // Check the other state 1382 s, err := b.State("env2") 1383 if err != nil { 1384 t.Fatalf("bad: %s", err) 1385 } 1386 if err := s.RefreshState(); err != nil { 1387 t.Fatalf("bad: %s", err) 1388 } 1389 state := s.State() 1390 if state == nil { 1391 t.Fatal("state should not be nil") 1392 } 1393 if state.Lineage != "backend-change-env2" { 1394 t.Fatalf("bad: %#v", state) 1395 } 1396 } 1397 1398 // Verify no local backup 1399 if _, err := os.Stat(DefaultStateFilename + DefaultBackupExtension); err == nil { 1400 t.Fatal("file should not exist") 1401 } 1402 1403 { 1404 // Verify existing workspaces exist 1405 envPath := filepath.Join(backendLocal.DefaultWorkspaceDir, "env2", backendLocal.DefaultStateFilename) 1406 if _, err := os.Stat(envPath); err != nil { 1407 t.Fatal("env should exist") 1408 } 1409 } 1410 1411 { 1412 // Verify new workspaces exist 1413 envPath := filepath.Join("envdir-new", "env2", backendLocal.DefaultStateFilename) 1414 if _, err := os.Stat(envPath); err != nil { 1415 t.Fatal("env should exist") 1416 } 1417 } 1418 } 1419 1420 // Changing a configured backend that supports multi-state to a 1421 // backend that also supports multi-state, but doesn't allow a 1422 // default state while the default state is non-empty. 1423 func TestMetaBackend_configuredChangeCopy_multiToNoDefaultWithDefault(t *testing.T) { 1424 // Create a temporary working directory that is empty 1425 td := tempDir(t) 1426 copy.CopyDir(testFixturePath("backend-change-multi-to-no-default-with-default"), td) 1427 defer os.RemoveAll(td) 1428 defer testChdir(t, td)() 1429 1430 // Register the single-state backend 1431 backendInit.Set("local-no-default", backendLocal.TestNewLocalNoDefault) 1432 defer backendInit.Set("local-no-default", nil) 1433 1434 // Ask input 1435 defer testInputMap(t, map[string]string{ 1436 "backend-migrate-multistate-to-multistate": "yes", 1437 "new-state-name": "env1", 1438 })() 1439 1440 // Setup the meta 1441 m := testMetaBackend(t, nil) 1442 1443 // Get the backend 1444 b, err := m.Backend(&BackendOpts{Init: true}) 1445 if err != nil { 1446 t.Fatalf("bad: %s", err) 1447 } 1448 1449 // Check resulting states 1450 states, err := b.States() 1451 if err != nil { 1452 t.Fatalf("bad: %s", err) 1453 } 1454 1455 sort.Strings(states) 1456 expected := []string{"env1", "env2"} 1457 if !reflect.DeepEqual(states, expected) { 1458 t.Fatalf("bad: %#v", states) 1459 } 1460 1461 { 1462 // Check the renamed default state 1463 s, err := b.State("env1") 1464 if err != nil { 1465 t.Fatalf("bad: %s", err) 1466 } 1467 if err := s.RefreshState(); err != nil { 1468 t.Fatalf("bad: %s", err) 1469 } 1470 state := s.State() 1471 if state == nil { 1472 t.Fatal("state should not be nil") 1473 } 1474 if state.Lineage != "backend-change-env1" { 1475 t.Fatalf("bad: %#v", state) 1476 } 1477 } 1478 1479 { 1480 // Verify existing workspaces exist 1481 envPath := filepath.Join(backendLocal.DefaultWorkspaceDir, "env2", backendLocal.DefaultStateFilename) 1482 if _, err := os.Stat(envPath); err != nil { 1483 t.Fatal("env should exist") 1484 } 1485 } 1486 1487 { 1488 // Verify new workspaces exist 1489 envPath := filepath.Join("envdir-new", "env2", backendLocal.DefaultStateFilename) 1490 if _, err := os.Stat(envPath); err != nil { 1491 t.Fatal("env should exist") 1492 } 1493 } 1494 } 1495 1496 // Changing a configured backend that supports multi-state to a 1497 // backend that also supports multi-state, but doesn't allow a 1498 // default state while the default state is empty. 1499 func TestMetaBackend_configuredChangeCopy_multiToNoDefaultWithoutDefault(t *testing.T) { 1500 // Create a temporary working directory that is empty 1501 td := tempDir(t) 1502 copy.CopyDir(testFixturePath("backend-change-multi-to-no-default-without-default"), td) 1503 defer os.RemoveAll(td) 1504 defer testChdir(t, td)() 1505 1506 // Register the single-state backend 1507 backendInit.Set("local-no-default", backendLocal.TestNewLocalNoDefault) 1508 defer backendInit.Set("local-no-default", nil) 1509 1510 // Ask input 1511 defer testInputMap(t, map[string]string{ 1512 "backend-migrate-multistate-to-multistate": "yes", 1513 "select-workspace": "1", 1514 })() 1515 1516 // Setup the meta 1517 m := testMetaBackend(t, nil) 1518 1519 // Get the backend 1520 b, err := m.Backend(&BackendOpts{Init: true}) 1521 if err != nil { 1522 t.Fatalf("bad: %s", err) 1523 } 1524 1525 // Check resulting states 1526 states, err := b.States() 1527 if err != nil { 1528 t.Fatalf("bad: %s", err) 1529 } 1530 1531 sort.Strings(states) 1532 expected := []string{"env2"} 1533 if !reflect.DeepEqual(states, expected) { 1534 t.Fatalf("bad: %#v", states) 1535 } 1536 1537 { 1538 // Check the named state 1539 s, err := b.State("env2") 1540 if err != nil { 1541 t.Fatalf("bad: %s", err) 1542 } 1543 if err := s.RefreshState(); err != nil { 1544 t.Fatalf("bad: %s", err) 1545 } 1546 state := s.State() 1547 if state == nil { 1548 t.Fatal("state should not be nil") 1549 } 1550 if state.Lineage != "backend-change-env2" { 1551 t.Fatalf("bad: %#v", state) 1552 } 1553 } 1554 1555 { 1556 // Verify existing workspaces exist 1557 envPath := filepath.Join(backendLocal.DefaultWorkspaceDir, "env2", backendLocal.DefaultStateFilename) 1558 if _, err := os.Stat(envPath); err != nil { 1559 t.Fatal("env should exist") 1560 } 1561 } 1562 1563 { 1564 // Verify new workspaces exist 1565 envPath := filepath.Join("envdir-new", "env2", backendLocal.DefaultStateFilename) 1566 if _, err := os.Stat(envPath); err != nil { 1567 t.Fatal("env should exist") 1568 } 1569 } 1570 } 1571 1572 // Unsetting a saved backend 1573 func TestMetaBackend_configuredUnset(t *testing.T) { 1574 // Create a temporary working directory that is empty 1575 td := tempDir(t) 1576 copy.CopyDir(testFixturePath("backend-unset"), td) 1577 defer os.RemoveAll(td) 1578 defer testChdir(t, td)() 1579 1580 // Ask input 1581 defer testInteractiveInput(t, []string{"no"})() 1582 1583 // Setup the meta 1584 m := testMetaBackend(t, nil) 1585 1586 // Get the backend 1587 b, err := m.Backend(&BackendOpts{Init: true}) 1588 if err != nil { 1589 t.Fatalf("bad: %s", err) 1590 } 1591 1592 // Check the state 1593 s, err := b.State(backend.DefaultStateName) 1594 if err != nil { 1595 t.Fatalf("bad: %s", err) 1596 } 1597 if err := s.RefreshState(); err != nil { 1598 t.Fatalf("bad: %s", err) 1599 } 1600 state := s.State() 1601 if state != nil { 1602 t.Fatal("state should be nil") 1603 } 1604 1605 // Verify the default paths don't exist 1606 if !isEmptyState(DefaultStateFilename) { 1607 data, _ := ioutil.ReadFile(DefaultStateFilename) 1608 t.Fatal("state should not exist, but contains:\n", string(data)) 1609 } 1610 1611 // Verify a backup doesn't exist 1612 if !isEmptyState(DefaultStateFilename + DefaultBackupExtension) { 1613 data, _ := ioutil.ReadFile(DefaultStateFilename + DefaultBackupExtension) 1614 t.Fatal("backup should not exist, but contains:\n", string(data)) 1615 } 1616 1617 // Verify we have no configured backend/legacy 1618 path := filepath.Join(m.DataDir(), DefaultStateFilename) 1619 if _, err := os.Stat(path); err == nil { 1620 f, err := os.Open(path) 1621 if err != nil { 1622 t.Fatalf("err: %s", err) 1623 } 1624 actual, err := terraform.ReadState(f) 1625 f.Close() 1626 if err != nil { 1627 t.Fatalf("err: %s", err) 1628 } 1629 1630 if !actual.Remote.Empty() { 1631 t.Fatalf("bad: %#v", actual) 1632 } 1633 if !actual.Backend.Empty() { 1634 t.Fatalf("bad: %#v", actual) 1635 } 1636 } 1637 1638 // Write some state 1639 s.WriteState(testState()) 1640 if err := s.PersistState(); err != nil { 1641 t.Fatalf("bad: %s", err) 1642 } 1643 1644 // Verify it exists where we expect it to 1645 if isEmptyState(DefaultStateFilename) { 1646 t.Fatal(DefaultStateFilename, "is empty") 1647 } 1648 1649 // Verify no backup since it was empty to start 1650 if !isEmptyState(DefaultStateFilename + DefaultBackupExtension) { 1651 data, _ := ioutil.ReadFile(DefaultStateFilename + DefaultBackupExtension) 1652 t.Fatal("backup state should be empty, but contains:\n", string(data)) 1653 } 1654 } 1655 1656 // Unsetting a saved backend and copying the remote state 1657 func TestMetaBackend_configuredUnsetCopy(t *testing.T) { 1658 // Create a temporary working directory that is empty 1659 td := tempDir(t) 1660 copy.CopyDir(testFixturePath("backend-unset"), td) 1661 defer os.RemoveAll(td) 1662 defer testChdir(t, td)() 1663 1664 // Ask input 1665 defer testInteractiveInput(t, []string{"yes", "yes"})() 1666 1667 // Setup the meta 1668 m := testMetaBackend(t, nil) 1669 1670 // Get the backend 1671 b, err := m.Backend(&BackendOpts{Init: true}) 1672 if err != nil { 1673 t.Fatalf("bad: %s", err) 1674 } 1675 1676 // Check the state 1677 s, err := b.State(backend.DefaultStateName) 1678 if err != nil { 1679 t.Fatalf("bad: %s", err) 1680 } 1681 if err := s.RefreshState(); err != nil { 1682 t.Fatalf("bad: %s", err) 1683 } 1684 state := s.State() 1685 if state == nil { 1686 t.Fatal("state is nil") 1687 } 1688 if state.Lineage != "configuredUnset" { 1689 t.Fatalf("bad: %#v", state) 1690 } 1691 1692 // Verify a backup doesn't exist 1693 if !isEmptyState(DefaultStateFilename + DefaultBackupExtension) { 1694 t.Fatalf("backup state should be empty") 1695 } 1696 1697 // Verify we have no configured backend/legacy 1698 path := filepath.Join(m.DataDir(), DefaultStateFilename) 1699 if _, err := os.Stat(path); err == nil { 1700 f, err := os.Open(path) 1701 if err != nil { 1702 t.Fatalf("err: %s", err) 1703 } 1704 actual, err := terraform.ReadState(f) 1705 f.Close() 1706 if err != nil { 1707 t.Fatalf("err: %s", err) 1708 } 1709 1710 if !actual.Remote.Empty() { 1711 t.Fatalf("bad: %#v", actual) 1712 } 1713 if !actual.Backend.Empty() { 1714 t.Fatalf("bad: %#v", actual) 1715 } 1716 } 1717 1718 // Write some state 1719 s.WriteState(testState()) 1720 if err := s.PersistState(); err != nil { 1721 t.Fatalf("bad: %s", err) 1722 } 1723 1724 // Verify it exists where we expect it to 1725 if _, err := os.Stat(DefaultStateFilename); err != nil { 1726 t.Fatalf("err: %s", err) 1727 } 1728 1729 // Verify a backup since it wasn't empty to start 1730 if isEmptyState(DefaultStateFilename + DefaultBackupExtension) { 1731 t.Fatal("backup is empty") 1732 } 1733 } 1734 1735 // Saved backend state matching config, with legacy 1736 func TestMetaBackend_configuredUnchangedLegacy(t *testing.T) { 1737 // Create a temporary working directory that is empty 1738 td := tempDir(t) 1739 copy.CopyDir(testFixturePath("backend-unchanged-with-legacy"), td) 1740 defer os.RemoveAll(td) 1741 defer testChdir(t, td)() 1742 1743 // Ask input 1744 defer testInteractiveInput(t, []string{"no"})() 1745 1746 // Setup the meta 1747 m := testMetaBackend(t, nil) 1748 1749 // Get the backend 1750 b, err := m.Backend(&BackendOpts{Init: true}) 1751 if err != nil { 1752 t.Fatalf("bad: %s", err) 1753 } 1754 1755 // Check the state 1756 s, err := b.State(backend.DefaultStateName) 1757 if err != nil { 1758 t.Fatalf("bad: %s", err) 1759 } 1760 if err := s.RefreshState(); err != nil { 1761 t.Fatalf("bad: %s", err) 1762 } 1763 state := s.State() 1764 if state == nil { 1765 t.Fatal("state is nil") 1766 } 1767 if state.Lineage != "configured" { 1768 t.Fatalf("bad: %#v", state) 1769 } 1770 1771 // Verify the default paths don't exist 1772 if _, err := os.Stat(DefaultStateFilename); err == nil { 1773 t.Fatalf("err: %s", err) 1774 } 1775 1776 // Verify a backup doesn't exist 1777 if _, err := os.Stat(DefaultStateFilename + DefaultBackupExtension); err == nil { 1778 t.Fatal("file should not exist") 1779 } 1780 1781 // Verify we have no configured legacy 1782 { 1783 path := filepath.Join(m.DataDir(), DefaultStateFilename) 1784 f, err := os.Open(path) 1785 if err != nil { 1786 t.Fatalf("err: %s", err) 1787 } 1788 actual, err := terraform.ReadState(f) 1789 f.Close() 1790 if err != nil { 1791 t.Fatalf("err: %s", err) 1792 } 1793 1794 if !actual.Remote.Empty() { 1795 t.Fatalf("bad: %#v", actual) 1796 } 1797 if actual.Backend.Empty() { 1798 t.Fatalf("bad: %#v", actual) 1799 } 1800 } 1801 1802 // Write some state 1803 state = terraform.NewState() 1804 state.Lineage = "changing" 1805 s.WriteState(state) 1806 if err := s.PersistState(); err != nil { 1807 t.Fatalf("bad: %s", err) 1808 } 1809 1810 // Verify the state is where we expect 1811 { 1812 f, err := os.Open("local-state.tfstate") 1813 if err != nil { 1814 t.Fatalf("err: %s", err) 1815 } 1816 actual, err := terraform.ReadState(f) 1817 f.Close() 1818 if err != nil { 1819 t.Fatalf("err: %s", err) 1820 } 1821 1822 if actual.Lineage != state.Lineage { 1823 t.Fatalf("bad: %#v", actual) 1824 } 1825 } 1826 1827 // Verify no local state 1828 if _, err := os.Stat(DefaultStateFilename); err == nil { 1829 t.Fatal("file should not exist") 1830 } 1831 1832 // Verify no local backup 1833 if _, err := os.Stat(DefaultStateFilename + DefaultBackupExtension); err == nil { 1834 t.Fatal("file should not exist") 1835 } 1836 } 1837 1838 // Saved backend state matching config, with legacy 1839 func TestMetaBackend_configuredUnchangedLegacyCopy(t *testing.T) { 1840 // Create a temporary working directory that is empty 1841 td := tempDir(t) 1842 copy.CopyDir(testFixturePath("backend-unchanged-with-legacy"), td) 1843 defer os.RemoveAll(td) 1844 defer testChdir(t, td)() 1845 1846 // Setup the meta 1847 m := testMetaBackend(t, nil) 1848 m.forceInitCopy = true 1849 1850 // Get the backend 1851 b, err := m.Backend(&BackendOpts{Init: true}) 1852 if err != nil { 1853 t.Fatalf("bad: %s", err) 1854 } 1855 1856 // Check the state 1857 s, err := b.State(backend.DefaultStateName) 1858 if err != nil { 1859 t.Fatalf("bad: %s", err) 1860 } 1861 if err := s.RefreshState(); err != nil { 1862 t.Fatalf("bad: %s", err) 1863 } 1864 state := s.State() 1865 if state == nil { 1866 t.Fatal("state is nil") 1867 } 1868 if state.Lineage != "backend-unchanged-with-legacy" { 1869 t.Fatalf("bad: %#v", state) 1870 } 1871 1872 // Verify the default paths don't exist 1873 if _, err := os.Stat(DefaultStateFilename); err == nil { 1874 t.Fatal("file should not exist") 1875 } 1876 1877 // Verify a backup doesn't exist 1878 if _, err := os.Stat(DefaultStateFilename + DefaultBackupExtension); err == nil { 1879 t.Fatal("file should not exist") 1880 } 1881 1882 // Verify we have no configured legacy 1883 { 1884 path := filepath.Join(m.DataDir(), DefaultStateFilename) 1885 f, err := os.Open(path) 1886 if err != nil { 1887 t.Fatalf("err: %s", err) 1888 } 1889 actual, err := terraform.ReadState(f) 1890 f.Close() 1891 if err != nil { 1892 t.Fatalf("err: %s", err) 1893 } 1894 1895 if !actual.Remote.Empty() { 1896 t.Fatalf("bad: %#v", actual) 1897 } 1898 if actual.Backend.Empty() { 1899 t.Fatalf("bad: %#v", actual) 1900 } 1901 } 1902 1903 // Write some state 1904 state = terraform.NewState() 1905 state.Lineage = "changing" 1906 s.WriteState(state) 1907 if err := s.PersistState(); err != nil { 1908 t.Fatalf("bad: %s", err) 1909 } 1910 1911 // Verify the state is where we expect 1912 { 1913 f, err := os.Open("local-state.tfstate") 1914 if err != nil { 1915 t.Fatalf("err: %s", err) 1916 } 1917 actual, err := terraform.ReadState(f) 1918 f.Close() 1919 if err != nil { 1920 t.Fatalf("err: %s", err) 1921 } 1922 1923 if actual.Lineage != state.Lineage { 1924 t.Fatalf("bad: %#v", actual) 1925 } 1926 } 1927 1928 // Verify no local state 1929 if _, err := os.Stat(DefaultStateFilename); err == nil { 1930 t.Fatal("file should not exist") 1931 } 1932 1933 // Verify no local backup 1934 if _, err := os.Stat(DefaultStateFilename + DefaultBackupExtension); err == nil { 1935 t.Fatal("file should not exist") 1936 } 1937 } 1938 1939 // Saved backend state, new config, legacy remote state 1940 func TestMetaBackend_configuredChangedLegacy(t *testing.T) { 1941 // Create a temporary working directory that is empty 1942 td := tempDir(t) 1943 copy.CopyDir(testFixturePath("backend-changed-with-legacy"), td) 1944 defer os.RemoveAll(td) 1945 defer testChdir(t, td)() 1946 1947 // Ask input 1948 defer testInteractiveInput(t, []string{"no", "no"})() 1949 1950 // Setup the meta 1951 m := testMetaBackend(t, nil) 1952 1953 // Get the backend 1954 b, err := m.Backend(&BackendOpts{Init: true}) 1955 if err != nil { 1956 t.Fatalf("bad: %s", err) 1957 } 1958 1959 // Check the state 1960 s, err := b.State(backend.DefaultStateName) 1961 if err != nil { 1962 t.Fatalf("bad: %s", err) 1963 } 1964 if err := s.RefreshState(); err != nil { 1965 t.Fatalf("bad: %s", err) 1966 } 1967 state := s.State() 1968 if state != nil { 1969 t.Fatal("state should be nil") 1970 } 1971 1972 // Verify the default paths don't exist 1973 if _, err := os.Stat(DefaultStateFilename); err == nil { 1974 t.Fatal("file should not exist") 1975 } 1976 1977 // Verify a backup doesn't exist 1978 if _, err := os.Stat(DefaultStateFilename + DefaultBackupExtension); err == nil { 1979 t.Fatal("file should not exist") 1980 } 1981 1982 // Verify we have no configured legacy 1983 { 1984 path := filepath.Join(m.DataDir(), DefaultStateFilename) 1985 f, err := os.Open(path) 1986 if err != nil { 1987 t.Fatalf("err: %s", err) 1988 } 1989 actual, err := terraform.ReadState(f) 1990 f.Close() 1991 if err != nil { 1992 t.Fatalf("err: %s", err) 1993 } 1994 1995 if !actual.Remote.Empty() { 1996 t.Fatalf("bad: %#v", actual) 1997 } 1998 if actual.Backend.Empty() { 1999 t.Fatalf("bad: %#v", actual) 2000 } 2001 } 2002 2003 // Write some state 2004 state = terraform.NewState() 2005 state.Lineage = "changing" 2006 s.WriteState(state) 2007 if err := s.PersistState(); err != nil { 2008 t.Fatalf("bad: %s", err) 2009 } 2010 2011 // Verify the state is where we expect 2012 { 2013 f, err := os.Open("local-state-2.tfstate") 2014 if err != nil { 2015 t.Fatalf("err: %s", err) 2016 } 2017 actual, err := terraform.ReadState(f) 2018 f.Close() 2019 if err != nil { 2020 t.Fatalf("err: %s", err) 2021 } 2022 2023 if actual.Lineage != state.Lineage { 2024 t.Fatalf("bad: %#v", actual) 2025 } 2026 } 2027 2028 // Verify no local state 2029 if _, err := os.Stat(DefaultStateFilename); err == nil { 2030 t.Fatal("file should not exist") 2031 } 2032 2033 // Verify no local backup 2034 if _, err := os.Stat(DefaultStateFilename + DefaultBackupExtension); err == nil { 2035 t.Fatal("file should not exist") 2036 } 2037 } 2038 2039 // Saved backend state, new config, legacy remote state 2040 func TestMetaBackend_configuredChangedLegacyCopyBackend(t *testing.T) { 2041 // Create a temporary working directory that is empty 2042 td := tempDir(t) 2043 copy.CopyDir(testFixturePath("backend-changed-with-legacy"), td) 2044 defer os.RemoveAll(td) 2045 defer testChdir(t, td)() 2046 2047 // Ask input 2048 defer testInteractiveInput(t, []string{"yes", "no"})() 2049 2050 // Setup the meta 2051 m := testMetaBackend(t, nil) 2052 2053 // Get the backend 2054 b, err := m.Backend(&BackendOpts{Init: true}) 2055 if err != nil { 2056 t.Fatalf("bad: %s", err) 2057 } 2058 2059 // Check the state 2060 s, err := b.State(backend.DefaultStateName) 2061 if err != nil { 2062 t.Fatalf("bad: %s", err) 2063 } 2064 if err := s.RefreshState(); err != nil { 2065 t.Fatalf("bad: %s", err) 2066 } 2067 state := s.State() 2068 if state == nil { 2069 t.Fatal("state is nil") 2070 } 2071 if state.Lineage != "configured" { 2072 t.Fatalf("bad: %#v", state) 2073 } 2074 2075 // Verify the default paths don't exist 2076 if _, err := os.Stat(DefaultStateFilename); err == nil { 2077 t.Fatal("file should not exist") 2078 } 2079 2080 // Verify a backup doesn't exist 2081 if _, err := os.Stat(DefaultStateFilename + DefaultBackupExtension); err == nil { 2082 t.Fatal("file should not exist") 2083 } 2084 2085 // Verify we have no configured legacy 2086 { 2087 path := filepath.Join(m.DataDir(), DefaultStateFilename) 2088 f, err := os.Open(path) 2089 if err != nil { 2090 t.Fatalf("err: %s", err) 2091 } 2092 actual, err := terraform.ReadState(f) 2093 f.Close() 2094 if err != nil { 2095 t.Fatalf("err: %s", err) 2096 } 2097 2098 if !actual.Remote.Empty() { 2099 t.Fatalf("bad: %#v", actual) 2100 } 2101 if actual.Backend.Empty() { 2102 t.Fatalf("bad: %#v", actual) 2103 } 2104 } 2105 2106 // Write some state 2107 state = terraform.NewState() 2108 state.Lineage = "changing" 2109 s.WriteState(state) 2110 if err := s.PersistState(); err != nil { 2111 t.Fatalf("bad: %s", err) 2112 } 2113 2114 // Verify the state is where we expect 2115 { 2116 f, err := os.Open("local-state-2.tfstate") 2117 if err != nil { 2118 t.Fatalf("err: %s", err) 2119 } 2120 actual, err := terraform.ReadState(f) 2121 f.Close() 2122 if err != nil { 2123 t.Fatalf("err: %s", err) 2124 } 2125 2126 if actual.Lineage != state.Lineage { 2127 t.Fatalf("bad: %#v", actual) 2128 } 2129 } 2130 2131 // Verify no local state 2132 if _, err := os.Stat(DefaultStateFilename); err == nil { 2133 t.Fatal("file should not exist") 2134 } 2135 2136 // Verify no local backup 2137 if _, err := os.Stat(DefaultStateFilename + DefaultBackupExtension); err == nil { 2138 t.Fatal("file should not exist") 2139 } 2140 } 2141 2142 // Saved backend state, new config, legacy remote state 2143 func TestMetaBackend_configuredChangedLegacyCopyLegacy(t *testing.T) { 2144 // Create a temporary working directory that is empty 2145 td := tempDir(t) 2146 copy.CopyDir(testFixturePath("backend-changed-with-legacy"), td) 2147 defer os.RemoveAll(td) 2148 defer testChdir(t, td)() 2149 2150 // Ask input 2151 defer testInteractiveInput(t, []string{"no", "yes", "yes"})() 2152 2153 // Setup the meta 2154 m := testMetaBackend(t, nil) 2155 2156 // Get the backend 2157 b, err := m.Backend(&BackendOpts{Init: true}) 2158 if err != nil { 2159 t.Fatalf("bad: %s", err) 2160 } 2161 2162 // Check the state 2163 s, err := b.State(backend.DefaultStateName) 2164 if err != nil { 2165 t.Fatalf("bad: %s", err) 2166 } 2167 if err := s.RefreshState(); err != nil { 2168 t.Fatalf("bad: %s", err) 2169 } 2170 state := s.State() 2171 if state == nil { 2172 t.Fatal("state is nil") 2173 } 2174 if state.Lineage != "legacy" { 2175 t.Fatalf("bad: %#v", state) 2176 } 2177 2178 // Verify the default paths don't exist 2179 if _, err := os.Stat(DefaultStateFilename); err == nil { 2180 t.Fatal("file should not exist") 2181 } 2182 2183 // Verify a backup doesn't exist 2184 if _, err := os.Stat(DefaultStateFilename + DefaultBackupExtension); err == nil { 2185 t.Fatal("file should not exist") 2186 } 2187 2188 // Verify we have no configured legacy 2189 { 2190 path := filepath.Join(m.DataDir(), DefaultStateFilename) 2191 f, err := os.Open(path) 2192 if err != nil { 2193 t.Fatalf("err: %s", err) 2194 } 2195 actual, err := terraform.ReadState(f) 2196 f.Close() 2197 if err != nil { 2198 t.Fatalf("err: %s", err) 2199 } 2200 2201 if !actual.Remote.Empty() { 2202 t.Fatalf("bad: %#v", actual) 2203 } 2204 if actual.Backend.Empty() { 2205 t.Fatalf("bad: %#v", actual) 2206 } 2207 } 2208 2209 // Write some state 2210 state = terraform.NewState() 2211 state.Lineage = "changing" 2212 s.WriteState(state) 2213 if err := s.PersistState(); err != nil { 2214 t.Fatalf("bad: %s", err) 2215 } 2216 2217 // Verify the state is where we expect 2218 { 2219 f, err := os.Open("local-state-2.tfstate") 2220 if err != nil { 2221 t.Fatalf("err: %s", err) 2222 } 2223 actual, err := terraform.ReadState(f) 2224 f.Close() 2225 if err != nil { 2226 t.Fatalf("err: %s", err) 2227 } 2228 2229 if actual.Lineage != state.Lineage { 2230 t.Fatalf("bad: %#v", actual) 2231 } 2232 } 2233 2234 // Verify no local state 2235 if _, err := os.Stat(DefaultStateFilename); err == nil { 2236 t.Fatal("file should not exist") 2237 } 2238 2239 // Verify no local backup 2240 if _, err := os.Stat(DefaultStateFilename + DefaultBackupExtension); err == nil { 2241 t.Fatal("file should not exist") 2242 } 2243 } 2244 2245 // Saved backend state, new config, legacy remote state 2246 func TestMetaBackend_configuredChangedLegacyCopyBoth(t *testing.T) { 2247 // Create a temporary working directory that is empty 2248 td := tempDir(t) 2249 copy.CopyDir(testFixturePath("backend-changed-with-legacy"), td) 2250 defer os.RemoveAll(td) 2251 defer testChdir(t, td)() 2252 2253 // Ask input 2254 defer testInteractiveInput(t, []string{"yes", "yes", "yes", "yes"})() 2255 2256 // Setup the meta 2257 m := testMetaBackend(t, nil) 2258 2259 // Get the backend 2260 b, err := m.Backend(&BackendOpts{Init: true}) 2261 if err != nil { 2262 t.Fatalf("bad: %s", err) 2263 } 2264 2265 // Check the state 2266 s, err := b.State(backend.DefaultStateName) 2267 if err != nil { 2268 t.Fatalf("bad: %s", err) 2269 } 2270 if err := s.RefreshState(); err != nil { 2271 t.Fatalf("bad: %s", err) 2272 } 2273 state := s.State() 2274 if state == nil { 2275 t.Fatal("state is nil") 2276 } 2277 if state.Lineage != "legacy" { 2278 t.Fatalf("bad: %#v", state) 2279 } 2280 2281 // Verify the default paths don't exist 2282 if _, err := os.Stat(DefaultStateFilename); err == nil { 2283 t.Fatal("file should not exist") 2284 } 2285 2286 // Verify a backup doesn't exist 2287 if _, err := os.Stat(DefaultStateFilename + DefaultBackupExtension); err == nil { 2288 t.Fatal("file should not exist") 2289 } 2290 2291 // Verify we have no configured legacy 2292 { 2293 path := filepath.Join(m.DataDir(), DefaultStateFilename) 2294 f, err := os.Open(path) 2295 if err != nil { 2296 t.Fatalf("err: %s", err) 2297 } 2298 actual, err := terraform.ReadState(f) 2299 f.Close() 2300 if err != nil { 2301 t.Fatalf("err: %s", err) 2302 } 2303 2304 if !actual.Remote.Empty() { 2305 t.Fatalf("bad: %#v", actual) 2306 } 2307 if actual.Backend.Empty() { 2308 t.Fatalf("bad: %#v", actual) 2309 } 2310 } 2311 2312 // Write some state 2313 state = terraform.NewState() 2314 state.Lineage = "changing" 2315 s.WriteState(state) 2316 if err := s.PersistState(); err != nil { 2317 t.Fatalf("bad: %s", err) 2318 } 2319 2320 // Verify the state is where we expect 2321 { 2322 f, err := os.Open("local-state-2.tfstate") 2323 if err != nil { 2324 t.Fatalf("err: %s", err) 2325 } 2326 actual, err := terraform.ReadState(f) 2327 f.Close() 2328 if err != nil { 2329 t.Fatalf("err: %s", err) 2330 } 2331 2332 if actual.Lineage != state.Lineage { 2333 t.Fatalf("bad: %#v", actual) 2334 } 2335 } 2336 2337 // Verify no local state 2338 if _, err := os.Stat(DefaultStateFilename); err == nil { 2339 t.Fatal("file should not exist") 2340 } 2341 2342 // Verify no local backup 2343 if _, err := os.Stat(DefaultStateFilename + DefaultBackupExtension); err == nil { 2344 t.Fatal("file should not exist") 2345 } 2346 } 2347 2348 // Saved backend state, unset config, legacy remote state 2349 func TestMetaBackend_configuredUnsetWithLegacyNoCopy(t *testing.T) { 2350 // Create a temporary working directory that is empty 2351 td := tempDir(t) 2352 copy.CopyDir(testFixturePath("backend-unset-with-legacy"), td) 2353 defer os.RemoveAll(td) 2354 defer testChdir(t, td)() 2355 2356 // Ask input 2357 defer testInteractiveInput(t, []string{"no", "no"})() 2358 2359 // Setup the meta 2360 m := testMetaBackend(t, nil) 2361 2362 // Get the backend 2363 b, err := m.Backend(&BackendOpts{Init: true}) 2364 if err != nil { 2365 t.Fatalf("bad: %s", err) 2366 } 2367 2368 // Check the state 2369 s, err := b.State(backend.DefaultStateName) 2370 if err != nil { 2371 t.Fatalf("bad: %s", err) 2372 } 2373 if err := s.RefreshState(); err != nil { 2374 t.Fatalf("bad: %s", err) 2375 } 2376 state := s.State() 2377 if state != nil { 2378 t.Fatal("state should be nil") 2379 } 2380 2381 // Verify the default paths dont exist since we had no state 2382 if !isEmptyState(DefaultStateFilename) { 2383 t.Fatal("state should be empty") 2384 } 2385 2386 // Verify a backup doesn't exist 2387 if !isEmptyState(DefaultStateFilename + DefaultBackupExtension) { 2388 t.Fatal("backup should be empty") 2389 } 2390 2391 // Verify we have no configured backend/legacy 2392 path := filepath.Join(m.DataDir(), DefaultStateFilename) 2393 if _, err := os.Stat(path); err == nil { 2394 f, err := os.Open(path) 2395 if err != nil { 2396 t.Fatalf("err: %s", err) 2397 } 2398 actual, err := terraform.ReadState(f) 2399 f.Close() 2400 if err != nil { 2401 t.Fatalf("err: %s", err) 2402 } 2403 2404 if !actual.Remote.Empty() { 2405 t.Fatalf("bad: %#v", actual) 2406 } 2407 if !actual.Backend.Empty() { 2408 t.Fatalf("bad: %#v", actual) 2409 } 2410 } 2411 2412 // Write some state 2413 state = terraform.NewState() 2414 state.Lineage = "changing" 2415 s.WriteState(state) 2416 if err := s.PersistState(); err != nil { 2417 t.Fatalf("bad: %s", err) 2418 } 2419 2420 // Verify the state is where we expect 2421 { 2422 f, err := os.Open(DefaultStateFilename) 2423 if err != nil { 2424 t.Fatalf("err: %s", err) 2425 } 2426 actual, err := terraform.ReadState(f) 2427 f.Close() 2428 if err != nil { 2429 t.Fatalf("err: %s", err) 2430 } 2431 2432 if actual.Lineage != state.Lineage { 2433 t.Fatalf("bad: %#v", actual) 2434 } 2435 } 2436 } 2437 2438 // Saved backend state, unset config, legacy remote state 2439 func TestMetaBackend_configuredUnsetWithLegacyCopyBackend(t *testing.T) { 2440 // Create a temporary working directory that is empty 2441 td := tempDir(t) 2442 copy.CopyDir(testFixturePath("backend-unset-with-legacy"), td) 2443 defer os.RemoveAll(td) 2444 defer testChdir(t, td)() 2445 2446 // Ask input 2447 defer testInteractiveInput(t, []string{"yes", "no"})() 2448 2449 // Setup the meta 2450 m := testMetaBackend(t, nil) 2451 2452 // Get the backend 2453 b, err := m.Backend(&BackendOpts{Init: true}) 2454 if err != nil { 2455 t.Fatalf("bad: %s", err) 2456 } 2457 2458 // Check the state 2459 s, err := b.State(backend.DefaultStateName) 2460 if err != nil { 2461 t.Fatalf("bad: %s", err) 2462 } 2463 if err := s.RefreshState(); err != nil { 2464 t.Fatalf("bad: %s", err) 2465 } 2466 state := s.State() 2467 if state == nil { 2468 t.Fatal("state is nil") 2469 } 2470 if state.Lineage != "backend" { 2471 t.Fatalf("bad: %#v", state) 2472 } 2473 2474 // Verify the default paths exist 2475 if isEmptyState(DefaultStateFilename) { 2476 t.Fatalf("default state was empty") 2477 } 2478 2479 // Verify a backup doesn't exist 2480 if !isEmptyState(DefaultStateFilename + DefaultBackupExtension) { 2481 t.Fatal("backupstate should be empty") 2482 } 2483 2484 // Verify we have no configured backend/legacy 2485 path := filepath.Join(m.DataDir(), DefaultStateFilename) 2486 if _, err := os.Stat(path); err == nil { 2487 f, err := os.Open(path) 2488 if err != nil { 2489 t.Fatalf("err: %s", err) 2490 } 2491 actual, err := terraform.ReadState(f) 2492 f.Close() 2493 if err != nil { 2494 t.Fatalf("err: %s", err) 2495 } 2496 2497 if !actual.Remote.Empty() { 2498 t.Fatalf("bad: %#v", actual) 2499 } 2500 if !actual.Backend.Empty() { 2501 t.Fatalf("bad: %#v", actual) 2502 } 2503 } 2504 2505 // Write some state 2506 state = terraform.NewState() 2507 state.Lineage = "changing" 2508 s.WriteState(state) 2509 if err := s.PersistState(); err != nil { 2510 t.Fatalf("bad: %s", err) 2511 } 2512 2513 // Verify the state is where we expect 2514 { 2515 f, err := os.Open(DefaultStateFilename) 2516 if err != nil { 2517 t.Fatalf("err: %s", err) 2518 } 2519 actual, err := terraform.ReadState(f) 2520 f.Close() 2521 if err != nil { 2522 t.Fatalf("err: %s", err) 2523 } 2524 2525 if actual.Lineage != state.Lineage { 2526 t.Fatalf("bad: %#v", actual) 2527 } 2528 } 2529 2530 // Verify a local backup 2531 if isEmptyState(DefaultStateFilename + DefaultBackupExtension) { 2532 t.Fatal("backup is empty") 2533 } 2534 } 2535 2536 // Saved backend state, unset config, legacy remote state 2537 func TestMetaBackend_configuredUnsetWithLegacyCopyLegacy(t *testing.T) { 2538 // Create a temporary working directory that is empty 2539 td := tempDir(t) 2540 copy.CopyDir(testFixturePath("backend-unset-with-legacy"), td) 2541 defer os.RemoveAll(td) 2542 defer testChdir(t, td)() 2543 2544 // Ask input 2545 defer testInteractiveInput(t, []string{"no", "yes", "yes"})() 2546 2547 // Setup the meta 2548 m := testMetaBackend(t, nil) 2549 2550 // Get the backend 2551 b, err := m.Backend(&BackendOpts{Init: true}) 2552 if err != nil { 2553 t.Fatalf("bad: %s", err) 2554 } 2555 2556 // Check the state 2557 s, err := b.State(backend.DefaultStateName) 2558 if err != nil { 2559 t.Fatalf("bad: %s", err) 2560 } 2561 if err := s.RefreshState(); err != nil { 2562 t.Fatalf("bad: %s", err) 2563 } 2564 state := s.State() 2565 if state == nil { 2566 t.Fatal("state is nil") 2567 } 2568 if state.Lineage != "legacy" { 2569 t.Fatalf("bad: %#v", state) 2570 } 2571 2572 // Verify the default paths exist 2573 if isEmptyState(DefaultStateFilename) { 2574 t.Fatalf("default state was empty") 2575 } 2576 2577 // Verify a backup doesn't exist 2578 if !isEmptyState(DefaultStateFilename + DefaultBackupExtension) { 2579 t.Fatal("backupstate should be empty") 2580 } 2581 2582 // Verify we have no configured backend/legacy 2583 path := filepath.Join(m.DataDir(), DefaultStateFilename) 2584 if _, err := os.Stat(path); err == nil { 2585 f, err := os.Open(path) 2586 if err != nil { 2587 t.Fatalf("err: %s", err) 2588 } 2589 actual, err := terraform.ReadState(f) 2590 f.Close() 2591 if err != nil { 2592 t.Fatalf("err: %s", err) 2593 } 2594 2595 if !actual.Remote.Empty() { 2596 t.Fatalf("bad: %#v", actual) 2597 } 2598 if !actual.Backend.Empty() { 2599 t.Fatalf("bad: %#v", actual) 2600 } 2601 } 2602 2603 // Write some state 2604 state = terraform.NewState() 2605 state.Lineage = "changing" 2606 s.WriteState(state) 2607 if err := s.PersistState(); err != nil { 2608 t.Fatalf("bad: %s", err) 2609 } 2610 2611 // Verify the state is where we expect 2612 { 2613 f, err := os.Open(DefaultStateFilename) 2614 if err != nil { 2615 t.Fatalf("err: %s", err) 2616 } 2617 actual, err := terraform.ReadState(f) 2618 f.Close() 2619 if err != nil { 2620 t.Fatalf("err: %s", err) 2621 } 2622 2623 if actual.Lineage != state.Lineage { 2624 t.Fatalf("bad: %#v", actual) 2625 } 2626 } 2627 2628 // Verify a local backup 2629 if isEmptyState(DefaultStateFilename + DefaultBackupExtension) { 2630 t.Fatal("backup is empty") 2631 } 2632 } 2633 2634 // Saved backend state, unset config, legacy remote state 2635 func TestMetaBackend_configuredUnsetWithLegacyCopyBoth(t *testing.T) { 2636 // Create a temporary working directory that is empty 2637 td := tempDir(t) 2638 copy.CopyDir(testFixturePath("backend-unset-with-legacy"), td) 2639 defer os.RemoveAll(td) 2640 defer testChdir(t, td)() 2641 2642 // Ask input 2643 defer testInteractiveInput(t, []string{"yes", "yes", "yes", "yes"})() 2644 2645 // Setup the meta 2646 m := testMetaBackend(t, nil) 2647 2648 // Get the backend 2649 b, err := m.Backend(&BackendOpts{Init: true}) 2650 if err != nil { 2651 t.Fatalf("bad: %s", err) 2652 } 2653 2654 // Check the state 2655 s, err := b.State(backend.DefaultStateName) 2656 if err != nil { 2657 t.Fatalf("bad: %s", err) 2658 } 2659 if err := s.RefreshState(); err != nil { 2660 t.Fatalf("bad: %s", err) 2661 } 2662 state := s.State() 2663 if state == nil { 2664 t.Fatal("state is nil") 2665 } 2666 if state.Lineage != "legacy" { 2667 t.Fatalf("bad: %#v", state) 2668 } 2669 2670 // Verify the default paths exist 2671 if isEmptyState(DefaultStateFilename) { 2672 t.Fatal("state is empty") 2673 } 2674 2675 // Verify a backup exists 2676 if isEmptyState(DefaultStateFilename + DefaultBackupExtension) { 2677 t.Fatal("backup is empty") 2678 } 2679 2680 // Verify we have no configured backend/legacy 2681 path := filepath.Join(m.DataDir(), DefaultStateFilename) 2682 if _, err := os.Stat(path); err == nil { 2683 f, err := os.Open(path) 2684 if err != nil { 2685 t.Fatalf("err: %s", err) 2686 } 2687 actual, err := terraform.ReadState(f) 2688 f.Close() 2689 if err != nil { 2690 t.Fatalf("err: %s", err) 2691 } 2692 2693 if !actual.Remote.Empty() { 2694 t.Fatalf("bad: %#v", actual) 2695 } 2696 if !actual.Backend.Empty() { 2697 t.Fatalf("bad: %#v", actual) 2698 } 2699 } 2700 2701 // Write some state 2702 state = terraform.NewState() 2703 state.Lineage = "changing" 2704 s.WriteState(state) 2705 if err := s.PersistState(); err != nil { 2706 t.Fatalf("bad: %s", err) 2707 } 2708 2709 // Verify the state is where we expect 2710 { 2711 f, err := os.Open(DefaultStateFilename) 2712 if err != nil { 2713 t.Fatalf("err: %s", err) 2714 } 2715 actual, err := terraform.ReadState(f) 2716 f.Close() 2717 if err != nil { 2718 t.Fatalf("err: %s", err) 2719 } 2720 2721 if actual.Lineage != state.Lineage { 2722 t.Fatalf("bad: %#v", actual) 2723 } 2724 } 2725 2726 // Verify a local backup 2727 if isEmptyState(DefaultStateFilename + DefaultBackupExtension) { 2728 t.Fatal("backup is empty") 2729 } 2730 } 2731 2732 // A plan that has no backend config 2733 func TestMetaBackend_planLocal(t *testing.T) { 2734 // Create a temporary working directory that is empty 2735 td := tempDir(t) 2736 copy.CopyDir(testFixturePath("backend-plan-local"), td) 2737 defer os.RemoveAll(td) 2738 defer testChdir(t, td)() 2739 2740 // Create the plan 2741 plan := &terraform.Plan{ 2742 Module: testModule(t, "backend-plan-local"), 2743 State: nil, 2744 } 2745 2746 // Setup the meta 2747 m := testMetaBackend(t, nil) 2748 2749 // Get the backend 2750 b, err := m.Backend(&BackendOpts{Plan: plan}) 2751 if err != nil { 2752 t.Fatalf("bad: %s", err) 2753 } 2754 2755 // Check the state 2756 s, err := b.State(backend.DefaultStateName) 2757 if err != nil { 2758 t.Fatalf("bad: %s", err) 2759 } 2760 if err := s.RefreshState(); err != nil { 2761 t.Fatalf("bad: %s", err) 2762 } 2763 state := s.State() 2764 if state != nil { 2765 t.Fatalf("state should be nil: %#v", state) 2766 } 2767 2768 // Verify the default path doens't exist 2769 if !isEmptyState(DefaultStateFilename) { 2770 t.Fatal("expected empty state") 2771 } 2772 2773 // Verify a backup doesn't exists 2774 if !isEmptyState(DefaultStateFilename + DefaultBackupExtension) { 2775 t.Fatal("expected empty backup") 2776 } 2777 2778 // Verify we have no configured backend/legacy 2779 path := filepath.Join(m.DataDir(), DefaultStateFilename) 2780 if _, err := os.Stat(path); err == nil { 2781 t.Fatalf("should not have backend configured") 2782 } 2783 2784 // Write some state 2785 state = terraform.NewState() 2786 state.Lineage = "changing" 2787 s.WriteState(state) 2788 if err := s.PersistState(); err != nil { 2789 t.Fatalf("bad: %s", err) 2790 } 2791 2792 // Verify the state is where we expect 2793 { 2794 f, err := os.Open(DefaultStateFilename) 2795 if err != nil { 2796 t.Fatalf("err: %s", err) 2797 } 2798 actual, err := terraform.ReadState(f) 2799 f.Close() 2800 if err != nil { 2801 t.Fatalf("err: %s", err) 2802 } 2803 2804 if actual.Lineage != state.Lineage { 2805 t.Fatalf("bad: %#v", actual) 2806 } 2807 } 2808 2809 // Verify no local backup 2810 if !isEmptyState(DefaultStateFilename + DefaultBackupExtension) { 2811 t.Fatalf("backup state should be empty") 2812 } 2813 } 2814 2815 // A plan with a custom state save path 2816 func TestMetaBackend_planLocalStatePath(t *testing.T) { 2817 // Create a temporary working directory that is empty 2818 td := tempDir(t) 2819 copy.CopyDir(testFixturePath("backend-plan-local"), td) 2820 defer os.RemoveAll(td) 2821 defer testChdir(t, td)() 2822 2823 // Create our state 2824 original := testState() 2825 original.Lineage = "hello" 2826 2827 // Create the plan 2828 plan := &terraform.Plan{ 2829 Module: testModule(t, "backend-plan-local"), 2830 State: original, 2831 } 2832 2833 // Create an alternate output path 2834 statePath := "foo.tfstate" 2835 2836 // put a initial state there that needs to be backed up 2837 err := (&state.LocalState{Path: statePath}).WriteState(original) 2838 if err != nil { 2839 t.Fatal(err) 2840 } 2841 2842 // Setup the meta 2843 m := testMetaBackend(t, nil) 2844 m.stateOutPath = statePath 2845 2846 // Get the backend 2847 b, err := m.Backend(&BackendOpts{Plan: plan}) 2848 if err != nil { 2849 t.Fatalf("bad: %s", err) 2850 } 2851 2852 // Check the state 2853 s, err := b.State(backend.DefaultStateName) 2854 if err != nil { 2855 t.Fatalf("bad: %s", err) 2856 } 2857 if err := s.RefreshState(); err != nil { 2858 t.Fatalf("bad: %s", err) 2859 } 2860 state := s.State() 2861 if state == nil { 2862 t.Fatal("state is nil") 2863 } 2864 if state.Lineage != "hello" { 2865 t.Fatalf("bad: %#v", state) 2866 } 2867 2868 // Verify the default path doesn't exist 2869 if _, err := os.Stat(DefaultStateFilename); err == nil { 2870 t.Fatalf("err: %s", err) 2871 } 2872 2873 // Verify a backup doesn't exists 2874 if _, err := os.Stat(DefaultStateFilename + DefaultBackupExtension); err == nil { 2875 t.Fatal("file should not exist") 2876 } 2877 2878 // Verify we have no configured backend/legacy 2879 path := filepath.Join(m.DataDir(), DefaultStateFilename) 2880 if _, err := os.Stat(path); err == nil { 2881 t.Fatalf("should not have backend configured") 2882 } 2883 2884 // Write some state 2885 state = terraform.NewState() 2886 state.Lineage = "changing" 2887 s.WriteState(state) 2888 if err := s.PersistState(); err != nil { 2889 t.Fatalf("bad: %s", err) 2890 } 2891 2892 // Verify the state is where we expect 2893 { 2894 f, err := os.Open(statePath) 2895 if err != nil { 2896 t.Fatalf("err: %s", err) 2897 } 2898 actual, err := terraform.ReadState(f) 2899 f.Close() 2900 if err != nil { 2901 t.Fatalf("err: %s", err) 2902 } 2903 2904 if actual.Lineage != state.Lineage { 2905 t.Fatalf("bad: %#v", actual) 2906 } 2907 } 2908 2909 // Verify we have a backup 2910 if isEmptyState(statePath + DefaultBackupExtension) { 2911 t.Fatal("backup is empty") 2912 } 2913 } 2914 2915 // A plan that has no backend config, matching local state 2916 func TestMetaBackend_planLocalMatch(t *testing.T) { 2917 // Create a temporary working directory that is empty 2918 td := tempDir(t) 2919 copy.CopyDir(testFixturePath("backend-plan-local-match"), td) 2920 defer os.RemoveAll(td) 2921 defer testChdir(t, td)() 2922 2923 // Create the plan 2924 plan := &terraform.Plan{ 2925 Module: testModule(t, "backend-plan-local-match"), 2926 State: testStateRead(t, DefaultStateFilename), 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 2955 if isEmptyState(DefaultStateFilename) { 2956 t.Fatal("state is empty") 2957 } 2958 2959 // Verify a backup exists 2960 if _, err := os.Stat(DefaultStateFilename + DefaultBackupExtension); err != nil { 2961 t.Fatalf("err: %s", err) 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(DefaultStateFilename) 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 local backup 2996 if isEmptyState(DefaultStateFilename + DefaultBackupExtension) { 2997 t.Fatal("backup is empty") 2998 } 2999 } 3000 3001 // A plan that has no backend config, mismatched lineage 3002 func TestMetaBackend_planLocalMismatchLineage(t *testing.T) { 3003 // Create a temporary working directory that is empty 3004 td := tempDir(t) 3005 copy.CopyDir(testFixturePath("backend-plan-local-mismatch-lineage"), td) 3006 defer os.RemoveAll(td) 3007 defer testChdir(t, td)() 3008 3009 // Save the original 3010 original := testStateRead(t, DefaultStateFilename) 3011 3012 // Change the lineage 3013 planState := testStateRead(t, DefaultStateFilename) 3014 planState.Lineage = "bad" 3015 3016 // Create the plan 3017 plan := &terraform.Plan{ 3018 Module: testModule(t, "backend-plan-local-mismatch-lineage"), 3019 State: planState, 3020 } 3021 3022 // Setup the meta 3023 m := testMetaBackend(t, nil) 3024 3025 // Get the backend 3026 _, err := m.Backend(&BackendOpts{Plan: plan}) 3027 if err == nil { 3028 t.Fatal("should have error") 3029 } 3030 if !strings.Contains(err.Error(), "lineage") { 3031 t.Fatalf("bad: %s", err) 3032 } 3033 3034 // Verify our local state didn't change 3035 actual := testStateRead(t, DefaultStateFilename) 3036 if !actual.Equal(original) { 3037 t.Fatalf("bad: %#v", actual) 3038 } 3039 3040 // Verify a backup doesn't exists 3041 if _, err := os.Stat(DefaultStateFilename + DefaultBackupExtension); err == nil { 3042 t.Fatal("file should not exist") 3043 } 3044 3045 // Verify we have no configured backend/legacy 3046 path := filepath.Join(m.DataDir(), DefaultStateFilename) 3047 if _, err := os.Stat(path); err == nil { 3048 t.Fatalf("should not have backend configured") 3049 } 3050 } 3051 3052 // A plan that has no backend config, newer local 3053 func TestMetaBackend_planLocalNewer(t *testing.T) { 3054 // Create a temporary working directory that is empty 3055 td := tempDir(t) 3056 copy.CopyDir(testFixturePath("backend-plan-local-newer"), td) 3057 defer os.RemoveAll(td) 3058 defer testChdir(t, td)() 3059 3060 // Save the original 3061 original := testStateRead(t, DefaultStateFilename) 3062 3063 // Change the serial 3064 planState := testStateRead(t, DefaultStateFilename) 3065 planState.Serial = 7 3066 planState.RootModule().Dependencies = []string{"foo"} 3067 3068 // Create the plan 3069 plan := &terraform.Plan{ 3070 Module: testModule(t, "backend-plan-local-newer"), 3071 State: planState, 3072 } 3073 3074 // Setup the meta 3075 m := testMetaBackend(t, nil) 3076 3077 // Get the backend 3078 _, err := m.Backend(&BackendOpts{Plan: plan}) 3079 if err == nil { 3080 t.Fatal("should have error") 3081 } 3082 if !strings.Contains(err.Error(), "older") { 3083 t.Fatalf("bad: %s", err) 3084 } 3085 3086 // Verify our local state didn't change 3087 actual := testStateRead(t, DefaultStateFilename) 3088 if !actual.Equal(original) { 3089 t.Fatalf("bad: %#v", actual) 3090 } 3091 3092 // Verify a backup doesn't exists 3093 if _, err := os.Stat(DefaultStateFilename + DefaultBackupExtension); err == nil { 3094 t.Fatal("file should not exist") 3095 } 3096 3097 // Verify we have no configured backend/legacy 3098 path := filepath.Join(m.DataDir(), DefaultStateFilename) 3099 if _, err := os.Stat(path); err == nil { 3100 t.Fatalf("should not have backend configured") 3101 } 3102 } 3103 3104 // A plan that has a backend in an empty dir 3105 func TestMetaBackend_planBackendEmptyDir(t *testing.T) { 3106 // Create a temporary working directory that is empty 3107 td := tempDir(t) 3108 copy.CopyDir(testFixturePath("backend-plan-backend-empty"), td) 3109 defer os.RemoveAll(td) 3110 defer testChdir(t, td)() 3111 3112 // Get the state for the plan by getting the real state and 3113 // adding the backend config to it. 3114 original := testStateRead(t, filepath.Join( 3115 testFixturePath("backend-plan-backend-empty-config"), 3116 "local-state.tfstate")) 3117 backendState := testStateRead(t, filepath.Join( 3118 testFixturePath("backend-plan-backend-empty-config"), 3119 DefaultDataDir, DefaultStateFilename)) 3120 planState := original.DeepCopy() 3121 3122 // Create the plan 3123 plan := &terraform.Plan{ 3124 Module: testModule(t, "backend-plan-backend-empty-config"), 3125 State: planState, 3126 Backend: backendState.Backend, 3127 } 3128 3129 // Setup the meta 3130 m := testMetaBackend(t, nil) 3131 3132 // Get the backend 3133 b, err := m.Backend(&BackendOpts{Plan: plan}) 3134 if err != nil { 3135 t.Fatalf("bad: %s", err) 3136 } 3137 3138 // Check the state 3139 s, err := b.State(backend.DefaultStateName) 3140 if err != nil { 3141 t.Fatalf("bad: %s", err) 3142 } 3143 if err := s.RefreshState(); err != nil { 3144 t.Fatalf("bad: %s", err) 3145 } 3146 state := s.State() 3147 if state == nil { 3148 t.Fatal("should is nil") 3149 } 3150 if state.Lineage != "hello" { 3151 t.Fatalf("bad: %#v", state) 3152 } 3153 3154 // Verify the default path doesn't exist 3155 if !isEmptyState(DefaultStateFilename) { 3156 t.Fatal("state is not empty") 3157 } 3158 3159 // Verify a backup doesn't exist 3160 if !isEmptyState(DefaultStateFilename + DefaultBackupExtension) { 3161 t.Fatal("backup is not empty") 3162 } 3163 3164 // Verify we have no configured backend/legacy 3165 path := filepath.Join(m.DataDir(), DefaultStateFilename) 3166 if _, err := os.Stat(path); err == nil { 3167 t.Fatalf("should not have backend configured") 3168 } 3169 3170 // Write some state 3171 state = terraform.NewState() 3172 state.Lineage = "changing" 3173 s.WriteState(state) 3174 if err := s.PersistState(); err != nil { 3175 t.Fatalf("bad: %s", err) 3176 } 3177 3178 // Verify the state is where we expect 3179 { 3180 f, err := os.Open("local-state.tfstate") 3181 if err != nil { 3182 t.Fatalf("err: %s", err) 3183 } 3184 actual, err := terraform.ReadState(f) 3185 f.Close() 3186 if err != nil { 3187 t.Fatalf("err: %s", err) 3188 } 3189 3190 if actual.Lineage != state.Lineage { 3191 t.Fatalf("bad: %#v", actual) 3192 } 3193 } 3194 3195 // Verify no default path 3196 if _, err := os.Stat(DefaultStateFilename); err == nil { 3197 t.Fatal("file should not exist") 3198 } 3199 3200 // Verify no local backup 3201 if _, err := os.Stat(DefaultStateFilename + DefaultBackupExtension); err == nil { 3202 t.Fatal("file should not exist") 3203 } 3204 } 3205 3206 // A plan that has a backend with matching state 3207 func TestMetaBackend_planBackendMatch(t *testing.T) { 3208 // Create a temporary working directory that is empty 3209 td := tempDir(t) 3210 copy.CopyDir(testFixturePath("backend-plan-backend-match"), td) 3211 defer os.RemoveAll(td) 3212 defer testChdir(t, td)() 3213 3214 // Get the state for the plan by getting the real state and 3215 // adding the backend config to it. 3216 original := testStateRead(t, filepath.Join( 3217 testFixturePath("backend-plan-backend-empty-config"), 3218 "local-state.tfstate")) 3219 backendState := testStateRead(t, filepath.Join( 3220 testFixturePath("backend-plan-backend-empty-config"), 3221 DefaultDataDir, DefaultStateFilename)) 3222 planState := original.DeepCopy() 3223 3224 // Create the plan 3225 plan := &terraform.Plan{ 3226 Module: testModule(t, "backend-plan-backend-empty-config"), 3227 State: planState, 3228 Backend: backendState.Backend, 3229 } 3230 3231 // Setup the meta 3232 m := testMetaBackend(t, nil) 3233 3234 // Get the backend 3235 b, err := m.Backend(&BackendOpts{Plan: plan}) 3236 if err != nil { 3237 t.Fatalf("bad: %s", err) 3238 } 3239 3240 // Check the state 3241 s, err := b.State(backend.DefaultStateName) 3242 if err != nil { 3243 t.Fatalf("bad: %s", err) 3244 } 3245 if err := s.RefreshState(); err != nil { 3246 t.Fatalf("bad: %s", err) 3247 } 3248 state := s.State() 3249 if state == nil { 3250 t.Fatal("should is nil") 3251 } 3252 if state.Lineage != "hello" { 3253 t.Fatalf("bad: %#v", state) 3254 } 3255 3256 // Verify the default path exists 3257 if _, err := os.Stat(DefaultStateFilename); err == nil { 3258 t.Fatal("file should not exist") 3259 } 3260 3261 // Verify a backup doesn't exist 3262 if _, err := os.Stat(DefaultStateFilename + DefaultBackupExtension); err == nil { 3263 t.Fatal("file should not exist") 3264 } 3265 3266 // Verify we have no configured backend/legacy 3267 path := filepath.Join(m.DataDir(), DefaultStateFilename) 3268 if _, err := os.Stat(path); err == nil { 3269 t.Fatalf("should not have backend configured") 3270 } 3271 3272 // Write some state 3273 state = terraform.NewState() 3274 state.Lineage = "changing" 3275 s.WriteState(state) 3276 if err := s.PersistState(); err != nil { 3277 t.Fatalf("bad: %s", err) 3278 } 3279 3280 // Verify the state is where we expect 3281 { 3282 f, err := os.Open("local-state.tfstate") 3283 if err != nil { 3284 t.Fatalf("err: %s", err) 3285 } 3286 actual, err := terraform.ReadState(f) 3287 f.Close() 3288 if err != nil { 3289 t.Fatalf("err: %s", err) 3290 } 3291 3292 if actual.Lineage != state.Lineage { 3293 t.Fatalf("bad: %#v", actual) 3294 } 3295 } 3296 3297 // Verify no default path 3298 if _, err := os.Stat(DefaultStateFilename); err == nil { 3299 t.Fatal("file should not exist") 3300 } 3301 3302 // Verify no local backup 3303 if _, err := os.Stat(DefaultStateFilename + DefaultBackupExtension); err == nil { 3304 t.Fatal("file should not exist") 3305 } 3306 } 3307 3308 // A plan that has a backend with mismatching lineage 3309 func TestMetaBackend_planBackendMismatchLineage(t *testing.T) { 3310 // Create a temporary working directory that is empty 3311 td := tempDir(t) 3312 copy.CopyDir(testFixturePath("backend-plan-backend-mismatch"), td) 3313 defer os.RemoveAll(td) 3314 defer testChdir(t, td)() 3315 3316 // Get the state for the plan by getting the real state and 3317 // adding the backend config to it. 3318 original := testStateRead(t, filepath.Join( 3319 testFixturePath("backend-plan-backend-empty-config"), 3320 "local-state.tfstate")) 3321 backendState := testStateRead(t, filepath.Join( 3322 testFixturePath("backend-plan-backend-empty-config"), 3323 DefaultDataDir, DefaultStateFilename)) 3324 planState := original.DeepCopy() 3325 3326 // Get the real original 3327 original = testStateRead(t, "local-state.tfstate") 3328 3329 // Create the plan 3330 plan := &terraform.Plan{ 3331 Module: testModule(t, "backend-plan-backend-empty-config"), 3332 State: planState, 3333 Backend: backendState.Backend, 3334 } 3335 3336 // Setup the meta 3337 m := testMetaBackend(t, nil) 3338 3339 // Get the backend 3340 _, err := m.Backend(&BackendOpts{Plan: plan}) 3341 if err == nil { 3342 t.Fatal("should have error") 3343 } 3344 if !strings.Contains(err.Error(), "lineage") { 3345 t.Fatalf("bad: %s", err) 3346 } 3347 3348 // Verify our local state didn't change 3349 actual := testStateRead(t, "local-state.tfstate") 3350 if !actual.Equal(original) { 3351 t.Fatalf("bad: %#v", actual) 3352 } 3353 3354 // Verify a backup doesn't exist 3355 if _, err := os.Stat(DefaultStateFilename + DefaultBackupExtension); err == nil { 3356 t.Fatal("file should not exist") 3357 } 3358 3359 // Verify we have no configured backend/legacy 3360 path := filepath.Join(m.DataDir(), DefaultStateFilename) 3361 if _, err := os.Stat(path); err == nil { 3362 t.Fatalf("should not have backend configured") 3363 } 3364 3365 // Verify we have no default state 3366 if _, err := os.Stat(DefaultStateFilename); err == nil { 3367 t.Fatal("file should not exist") 3368 } 3369 } 3370 3371 // A plan that has a legacy remote state 3372 func TestMetaBackend_planLegacy(t *testing.T) { 3373 // Create a temporary working directory that is empty 3374 td := tempDir(t) 3375 copy.CopyDir(testFixturePath("backend-plan-legacy"), td) 3376 defer os.RemoveAll(td) 3377 defer testChdir(t, td)() 3378 3379 // Get the state for the plan by getting the real state and 3380 // adding the backend config to it. 3381 original := testStateRead(t, filepath.Join( 3382 testFixturePath("backend-plan-legacy-data"), "local-state.tfstate")) 3383 dataState := testStateRead(t, filepath.Join( 3384 testFixturePath("backend-plan-legacy-data"), "state.tfstate")) 3385 planState := original.DeepCopy() 3386 planState.Remote = dataState.Remote 3387 3388 // Create the plan 3389 plan := &terraform.Plan{ 3390 Module: testModule(t, "backend-plan-legacy-data"), 3391 State: planState, 3392 } 3393 3394 // Setup the meta 3395 m := testMetaBackend(t, nil) 3396 3397 // Get the backend 3398 b, err := m.Backend(&BackendOpts{Plan: plan}) 3399 if err != nil { 3400 t.Fatalf("err: %s", err) 3401 } 3402 3403 // Check the state 3404 s, err := b.State(backend.DefaultStateName) 3405 if err != nil { 3406 t.Fatalf("bad: %s", err) 3407 } 3408 if err := s.RefreshState(); err != nil { 3409 t.Fatalf("bad: %s", err) 3410 } 3411 state := s.State() 3412 if state == nil { 3413 t.Fatal("should is nil") 3414 } 3415 if state.Lineage != "hello" { 3416 t.Fatalf("bad: %#v", state) 3417 } 3418 3419 // Verify the default path 3420 if _, err := os.Stat(DefaultStateFilename); err == nil { 3421 t.Fatal("file should not exist") 3422 } 3423 3424 // Verify a backup doesn't exist 3425 if _, err := os.Stat(DefaultStateFilename + DefaultBackupExtension); err == nil { 3426 t.Fatal("file should not exist") 3427 } 3428 3429 // Verify we have no configured backend/legacy 3430 path := filepath.Join(m.DataDir(), DefaultStateFilename) 3431 if _, err := os.Stat(path); err == nil { 3432 t.Fatalf("should not have backend configured") 3433 } 3434 3435 // Write some state 3436 state = terraform.NewState() 3437 state.Lineage = "changing" 3438 s.WriteState(state) 3439 if err := s.PersistState(); err != nil { 3440 t.Fatalf("bad: %s", err) 3441 } 3442 3443 // Verify the state is where we expect 3444 { 3445 f, err := os.Open("local-state.tfstate") 3446 if err != nil { 3447 t.Fatalf("err: %s", err) 3448 } 3449 actual, err := terraform.ReadState(f) 3450 f.Close() 3451 if err != nil { 3452 t.Fatalf("err: %s", err) 3453 } 3454 3455 if actual.Lineage != state.Lineage { 3456 t.Fatalf("bad: %#v", actual) 3457 } 3458 } 3459 3460 // Verify no default path 3461 if _, err := os.Stat(DefaultStateFilename); err == nil { 3462 t.Fatal("file should not exist") 3463 } 3464 3465 // Verify no local backup 3466 if _, err := os.Stat(DefaultStateFilename + DefaultBackupExtension); err == nil { 3467 t.Fatal("file should not exist") 3468 } 3469 } 3470 3471 // init a backend using -backend-config options multiple times 3472 func TestMetaBackend_configureWithExtra(t *testing.T) { 3473 // Create a temporary working directory that is empty 3474 td := tempDir(t) 3475 copy.CopyDir(testFixturePath("init-backend-empty"), td) 3476 defer os.RemoveAll(td) 3477 defer testChdir(t, td)() 3478 3479 extras := map[string]interface{}{"path": "hello"} 3480 m := testMetaBackend(t, nil) 3481 opts := &BackendOpts{ 3482 ConfigExtra: extras, 3483 Init: true, 3484 } 3485 3486 backendCfg, err := m.backendConfig(opts) 3487 if err != nil { 3488 t.Fatal(err) 3489 } 3490 3491 // init the backend 3492 _, err = m.Backend(&BackendOpts{ 3493 ConfigExtra: extras, 3494 Init: true, 3495 }) 3496 if err != nil { 3497 t.Fatalf("bad: %s", err) 3498 } 3499 3500 // Check the state 3501 s := testStateRead(t, filepath.Join(DefaultDataDir, backendLocal.DefaultStateFilename)) 3502 if s.Backend.Hash != backendCfg.Hash { 3503 t.Fatal("mismatched state and config backend hashes") 3504 } 3505 if s.Backend.Rehash() == s.Backend.Hash { 3506 t.Fatal("saved hash should not match actual hash") 3507 } 3508 if s.Backend.Rehash() != backendCfg.Rehash() { 3509 t.Fatal("mismatched state and config re-hashes") 3510 } 3511 3512 // init the backend again with the same options 3513 m = testMetaBackend(t, nil) 3514 _, err = m.Backend(&BackendOpts{ 3515 ConfigExtra: extras, 3516 Init: true, 3517 }) 3518 if err != nil { 3519 t.Fatalf("bad: %s", err) 3520 } 3521 3522 // Check the state 3523 s = testStateRead(t, filepath.Join(DefaultDataDir, backendLocal.DefaultStateFilename)) 3524 if s.Backend.Hash != backendCfg.Hash { 3525 t.Fatal("mismatched state and config backend hashes") 3526 } 3527 } 3528 3529 // when confniguring a default local state, don't delete local state 3530 func TestMetaBackend_localDoesNotDeleteLocal(t *testing.T) { 3531 // Create a temporary working directory that is empty 3532 td := tempDir(t) 3533 copy.CopyDir(testFixturePath("init-backend-empty"), td) 3534 defer os.RemoveAll(td) 3535 defer testChdir(t, td)() 3536 3537 // create our local state 3538 orig := &terraform.State{ 3539 Modules: []*terraform.ModuleState{ 3540 { 3541 Path: []string{"root"}, 3542 Outputs: map[string]*terraform.OutputState{ 3543 "foo": { 3544 Value: "bar", 3545 Type: "string", 3546 }, 3547 }, 3548 }, 3549 }, 3550 } 3551 3552 err := (&state.LocalState{Path: DefaultStateFilename}).WriteState(orig) 3553 if err != nil { 3554 t.Fatal(err) 3555 } 3556 3557 m := testMetaBackend(t, nil) 3558 m.forceInitCopy = true 3559 // init the backend 3560 _, err = m.Backend(&BackendOpts{ 3561 Init: true, 3562 }) 3563 if err != nil { 3564 t.Fatalf("bad: %s", err) 3565 } 3566 3567 // check that we can read the state 3568 s := testStateRead(t, DefaultStateFilename) 3569 if s.Empty() { 3570 t.Fatal("our state was deleted") 3571 } 3572 } 3573 3574 // move options from config to -backend-config 3575 func TestMetaBackend_configToExtra(t *testing.T) { 3576 // Create a temporary working directory that is empty 3577 td := tempDir(t) 3578 copy.CopyDir(testFixturePath("init-backend"), td) 3579 defer os.RemoveAll(td) 3580 defer testChdir(t, td)() 3581 3582 // init the backend 3583 m := testMetaBackend(t, nil) 3584 _, err := m.Backend(&BackendOpts{ 3585 Init: true, 3586 }) 3587 if err != nil { 3588 t.Fatalf("bad: %s", err) 3589 } 3590 3591 // Check the state 3592 s := testStateRead(t, filepath.Join(DefaultDataDir, backendLocal.DefaultStateFilename)) 3593 backendHash := s.Backend.Hash 3594 3595 // init again but remove the path option from the config 3596 cfg := "terraform {\n backend \"local\" {}\n}\n" 3597 if err := ioutil.WriteFile("main.tf", []byte(cfg), 0644); err != nil { 3598 t.Fatal(err) 3599 } 3600 3601 // init the backend again with the options 3602 extras := map[string]interface{}{"path": "hello"} 3603 m = testMetaBackend(t, nil) 3604 m.forceInitCopy = true 3605 _, err = m.Backend(&BackendOpts{ 3606 ConfigExtra: extras, 3607 Init: true, 3608 }) 3609 if err != nil { 3610 t.Fatalf("bad: %s", err) 3611 } 3612 3613 s = testStateRead(t, filepath.Join(DefaultDataDir, backendLocal.DefaultStateFilename)) 3614 3615 if s.Backend.Hash == backendHash { 3616 t.Fatal("state.Backend.Hash was not updated") 3617 } 3618 } 3619 3620 func testMetaBackend(t *testing.T, args []string) *Meta { 3621 var m Meta 3622 m.Ui = new(cli.MockUi) 3623 m.process(args, true) 3624 f := m.flagSet("test") 3625 if err := f.Parse(args); err != nil { 3626 t.Fatalf("bad: %s", err) 3627 } 3628 3629 return &m 3630 }