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