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