github.com/memsql/terraform@v0.7.0-rc2.0.20160706152241-21e2173e0a32/command/refresh_test.go (about) 1 package command 2 3 import ( 4 "bytes" 5 "io/ioutil" 6 "os" 7 "path/filepath" 8 "reflect" 9 "strings" 10 "testing" 11 12 "github.com/hashicorp/terraform/terraform" 13 "github.com/mitchellh/cli" 14 ) 15 16 func TestRefresh(t *testing.T) { 17 state := testState() 18 statePath := testStateFile(t, state) 19 20 p := testProvider() 21 ui := new(cli.MockUi) 22 c := &RefreshCommand{ 23 Meta: Meta{ 24 ContextOpts: testCtxConfig(p), 25 Ui: ui, 26 }, 27 } 28 29 p.RefreshFn = nil 30 p.RefreshReturn = &terraform.InstanceState{ID: "yes"} 31 32 args := []string{ 33 "-state", statePath, 34 testFixturePath("refresh"), 35 } 36 if code := c.Run(args); code != 0 { 37 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 38 } 39 40 if !p.RefreshCalled { 41 t.Fatal("refresh should be called") 42 } 43 44 f, err := os.Open(statePath) 45 if err != nil { 46 t.Fatalf("err: %s", err) 47 } 48 49 newState, err := terraform.ReadState(f) 50 f.Close() 51 if err != nil { 52 t.Fatalf("err: %s", err) 53 } 54 55 actual := strings.TrimSpace(newState.String()) 56 expected := strings.TrimSpace(testRefreshStr) 57 if actual != expected { 58 t.Fatalf("bad:\n\n%s", actual) 59 } 60 } 61 62 func TestRefresh_badState(t *testing.T) { 63 p := testProvider() 64 ui := new(cli.MockUi) 65 c := &RefreshCommand{ 66 Meta: Meta{ 67 ContextOpts: testCtxConfig(p), 68 Ui: ui, 69 }, 70 } 71 72 args := []string{ 73 "-state", "i-should-not-exist-ever", 74 testFixturePath("refresh"), 75 } 76 if code := c.Run(args); code != 1 { 77 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 78 } 79 } 80 81 func TestRefresh_cwd(t *testing.T) { 82 cwd, err := os.Getwd() 83 if err != nil { 84 t.Fatalf("err: %s", err) 85 } 86 if err := os.Chdir(testFixturePath("refresh")); err != nil { 87 t.Fatalf("err: %s", err) 88 } 89 defer os.Chdir(cwd) 90 91 state := testState() 92 statePath := testStateFile(t, state) 93 94 p := testProvider() 95 ui := new(cli.MockUi) 96 c := &RefreshCommand{ 97 Meta: Meta{ 98 ContextOpts: testCtxConfig(p), 99 Ui: ui, 100 }, 101 } 102 103 p.RefreshFn = nil 104 p.RefreshReturn = &terraform.InstanceState{ID: "yes"} 105 106 args := []string{ 107 "-state", statePath, 108 } 109 if code := c.Run(args); code != 0 { 110 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 111 } 112 113 if !p.RefreshCalled { 114 t.Fatal("refresh should be called") 115 } 116 117 f, err := os.Open(statePath) 118 if err != nil { 119 t.Fatalf("err: %s", err) 120 } 121 122 newState, err := terraform.ReadState(f) 123 f.Close() 124 if err != nil { 125 t.Fatalf("err: %s", err) 126 } 127 128 actual := strings.TrimSpace(newState.String()) 129 expected := strings.TrimSpace(testRefreshCwdStr) 130 if actual != expected { 131 t.Fatalf("bad:\n\n%s", actual) 132 } 133 } 134 135 func TestRefresh_defaultState(t *testing.T) { 136 originalState := testState() 137 138 // Write the state file in a temporary directory with the 139 // default filename. 140 td, err := ioutil.TempDir("", "tf") 141 if err != nil { 142 t.Fatalf("err: %s", err) 143 } 144 statePath := filepath.Join(td, DefaultStateFilename) 145 146 f, err := os.Create(statePath) 147 if err != nil { 148 t.Fatalf("err: %s", err) 149 } 150 err = terraform.WriteState(originalState, f) 151 f.Close() 152 if err != nil { 153 t.Fatalf("err: %s", err) 154 } 155 156 // Change to that directory 157 cwd, err := os.Getwd() 158 if err != nil { 159 t.Fatalf("err: %s", err) 160 } 161 if err := os.Chdir(filepath.Dir(statePath)); err != nil { 162 t.Fatalf("err: %s", err) 163 } 164 defer os.Chdir(cwd) 165 166 p := testProvider() 167 ui := new(cli.MockUi) 168 c := &RefreshCommand{ 169 Meta: Meta{ 170 ContextOpts: testCtxConfig(p), 171 Ui: ui, 172 }, 173 } 174 175 p.RefreshFn = nil 176 p.RefreshReturn = &terraform.InstanceState{ID: "yes"} 177 178 args := []string{ 179 testFixturePath("refresh"), 180 } 181 if code := c.Run(args); code != 0 { 182 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 183 } 184 185 if !p.RefreshCalled { 186 t.Fatal("refresh should be called") 187 } 188 189 f, err = os.Open(statePath) 190 if err != nil { 191 t.Fatalf("err: %s", err) 192 } 193 194 newState, err := terraform.ReadState(f) 195 f.Close() 196 if err != nil { 197 t.Fatalf("err: %s", err) 198 } 199 200 actual := newState.RootModule().Resources["test_instance.foo"].Primary 201 expected := p.RefreshReturn 202 if !reflect.DeepEqual(actual, expected) { 203 t.Fatalf("bad: %#v", actual) 204 } 205 206 f, err = os.Open(statePath + DefaultBackupExtension) 207 if err != nil { 208 t.Fatalf("err: %s", err) 209 } 210 211 backupState, err := terraform.ReadState(f) 212 f.Close() 213 if err != nil { 214 t.Fatalf("err: %s", err) 215 } 216 217 actual = backupState.RootModule().Resources["test_instance.foo"].Primary 218 expected = originalState.RootModule().Resources["test_instance.foo"].Primary 219 if !reflect.DeepEqual(actual, expected) { 220 t.Fatalf("bad: %#v", actual) 221 } 222 } 223 224 func TestRefresh_futureState(t *testing.T) { 225 cwd, err := os.Getwd() 226 if err != nil { 227 t.Fatalf("err: %s", err) 228 } 229 if err := os.Chdir(testFixturePath("refresh")); err != nil { 230 t.Fatalf("err: %s", err) 231 } 232 defer os.Chdir(cwd) 233 234 state := testState() 235 state.TFVersion = "99.99.99" 236 statePath := testStateFile(t, state) 237 238 p := testProvider() 239 ui := new(cli.MockUi) 240 c := &RefreshCommand{ 241 Meta: Meta{ 242 ContextOpts: testCtxConfig(p), 243 Ui: ui, 244 }, 245 } 246 247 args := []string{ 248 "-state", statePath, 249 } 250 if code := c.Run(args); code == 0 { 251 t.Fatal("should fail") 252 } 253 254 if p.RefreshCalled { 255 t.Fatal("refresh should not be called") 256 } 257 258 f, err := os.Open(statePath) 259 if err != nil { 260 t.Fatalf("err: %s", err) 261 } 262 263 newState, err := terraform.ReadState(f) 264 f.Close() 265 if err != nil { 266 t.Fatalf("err: %s", err) 267 } 268 269 actual := strings.TrimSpace(newState.String()) 270 expected := strings.TrimSpace(state.String()) 271 if actual != expected { 272 t.Fatalf("bad:\n\n%s", actual) 273 } 274 } 275 276 func TestRefresh_pastState(t *testing.T) { 277 state := testState() 278 state.TFVersion = "0.1.0" 279 statePath := testStateFile(t, state) 280 281 p := testProvider() 282 ui := new(cli.MockUi) 283 c := &RefreshCommand{ 284 Meta: Meta{ 285 ContextOpts: testCtxConfig(p), 286 Ui: ui, 287 }, 288 } 289 290 p.RefreshFn = nil 291 p.RefreshReturn = &terraform.InstanceState{ID: "yes"} 292 293 args := []string{ 294 "-state", statePath, 295 testFixturePath("refresh"), 296 } 297 if code := c.Run(args); code != 0 { 298 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 299 } 300 301 if !p.RefreshCalled { 302 t.Fatal("refresh should be called") 303 } 304 305 f, err := os.Open(statePath) 306 if err != nil { 307 t.Fatalf("err: %s", err) 308 } 309 310 newState, err := terraform.ReadState(f) 311 f.Close() 312 if err != nil { 313 t.Fatalf("err: %s", err) 314 } 315 316 actual := strings.TrimSpace(newState.String()) 317 expected := strings.TrimSpace(testRefreshStr) 318 if actual != expected { 319 t.Fatalf("bad:\n\n%s", actual) 320 } 321 322 if newState.TFVersion != terraform.Version { 323 t.Fatalf("bad:\n\n%s", newState.TFVersion) 324 } 325 } 326 327 func TestRefresh_outPath(t *testing.T) { 328 state := testState() 329 statePath := testStateFile(t, state) 330 331 // Output path 332 outf, err := ioutil.TempFile("", "tf") 333 if err != nil { 334 t.Fatalf("err: %s", err) 335 } 336 outPath := outf.Name() 337 outf.Close() 338 os.Remove(outPath) 339 340 p := testProvider() 341 ui := new(cli.MockUi) 342 c := &RefreshCommand{ 343 Meta: Meta{ 344 ContextOpts: testCtxConfig(p), 345 Ui: ui, 346 }, 347 } 348 349 p.RefreshFn = nil 350 p.RefreshReturn = &terraform.InstanceState{ID: "yes"} 351 352 args := []string{ 353 "-state", statePath, 354 "-state-out", outPath, 355 testFixturePath("refresh"), 356 } 357 if code := c.Run(args); code != 0 { 358 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 359 } 360 361 f, err := os.Open(statePath) 362 if err != nil { 363 t.Fatalf("err: %s", err) 364 } 365 366 newState, err := terraform.ReadState(f) 367 f.Close() 368 if err != nil { 369 t.Fatalf("err: %s", err) 370 } 371 372 if !reflect.DeepEqual(newState, state) { 373 t.Fatalf("bad: %#v", newState) 374 } 375 376 f, err = os.Open(outPath) 377 if err != nil { 378 t.Fatalf("err: %s", err) 379 } 380 381 newState, err = terraform.ReadState(f) 382 f.Close() 383 if err != nil { 384 t.Fatalf("err: %s", err) 385 } 386 387 actual := newState.RootModule().Resources["test_instance.foo"].Primary 388 expected := p.RefreshReturn 389 if !reflect.DeepEqual(actual, expected) { 390 t.Fatalf("bad: %#v", actual) 391 } 392 393 f, err = os.Open(outPath + DefaultBackupExtension) 394 if err != nil { 395 t.Fatalf("err: %s", err) 396 } 397 398 backupState, err := terraform.ReadState(f) 399 f.Close() 400 if err != nil { 401 t.Fatalf("err: %s", err) 402 } 403 404 actualStr := strings.TrimSpace(backupState.String()) 405 expectedStr := strings.TrimSpace(state.String()) 406 if actualStr != expectedStr { 407 t.Fatalf("bad:\n\n%s\n\n%s", actualStr, expectedStr) 408 } 409 } 410 411 func TestRefresh_var(t *testing.T) { 412 state := testState() 413 statePath := testStateFile(t, state) 414 415 p := testProvider() 416 ui := new(cli.MockUi) 417 c := &RefreshCommand{ 418 Meta: Meta{ 419 ContextOpts: testCtxConfig(p), 420 Ui: ui, 421 }, 422 } 423 424 args := []string{ 425 "-var", "foo=bar", 426 "-state", statePath, 427 testFixturePath("refresh-var"), 428 } 429 if code := c.Run(args); code != 0 { 430 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 431 } 432 433 if !p.ConfigureCalled { 434 t.Fatal("configure should be called") 435 } 436 if p.ConfigureConfig.Config["value"].(string) != "bar" { 437 t.Fatalf("bad: %#v", p.ConfigureConfig.Config) 438 } 439 } 440 441 func TestRefresh_varFile(t *testing.T) { 442 state := testState() 443 statePath := testStateFile(t, state) 444 445 p := testProvider() 446 ui := new(cli.MockUi) 447 c := &RefreshCommand{ 448 Meta: Meta{ 449 ContextOpts: testCtxConfig(p), 450 Ui: ui, 451 }, 452 } 453 454 varFilePath := testTempFile(t) 455 if err := ioutil.WriteFile(varFilePath, []byte(refreshVarFile), 0644); err != nil { 456 t.Fatalf("err: %s", err) 457 } 458 459 args := []string{ 460 "-var-file", varFilePath, 461 "-state", statePath, 462 testFixturePath("refresh-var"), 463 } 464 if code := c.Run(args); code != 0 { 465 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 466 } 467 468 if !p.ConfigureCalled { 469 t.Fatal("configure should be called") 470 } 471 if p.ConfigureConfig.Config["value"].(string) != "bar" { 472 t.Fatalf("bad: %#v", p.ConfigureConfig.Config) 473 } 474 } 475 476 func TestRefresh_varFileDefault(t *testing.T) { 477 state := testState() 478 statePath := testStateFile(t, state) 479 480 p := testProvider() 481 ui := new(cli.MockUi) 482 c := &RefreshCommand{ 483 Meta: Meta{ 484 ContextOpts: testCtxConfig(p), 485 Ui: ui, 486 }, 487 } 488 489 varFileDir := testTempDir(t) 490 varFilePath := filepath.Join(varFileDir, "terraform.tfvars") 491 if err := ioutil.WriteFile(varFilePath, []byte(refreshVarFile), 0644); err != nil { 492 t.Fatalf("err: %s", err) 493 } 494 495 cwd, err := os.Getwd() 496 if err != nil { 497 t.Fatalf("err: %s", err) 498 } 499 if err := os.Chdir(varFileDir); err != nil { 500 t.Fatalf("err: %s", err) 501 } 502 defer os.Chdir(cwd) 503 504 args := []string{ 505 "-state", statePath, 506 testFixturePath("refresh-var"), 507 } 508 if code := c.Run(args); code != 0 { 509 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 510 } 511 512 if !p.ConfigureCalled { 513 t.Fatal("configure should be called") 514 } 515 if p.ConfigureConfig.Config["value"].(string) != "bar" { 516 t.Fatalf("bad: %#v", p.ConfigureConfig.Config) 517 } 518 } 519 520 func TestRefresh_varsUnset(t *testing.T) { 521 // Disable test mode so input would be asked 522 test = false 523 defer func() { test = true }() 524 525 defaultInputReader = bytes.NewBufferString("bar\n") 526 527 state := testState() 528 statePath := testStateFile(t, state) 529 530 p := testProvider() 531 ui := new(cli.MockUi) 532 c := &RefreshCommand{ 533 Meta: Meta{ 534 ContextOpts: testCtxConfig(p), 535 Ui: ui, 536 }, 537 } 538 539 args := []string{ 540 "-state", statePath, 541 testFixturePath("refresh-unset-var"), 542 } 543 if code := c.Run(args); code != 0 { 544 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 545 } 546 } 547 548 func TestRefresh_backup(t *testing.T) { 549 state := testState() 550 statePath := testStateFile(t, state) 551 552 // Output path 553 outf, err := ioutil.TempFile("", "tf") 554 if err != nil { 555 t.Fatalf("err: %s", err) 556 } 557 outPath := outf.Name() 558 outf.Close() 559 os.Remove(outPath) 560 561 // Backup path 562 backupf, err := ioutil.TempFile("", "tf") 563 if err != nil { 564 t.Fatalf("err: %s", err) 565 } 566 backupPath := backupf.Name() 567 backupf.Close() 568 os.Remove(backupPath) 569 570 p := testProvider() 571 ui := new(cli.MockUi) 572 c := &RefreshCommand{ 573 Meta: Meta{ 574 ContextOpts: testCtxConfig(p), 575 Ui: ui, 576 }, 577 } 578 579 p.RefreshFn = nil 580 p.RefreshReturn = &terraform.InstanceState{ID: "yes"} 581 582 args := []string{ 583 "-state", statePath, 584 "-state-out", outPath, 585 "-backup", backupPath, 586 testFixturePath("refresh"), 587 } 588 if code := c.Run(args); code != 0 { 589 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 590 } 591 592 f, err := os.Open(statePath) 593 if err != nil { 594 t.Fatalf("err: %s", err) 595 } 596 597 newState, err := terraform.ReadState(f) 598 f.Close() 599 if err != nil { 600 t.Fatalf("err: %s", err) 601 } 602 603 if !reflect.DeepEqual(newState, state) { 604 t.Fatalf("bad: %#v", newState) 605 } 606 607 f, err = os.Open(outPath) 608 if err != nil { 609 t.Fatalf("err: %s", err) 610 } 611 612 newState, err = terraform.ReadState(f) 613 f.Close() 614 if err != nil { 615 t.Fatalf("err: %s", err) 616 } 617 618 actual := newState.RootModule().Resources["test_instance.foo"].Primary 619 expected := p.RefreshReturn 620 if !reflect.DeepEqual(actual, expected) { 621 t.Fatalf("bad: %#v", actual) 622 } 623 624 f, err = os.Open(backupPath) 625 if err != nil { 626 t.Fatalf("err: %s", err) 627 } 628 629 backupState, err := terraform.ReadState(f) 630 f.Close() 631 if err != nil { 632 t.Fatalf("err: %s", err) 633 } 634 635 actualStr := strings.TrimSpace(backupState.String()) 636 expectedStr := strings.TrimSpace(state.String()) 637 if actualStr != expectedStr { 638 t.Fatalf("bad:\n\n%s\n\n%s", actualStr, expectedStr) 639 } 640 } 641 642 func TestRefresh_disableBackup(t *testing.T) { 643 state := testState() 644 statePath := testStateFile(t, state) 645 646 // Output path 647 outf, err := ioutil.TempFile("", "tf") 648 if err != nil { 649 t.Fatalf("err: %s", err) 650 } 651 outPath := outf.Name() 652 outf.Close() 653 os.Remove(outPath) 654 655 p := testProvider() 656 ui := new(cli.MockUi) 657 c := &RefreshCommand{ 658 Meta: Meta{ 659 ContextOpts: testCtxConfig(p), 660 Ui: ui, 661 }, 662 } 663 664 p.RefreshFn = nil 665 p.RefreshReturn = &terraform.InstanceState{ID: "yes"} 666 667 args := []string{ 668 "-state", statePath, 669 "-state-out", outPath, 670 "-backup", "-", 671 testFixturePath("refresh"), 672 } 673 if code := c.Run(args); code != 0 { 674 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 675 } 676 677 f, err := os.Open(statePath) 678 if err != nil { 679 t.Fatalf("err: %s", err) 680 } 681 682 newState, err := terraform.ReadState(f) 683 f.Close() 684 if err != nil { 685 t.Fatalf("err: %s", err) 686 } 687 688 if !reflect.DeepEqual(newState, state) { 689 t.Fatalf("bad: %#v", newState) 690 } 691 692 f, err = os.Open(outPath) 693 if err != nil { 694 t.Fatalf("err: %s", err) 695 } 696 697 newState, err = terraform.ReadState(f) 698 f.Close() 699 if err != nil { 700 t.Fatalf("err: %s", err) 701 } 702 703 actual := newState.RootModule().Resources["test_instance.foo"].Primary 704 expected := p.RefreshReturn 705 if !reflect.DeepEqual(actual, expected) { 706 t.Fatalf("bad: %#v", actual) 707 } 708 709 // Ensure there is no backup 710 _, err = os.Stat(outPath + DefaultBackupExtension) 711 if err == nil || !os.IsNotExist(err) { 712 t.Fatalf("backup should not exist") 713 } 714 } 715 716 func TestRefresh_displaysOutputs(t *testing.T) { 717 state := testState() 718 statePath := testStateFile(t, state) 719 720 p := testProvider() 721 ui := new(cli.MockUi) 722 c := &RefreshCommand{ 723 Meta: Meta{ 724 ContextOpts: testCtxConfig(p), 725 Ui: ui, 726 }, 727 } 728 729 args := []string{ 730 "-state", statePath, 731 testFixturePath("refresh-output"), 732 } 733 if code := c.Run(args); code != 0 { 734 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 735 } 736 737 // Test that outputs were displayed 738 outputValue := "foo.example.com" 739 actual := ui.OutputWriter.String() 740 if !strings.Contains(actual, outputValue) { 741 t.Fatalf("Expected:\n%s\n\nTo include: %q", actual, outputValue) 742 } 743 } 744 745 const refreshVarFile = ` 746 foo = "bar" 747 ` 748 749 const testRefreshStr = ` 750 test_instance.foo: 751 ID = yes 752 ` 753 const testRefreshCwdStr = ` 754 test_instance.foo: 755 ID = yes 756 `