github.com/articulate/terraform@v0.6.13-0.20160303003731-8d31c93862de/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_outPath(t *testing.T) { 225 state := testState() 226 statePath := testStateFile(t, state) 227 228 // Output path 229 outf, err := ioutil.TempFile("", "tf") 230 if err != nil { 231 t.Fatalf("err: %s", err) 232 } 233 outPath := outf.Name() 234 outf.Close() 235 os.Remove(outPath) 236 237 p := testProvider() 238 ui := new(cli.MockUi) 239 c := &RefreshCommand{ 240 Meta: Meta{ 241 ContextOpts: testCtxConfig(p), 242 Ui: ui, 243 }, 244 } 245 246 p.RefreshFn = nil 247 p.RefreshReturn = &terraform.InstanceState{ID: "yes"} 248 249 args := []string{ 250 "-state", statePath, 251 "-state-out", outPath, 252 testFixturePath("refresh"), 253 } 254 if code := c.Run(args); code != 0 { 255 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 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 if !reflect.DeepEqual(newState, state) { 270 t.Fatalf("bad: %#v", newState) 271 } 272 273 f, err = os.Open(outPath) 274 if err != nil { 275 t.Fatalf("err: %s", err) 276 } 277 278 newState, err = terraform.ReadState(f) 279 f.Close() 280 if err != nil { 281 t.Fatalf("err: %s", err) 282 } 283 284 actual := newState.RootModule().Resources["test_instance.foo"].Primary 285 expected := p.RefreshReturn 286 if !reflect.DeepEqual(actual, expected) { 287 t.Fatalf("bad: %#v", actual) 288 } 289 290 f, err = os.Open(outPath + DefaultBackupExtension) 291 if err != nil { 292 t.Fatalf("err: %s", err) 293 } 294 295 backupState, err := terraform.ReadState(f) 296 f.Close() 297 if err != nil { 298 t.Fatalf("err: %s", err) 299 } 300 301 actualStr := strings.TrimSpace(backupState.String()) 302 expectedStr := strings.TrimSpace(state.String()) 303 if actualStr != expectedStr { 304 t.Fatalf("bad:\n\n%s\n\n%s", actualStr, expectedStr) 305 } 306 } 307 308 func TestRefresh_var(t *testing.T) { 309 state := testState() 310 statePath := testStateFile(t, state) 311 312 p := testProvider() 313 ui := new(cli.MockUi) 314 c := &RefreshCommand{ 315 Meta: Meta{ 316 ContextOpts: testCtxConfig(p), 317 Ui: ui, 318 }, 319 } 320 321 args := []string{ 322 "-var", "foo=bar", 323 "-state", statePath, 324 testFixturePath("refresh-var"), 325 } 326 if code := c.Run(args); code != 0 { 327 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 328 } 329 330 if !p.ConfigureCalled { 331 t.Fatal("configure should be called") 332 } 333 if p.ConfigureConfig.Config["value"].(string) != "bar" { 334 t.Fatalf("bad: %#v", p.ConfigureConfig.Config) 335 } 336 } 337 338 func TestRefresh_varFile(t *testing.T) { 339 state := testState() 340 statePath := testStateFile(t, state) 341 342 p := testProvider() 343 ui := new(cli.MockUi) 344 c := &RefreshCommand{ 345 Meta: Meta{ 346 ContextOpts: testCtxConfig(p), 347 Ui: ui, 348 }, 349 } 350 351 varFilePath := testTempFile(t) 352 if err := ioutil.WriteFile(varFilePath, []byte(refreshVarFile), 0644); err != nil { 353 t.Fatalf("err: %s", err) 354 } 355 356 args := []string{ 357 "-var-file", varFilePath, 358 "-state", statePath, 359 testFixturePath("refresh-var"), 360 } 361 if code := c.Run(args); code != 0 { 362 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 363 } 364 365 if !p.ConfigureCalled { 366 t.Fatal("configure should be called") 367 } 368 if p.ConfigureConfig.Config["value"].(string) != "bar" { 369 t.Fatalf("bad: %#v", p.ConfigureConfig.Config) 370 } 371 } 372 373 func TestRefresh_varFileDefault(t *testing.T) { 374 state := testState() 375 statePath := testStateFile(t, state) 376 377 p := testProvider() 378 ui := new(cli.MockUi) 379 c := &RefreshCommand{ 380 Meta: Meta{ 381 ContextOpts: testCtxConfig(p), 382 Ui: ui, 383 }, 384 } 385 386 varFileDir := testTempDir(t) 387 varFilePath := filepath.Join(varFileDir, "terraform.tfvars") 388 if err := ioutil.WriteFile(varFilePath, []byte(refreshVarFile), 0644); err != nil { 389 t.Fatalf("err: %s", err) 390 } 391 392 cwd, err := os.Getwd() 393 if err != nil { 394 t.Fatalf("err: %s", err) 395 } 396 if err := os.Chdir(varFileDir); err != nil { 397 t.Fatalf("err: %s", err) 398 } 399 defer os.Chdir(cwd) 400 401 args := []string{ 402 "-state", statePath, 403 testFixturePath("refresh-var"), 404 } 405 if code := c.Run(args); code != 0 { 406 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 407 } 408 409 if !p.ConfigureCalled { 410 t.Fatal("configure should be called") 411 } 412 if p.ConfigureConfig.Config["value"].(string) != "bar" { 413 t.Fatalf("bad: %#v", p.ConfigureConfig.Config) 414 } 415 } 416 417 func TestRefresh_varsUnset(t *testing.T) { 418 // Disable test mode so input would be asked 419 test = false 420 defer func() { test = true }() 421 422 defaultInputReader = bytes.NewBufferString("bar\n") 423 424 state := testState() 425 statePath := testStateFile(t, state) 426 427 p := testProvider() 428 ui := new(cli.MockUi) 429 c := &RefreshCommand{ 430 Meta: Meta{ 431 ContextOpts: testCtxConfig(p), 432 Ui: ui, 433 }, 434 } 435 436 args := []string{ 437 "-state", statePath, 438 testFixturePath("refresh-unset-var"), 439 } 440 if code := c.Run(args); code != 0 { 441 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 442 } 443 } 444 445 func TestRefresh_backup(t *testing.T) { 446 state := testState() 447 statePath := testStateFile(t, state) 448 449 // Output path 450 outf, err := ioutil.TempFile("", "tf") 451 if err != nil { 452 t.Fatalf("err: %s", err) 453 } 454 outPath := outf.Name() 455 outf.Close() 456 os.Remove(outPath) 457 458 // Backup path 459 backupf, err := ioutil.TempFile("", "tf") 460 if err != nil { 461 t.Fatalf("err: %s", err) 462 } 463 backupPath := backupf.Name() 464 backupf.Close() 465 os.Remove(backupPath) 466 467 p := testProvider() 468 ui := new(cli.MockUi) 469 c := &RefreshCommand{ 470 Meta: Meta{ 471 ContextOpts: testCtxConfig(p), 472 Ui: ui, 473 }, 474 } 475 476 p.RefreshFn = nil 477 p.RefreshReturn = &terraform.InstanceState{ID: "yes"} 478 479 args := []string{ 480 "-state", statePath, 481 "-state-out", outPath, 482 "-backup", backupPath, 483 testFixturePath("refresh"), 484 } 485 if code := c.Run(args); code != 0 { 486 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 487 } 488 489 f, err := os.Open(statePath) 490 if err != nil { 491 t.Fatalf("err: %s", err) 492 } 493 494 newState, err := terraform.ReadState(f) 495 f.Close() 496 if err != nil { 497 t.Fatalf("err: %s", err) 498 } 499 500 if !reflect.DeepEqual(newState, state) { 501 t.Fatalf("bad: %#v", newState) 502 } 503 504 f, err = os.Open(outPath) 505 if err != nil { 506 t.Fatalf("err: %s", err) 507 } 508 509 newState, err = terraform.ReadState(f) 510 f.Close() 511 if err != nil { 512 t.Fatalf("err: %s", err) 513 } 514 515 actual := newState.RootModule().Resources["test_instance.foo"].Primary 516 expected := p.RefreshReturn 517 if !reflect.DeepEqual(actual, expected) { 518 t.Fatalf("bad: %#v", actual) 519 } 520 521 f, err = os.Open(backupPath) 522 if err != nil { 523 t.Fatalf("err: %s", err) 524 } 525 526 backupState, err := terraform.ReadState(f) 527 f.Close() 528 if err != nil { 529 t.Fatalf("err: %s", err) 530 } 531 532 actualStr := strings.TrimSpace(backupState.String()) 533 expectedStr := strings.TrimSpace(state.String()) 534 if actualStr != expectedStr { 535 t.Fatalf("bad:\n\n%s\n\n%s", actualStr, expectedStr) 536 } 537 } 538 539 func TestRefresh_disableBackup(t *testing.T) { 540 state := testState() 541 statePath := testStateFile(t, state) 542 543 // Output path 544 outf, err := ioutil.TempFile("", "tf") 545 if err != nil { 546 t.Fatalf("err: %s", err) 547 } 548 outPath := outf.Name() 549 outf.Close() 550 os.Remove(outPath) 551 552 p := testProvider() 553 ui := new(cli.MockUi) 554 c := &RefreshCommand{ 555 Meta: Meta{ 556 ContextOpts: testCtxConfig(p), 557 Ui: ui, 558 }, 559 } 560 561 p.RefreshFn = nil 562 p.RefreshReturn = &terraform.InstanceState{ID: "yes"} 563 564 args := []string{ 565 "-state", statePath, 566 "-state-out", outPath, 567 "-backup", "-", 568 testFixturePath("refresh"), 569 } 570 if code := c.Run(args); code != 0 { 571 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 572 } 573 574 f, err := os.Open(statePath) 575 if err != nil { 576 t.Fatalf("err: %s", err) 577 } 578 579 newState, err := terraform.ReadState(f) 580 f.Close() 581 if err != nil { 582 t.Fatalf("err: %s", err) 583 } 584 585 if !reflect.DeepEqual(newState, state) { 586 t.Fatalf("bad: %#v", newState) 587 } 588 589 f, err = os.Open(outPath) 590 if err != nil { 591 t.Fatalf("err: %s", err) 592 } 593 594 newState, err = terraform.ReadState(f) 595 f.Close() 596 if err != nil { 597 t.Fatalf("err: %s", err) 598 } 599 600 actual := newState.RootModule().Resources["test_instance.foo"].Primary 601 expected := p.RefreshReturn 602 if !reflect.DeepEqual(actual, expected) { 603 t.Fatalf("bad: %#v", actual) 604 } 605 606 // Ensure there is no backup 607 _, err = os.Stat(outPath + DefaultBackupExtension) 608 if err == nil || !os.IsNotExist(err) { 609 t.Fatalf("backup should not exist") 610 } 611 } 612 613 func TestRefresh_displaysOutputs(t *testing.T) { 614 state := testState() 615 statePath := testStateFile(t, state) 616 617 p := testProvider() 618 ui := new(cli.MockUi) 619 c := &RefreshCommand{ 620 Meta: Meta{ 621 ContextOpts: testCtxConfig(p), 622 Ui: ui, 623 }, 624 } 625 626 args := []string{ 627 "-state", statePath, 628 testFixturePath("refresh-output"), 629 } 630 if code := c.Run(args); code != 0 { 631 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 632 } 633 634 // Test that outputs were displayed 635 outputValue := "foo.example.com" 636 actual := ui.OutputWriter.String() 637 if !strings.Contains(actual, outputValue) { 638 t.Fatalf("Expected:\n%s\n\nTo include: %q", actual, outputValue) 639 } 640 } 641 642 const refreshVarFile = ` 643 foo = "bar" 644 ` 645 646 const testRefreshStr = ` 647 test_instance.foo: 648 ID = yes 649 ` 650 const testRefreshCwdStr = ` 651 test_instance.foo: 652 ID = yes 653 `