github.com/trawler/terraform@v0.10.8-0.20171106022149-4b1c7a1d9b48/command/init_test.go (about) 1 package command 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "os" 7 "path/filepath" 8 "reflect" 9 "runtime" 10 "sort" 11 "strings" 12 "testing" 13 14 "github.com/hashicorp/terraform/helper/copy" 15 "github.com/hashicorp/terraform/plugin/discovery" 16 "github.com/mitchellh/cli" 17 ) 18 19 func TestInit_empty(t *testing.T) { 20 // Create a temporary working directory that is empty 21 td := tempDir(t) 22 os.MkdirAll(td, 0755) 23 defer os.RemoveAll(td) 24 defer testChdir(t, td)() 25 26 ui := new(cli.MockUi) 27 c := &InitCommand{ 28 Meta: Meta{ 29 testingOverrides: metaOverridesForProvider(testProvider()), 30 Ui: ui, 31 }, 32 } 33 34 args := []string{} 35 if code := c.Run(args); code != 0 { 36 t.Fatalf("bad: \n%s", ui.ErrorWriter.String()) 37 } 38 } 39 40 func TestInit_multipleArgs(t *testing.T) { 41 ui := new(cli.MockUi) 42 c := &InitCommand{ 43 Meta: Meta{ 44 testingOverrides: metaOverridesForProvider(testProvider()), 45 Ui: ui, 46 }, 47 } 48 49 args := []string{ 50 "bad", 51 "bad", 52 } 53 if code := c.Run(args); code != 1 { 54 t.Fatalf("bad: \n%s", ui.OutputWriter.String()) 55 } 56 } 57 58 func TestInit_fromModule_explicitDest(t *testing.T) { 59 dir := tempDir(t) 60 61 ui := new(cli.MockUi) 62 c := &InitCommand{ 63 Meta: Meta{ 64 testingOverrides: metaOverridesForProvider(testProvider()), 65 Ui: ui, 66 }, 67 } 68 69 args := []string{ 70 "-from-module=" + testFixturePath("init"), 71 dir, 72 } 73 if code := c.Run(args); code != 0 { 74 t.Fatalf("bad: \n%s", ui.ErrorWriter.String()) 75 } 76 77 if _, err := os.Stat(filepath.Join(dir, "hello.tf")); err != nil { 78 t.Fatalf("err: %s", err) 79 } 80 } 81 82 func TestInit_fromModule_cwdDest(t *testing.T) { 83 // Create a temporary working directory that is empty 84 td := tempDir(t) 85 os.MkdirAll(td, os.ModePerm) 86 defer os.RemoveAll(td) 87 defer testChdir(t, td)() 88 89 ui := new(cli.MockUi) 90 c := &InitCommand{ 91 Meta: Meta{ 92 testingOverrides: metaOverridesForProvider(testProvider()), 93 Ui: ui, 94 }, 95 } 96 97 args := []string{ 98 "-from-module=" + testFixturePath("init"), 99 } 100 if code := c.Run(args); code != 0 { 101 t.Fatalf("bad: \n%s", ui.ErrorWriter.String()) 102 } 103 104 if _, err := os.Stat(filepath.Join(td, "hello.tf")); err != nil { 105 t.Fatalf("err: %s", err) 106 } 107 } 108 109 // https://github.com/hashicorp/terraform/issues/518 110 func TestInit_fromModule_dstInSrc(t *testing.T) { 111 dir := tempDir(t) 112 if err := os.MkdirAll(dir, 0755); err != nil { 113 t.Fatalf("err: %s", err) 114 } 115 116 // Change to the temporary directory 117 cwd, err := os.Getwd() 118 if err != nil { 119 t.Fatalf("err: %s", err) 120 } 121 if err := os.Chdir(dir); err != nil { 122 t.Fatalf("err: %s", err) 123 } 124 defer os.Chdir(cwd) 125 126 if _, err := os.Create("issue518.tf"); err != nil { 127 t.Fatalf("err: %s", err) 128 } 129 130 ui := new(cli.MockUi) 131 c := &InitCommand{ 132 Meta: Meta{ 133 testingOverrides: metaOverridesForProvider(testProvider()), 134 Ui: ui, 135 }, 136 } 137 138 args := []string{ 139 "-from-module=.", 140 "foo", 141 } 142 if code := c.Run(args); code != 0 { 143 t.Fatalf("bad: \n%s", ui.ErrorWriter.String()) 144 } 145 146 if _, err := os.Stat(filepath.Join(dir, "foo", "issue518.tf")); err != nil { 147 t.Fatalf("err: %s", err) 148 } 149 } 150 151 func TestInit_get(t *testing.T) { 152 // Create a temporary working directory that is empty 153 td := tempDir(t) 154 copy.CopyDir(testFixturePath("init-get"), td) 155 defer os.RemoveAll(td) 156 defer testChdir(t, td)() 157 158 ui := new(cli.MockUi) 159 c := &InitCommand{ 160 Meta: Meta{ 161 testingOverrides: metaOverridesForProvider(testProvider()), 162 Ui: ui, 163 }, 164 } 165 166 args := []string{} 167 if code := c.Run(args); code != 0 { 168 t.Fatalf("bad: \n%s", ui.ErrorWriter.String()) 169 } 170 171 // Check output 172 output := ui.OutputWriter.String() 173 if !strings.Contains(output, "Getting source") { 174 t.Fatalf("doesn't look like get: %s", output) 175 } 176 } 177 178 func TestInit_getUpgradeModules(t *testing.T) { 179 // Create a temporary working directory that is empty 180 td := tempDir(t) 181 os.MkdirAll(td, 0755) 182 // copy.CopyDir(testFixturePath("init-get"), td) 183 defer os.RemoveAll(td) 184 defer testChdir(t, td)() 185 186 ui := new(cli.MockUi) 187 c := &InitCommand{ 188 Meta: Meta{ 189 testingOverrides: metaOverridesForProvider(testProvider()), 190 Ui: ui, 191 }, 192 } 193 194 args := []string{ 195 "-get=true", 196 "-get-plugins=false", 197 "-upgrade", 198 testFixturePath("init-get"), 199 } 200 if code := c.Run(args); code != 0 { 201 t.Fatalf("command did not complete successfully:\n%s", ui.ErrorWriter.String()) 202 } 203 204 // Check output 205 output := ui.OutputWriter.String() 206 if !strings.Contains(output, "Updating source") { 207 t.Fatalf("doesn't look like get upgrade: %s", output) 208 } 209 } 210 211 func TestInit_backend(t *testing.T) { 212 // Create a temporary working directory that is empty 213 td := tempDir(t) 214 copy.CopyDir(testFixturePath("init-backend"), td) 215 defer os.RemoveAll(td) 216 defer testChdir(t, td)() 217 218 ui := new(cli.MockUi) 219 c := &InitCommand{ 220 Meta: Meta{ 221 testingOverrides: metaOverridesForProvider(testProvider()), 222 Ui: ui, 223 }, 224 } 225 226 args := []string{} 227 if code := c.Run(args); code != 0 { 228 t.Fatalf("bad: \n%s", ui.ErrorWriter.String()) 229 } 230 231 if _, err := os.Stat(filepath.Join(DefaultDataDir, DefaultStateFilename)); err != nil { 232 t.Fatalf("err: %s", err) 233 } 234 } 235 236 func TestInit_backendUnset(t *testing.T) { 237 // Create a temporary working directory that is empty 238 td := tempDir(t) 239 copy.CopyDir(testFixturePath("init-backend"), td) 240 defer os.RemoveAll(td) 241 defer testChdir(t, td)() 242 243 { 244 ui := new(cli.MockUi) 245 c := &InitCommand{ 246 Meta: Meta{ 247 testingOverrides: metaOverridesForProvider(testProvider()), 248 Ui: ui, 249 }, 250 } 251 252 // Init 253 args := []string{} 254 if code := c.Run(args); code != 0 { 255 t.Fatalf("bad: \n%s", ui.ErrorWriter.String()) 256 } 257 258 if _, err := os.Stat(filepath.Join(DefaultDataDir, DefaultStateFilename)); err != nil { 259 t.Fatalf("err: %s", err) 260 } 261 } 262 263 { 264 // Unset 265 if err := ioutil.WriteFile("main.tf", []byte(""), 0644); err != nil { 266 t.Fatalf("err: %s", err) 267 } 268 269 ui := new(cli.MockUi) 270 c := &InitCommand{ 271 Meta: Meta{ 272 testingOverrides: metaOverridesForProvider(testProvider()), 273 Ui: ui, 274 }, 275 } 276 277 args := []string{"-force-copy"} 278 if code := c.Run(args); code != 0 { 279 t.Fatalf("bad: \n%s", ui.ErrorWriter.String()) 280 } 281 282 s := testStateRead(t, filepath.Join( 283 DefaultDataDir, DefaultStateFilename)) 284 if !s.Backend.Empty() { 285 t.Fatal("should not have backend config") 286 } 287 } 288 } 289 290 func TestInit_backendConfigFile(t *testing.T) { 291 // Create a temporary working directory that is empty 292 td := tempDir(t) 293 copy.CopyDir(testFixturePath("init-backend-config-file"), td) 294 defer os.RemoveAll(td) 295 defer testChdir(t, td)() 296 297 ui := new(cli.MockUi) 298 c := &InitCommand{ 299 Meta: Meta{ 300 testingOverrides: metaOverridesForProvider(testProvider()), 301 Ui: ui, 302 }, 303 } 304 305 args := []string{"-backend-config", "input.config"} 306 if code := c.Run(args); code != 0 { 307 t.Fatalf("bad: \n%s", ui.ErrorWriter.String()) 308 } 309 310 // Read our saved backend config and verify we have our settings 311 state := testStateRead(t, filepath.Join(DefaultDataDir, DefaultStateFilename)) 312 if v := state.Backend.Config["path"]; v != "hello" { 313 t.Fatalf("bad: %#v", v) 314 } 315 } 316 317 func TestInit_backendConfigFileChange(t *testing.T) { 318 // Create a temporary working directory that is empty 319 td := tempDir(t) 320 copy.CopyDir(testFixturePath("init-backend-config-file-change"), td) 321 defer os.RemoveAll(td) 322 defer testChdir(t, td)() 323 324 // Ask input 325 defer testInputMap(t, map[string]string{ 326 "backend-migrate-to-new": "no", 327 })() 328 329 ui := new(cli.MockUi) 330 c := &InitCommand{ 331 Meta: Meta{ 332 testingOverrides: metaOverridesForProvider(testProvider()), 333 Ui: ui, 334 }, 335 } 336 337 args := []string{"-backend-config", "input.config"} 338 if code := c.Run(args); code != 0 { 339 t.Fatalf("bad: \n%s", ui.ErrorWriter.String()) 340 } 341 342 // Read our saved backend config and verify we have our settings 343 state := testStateRead(t, filepath.Join(DefaultDataDir, DefaultStateFilename)) 344 if v := state.Backend.Config["path"]; v != "hello" { 345 t.Fatalf("bad: %#v", v) 346 } 347 } 348 349 func TestInit_backendConfigKV(t *testing.T) { 350 // Create a temporary working directory that is empty 351 td := tempDir(t) 352 copy.CopyDir(testFixturePath("init-backend-config-kv"), td) 353 defer os.RemoveAll(td) 354 defer testChdir(t, td)() 355 356 ui := new(cli.MockUi) 357 c := &InitCommand{ 358 Meta: Meta{ 359 testingOverrides: metaOverridesForProvider(testProvider()), 360 Ui: ui, 361 }, 362 } 363 364 args := []string{"-backend-config", "path=hello"} 365 if code := c.Run(args); code != 0 { 366 t.Fatalf("bad: \n%s", ui.ErrorWriter.String()) 367 } 368 369 // Read our saved backend config and verify we have our settings 370 state := testStateRead(t, filepath.Join(DefaultDataDir, DefaultStateFilename)) 371 if v := state.Backend.Config["path"]; v != "hello" { 372 t.Fatalf("bad: %#v", v) 373 } 374 } 375 376 func TestInit_targetSubdir(t *testing.T) { 377 // Create a temporary working directory that is empty 378 td := tempDir(t) 379 os.MkdirAll(td, 0755) 380 defer os.RemoveAll(td) 381 defer testChdir(t, td)() 382 383 // copy the source into a subdir 384 copy.CopyDir(testFixturePath("init-backend"), filepath.Join(td, "source")) 385 386 ui := new(cli.MockUi) 387 c := &InitCommand{ 388 Meta: Meta{ 389 testingOverrides: metaOverridesForProvider(testProvider()), 390 Ui: ui, 391 }, 392 } 393 394 args := []string{ 395 "source", 396 } 397 if code := c.Run(args); code != 0 { 398 t.Fatalf("bad: \n%s", ui.ErrorWriter.String()) 399 } 400 401 if _, err := os.Stat(filepath.Join(td, DefaultDataDir, DefaultStateFilename)); err != nil { 402 t.Fatalf("err: %s", err) 403 } 404 405 // a data directory should not have been added to out working dir 406 if _, err := os.Stat(filepath.Join(td, "source", DefaultDataDir)); !os.IsNotExist(err) { 407 t.Fatalf("err: %s", err) 408 } 409 } 410 411 func TestInit_backendReinitWithExtra(t *testing.T) { 412 td := tempDir(t) 413 copy.CopyDir(testFixturePath("init-backend-empty"), td) 414 defer os.RemoveAll(td) 415 defer testChdir(t, td)() 416 417 m := testMetaBackend(t, nil) 418 opts := &BackendOpts{ 419 ConfigExtra: map[string]interface{}{"path": "hello"}, 420 Init: true, 421 } 422 423 b, err := m.backendConfig(opts) 424 if err != nil { 425 t.Fatal(err) 426 } 427 428 ui := new(cli.MockUi) 429 c := &InitCommand{ 430 Meta: Meta{ 431 testingOverrides: metaOverridesForProvider(testProvider()), 432 Ui: ui, 433 }, 434 } 435 436 args := []string{"-backend-config", "path=hello"} 437 if code := c.Run(args); code != 0 { 438 t.Fatalf("bad: \n%s", ui.ErrorWriter.String()) 439 } 440 441 // Read our saved backend config and verify we have our settings 442 state := testStateRead(t, filepath.Join(DefaultDataDir, DefaultStateFilename)) 443 if v := state.Backend.Config["path"]; v != "hello" { 444 t.Fatalf("bad: %#v", v) 445 } 446 447 if state.Backend.Hash != b.Hash { 448 t.Fatal("mismatched state and config backend hashes") 449 } 450 451 if state.Backend.Rehash() != b.Rehash() { 452 t.Fatal("mismatched state and config re-hashes") 453 } 454 455 // init again and make sure nothing changes 456 if code := c.Run(args); code != 0 { 457 t.Fatalf("bad: \n%s", ui.ErrorWriter.String()) 458 } 459 state = testStateRead(t, filepath.Join(DefaultDataDir, DefaultStateFilename)) 460 if v := state.Backend.Config["path"]; v != "hello" { 461 t.Fatalf("bad: %#v", v) 462 } 463 464 if state.Backend.Hash != b.Hash { 465 t.Fatal("mismatched state and config backend hashes") 466 } 467 } 468 469 // move option from config to -backend-config args 470 func TestInit_backendReinitConfigToExtra(t *testing.T) { 471 td := tempDir(t) 472 copy.CopyDir(testFixturePath("init-backend"), td) 473 defer os.RemoveAll(td) 474 defer testChdir(t, td)() 475 476 ui := new(cli.MockUi) 477 c := &InitCommand{ 478 Meta: Meta{ 479 testingOverrides: metaOverridesForProvider(testProvider()), 480 Ui: ui, 481 }, 482 } 483 484 if code := c.Run([]string{"-input=false"}); code != 0 { 485 t.Fatalf("bad: \n%s", ui.ErrorWriter.String()) 486 } 487 488 // Read our saved backend config and verify we have our settings 489 state := testStateRead(t, filepath.Join(DefaultDataDir, DefaultStateFilename)) 490 if v := state.Backend.Config["path"]; v != "foo" { 491 t.Fatalf("bad: %#v", v) 492 } 493 494 backendHash := state.Backend.Hash 495 496 // init again but remove the path option from the config 497 cfg := "terraform {\n backend \"local\" {}\n}\n" 498 if err := ioutil.WriteFile("main.tf", []byte(cfg), 0644); err != nil { 499 t.Fatal(err) 500 } 501 502 args := []string{"-input=false", "-backend-config=path=foo"} 503 if code := c.Run(args); code != 0 { 504 t.Fatalf("bad: \n%s", ui.ErrorWriter.String()) 505 } 506 state = testStateRead(t, filepath.Join(DefaultDataDir, DefaultStateFilename)) 507 508 if state.Backend.Hash == backendHash { 509 t.Fatal("state.Backend.Hash was not updated") 510 } 511 } 512 513 // make sure inputFalse stops execution on migrate 514 func TestInit_inputFalse(t *testing.T) { 515 td := tempDir(t) 516 copy.CopyDir(testFixturePath("init-backend"), td) 517 defer os.RemoveAll(td) 518 defer testChdir(t, td)() 519 520 ui := new(cli.MockUi) 521 c := &InitCommand{ 522 Meta: Meta{ 523 testingOverrides: metaOverridesForProvider(testProvider()), 524 Ui: ui, 525 }, 526 } 527 528 args := []string{"-input=false", "-backend-config=path=foo"} 529 if code := c.Run([]string{"-input=false"}); code != 0 { 530 t.Fatalf("bad: \n%s", ui.ErrorWriter) 531 } 532 533 args = []string{"-input=false", "-backend-config=path=bar"} 534 if code := c.Run(args); code == 0 { 535 t.Fatal("init should have failed", ui.OutputWriter) 536 } 537 } 538 539 func TestInit_getProvider(t *testing.T) { 540 // Create a temporary working directory that is empty 541 td := tempDir(t) 542 copy.CopyDir(testFixturePath("init-get-providers"), td) 543 defer os.RemoveAll(td) 544 defer testChdir(t, td)() 545 546 ui := new(cli.MockUi) 547 m := Meta{ 548 testingOverrides: metaOverridesForProvider(testProvider()), 549 Ui: ui, 550 } 551 552 installer := &mockProviderInstaller{ 553 Providers: map[string][]string{ 554 // looking for an exact version 555 "exact": []string{"1.2.3"}, 556 // config requires >= 2.3.3 557 "greater_than": []string{"2.3.4", "2.3.3", "2.3.0"}, 558 // config specifies 559 "between": []string{"3.4.5", "2.3.4", "1.2.3"}, 560 }, 561 562 Dir: m.pluginDir(), 563 } 564 565 c := &InitCommand{ 566 Meta: m, 567 providerInstaller: installer, 568 } 569 570 args := []string{ 571 "-backend=false", // should be possible to install plugins without backend init 572 } 573 if code := c.Run(args); code != 0 { 574 t.Fatalf("bad: \n%s", ui.ErrorWriter.String()) 575 } 576 577 if !installer.PurgeUnusedCalled { 578 t.Errorf("init didn't purge providers, but should have") 579 } 580 581 // check that we got the providers for our config 582 exactPath := filepath.Join(c.pluginDir(), installer.FileName("exact", "1.2.3")) 583 if _, err := os.Stat(exactPath); os.IsNotExist(err) { 584 t.Fatal("provider 'exact' not downloaded") 585 } 586 greaterThanPath := filepath.Join(c.pluginDir(), installer.FileName("greater_than", "2.3.4")) 587 if _, err := os.Stat(greaterThanPath); os.IsNotExist(err) { 588 t.Fatal("provider 'greater_than' not downloaded") 589 } 590 betweenPath := filepath.Join(c.pluginDir(), installer.FileName("between", "2.3.4")) 591 if _, err := os.Stat(betweenPath); os.IsNotExist(err) { 592 t.Fatal("provider 'between' not downloaded") 593 } 594 } 595 596 // make sure we can locate providers in various paths 597 func TestInit_findVendoredProviders(t *testing.T) { 598 // Create a temporary working directory that is empty 599 td := tempDir(t) 600 601 configDirName := "init-get-providers" 602 copy.CopyDir(testFixturePath(configDirName), filepath.Join(td, configDirName)) 603 defer os.RemoveAll(td) 604 defer testChdir(t, td)() 605 606 ui := new(cli.MockUi) 607 m := Meta{ 608 testingOverrides: metaOverridesForProvider(testProvider()), 609 Ui: ui, 610 } 611 612 c := &InitCommand{ 613 Meta: m, 614 providerInstaller: &mockProviderInstaller{}, 615 } 616 617 // make our plugin paths 618 if err := os.MkdirAll(c.pluginDir(), 0755); err != nil { 619 t.Fatal(err) 620 } 621 if err := os.MkdirAll(DefaultPluginVendorDir, 0755); err != nil { 622 t.Fatal(err) 623 } 624 625 // add some dummy providers 626 // the auto plugin directory 627 exactPath := filepath.Join(c.pluginDir(), "terraform-provider-exact_v1.2.3_x4") 628 if err := ioutil.WriteFile(exactPath, []byte("test bin"), 0755); err != nil { 629 t.Fatal(err) 630 } 631 // the vendor path 632 greaterThanPath := filepath.Join(DefaultPluginVendorDir, "terraform-provider-greater_than_v2.3.4_x4") 633 if err := ioutil.WriteFile(greaterThanPath, []byte("test bin"), 0755); err != nil { 634 t.Fatal(err) 635 } 636 // Check the current directory too 637 betweenPath := filepath.Join(".", "terraform-provider-between_v2.3.4_x4") 638 if err := ioutil.WriteFile(betweenPath, []byte("test bin"), 0755); err != nil { 639 t.Fatal(err) 640 } 641 642 args := []string{configDirName} 643 if code := c.Run(args); code != 0 { 644 t.Fatalf("bad: \n%s", ui.ErrorWriter.String()) 645 } 646 } 647 648 // make sure we can locate providers defined in the legacy rc file 649 func TestInit_rcProviders(t *testing.T) { 650 // Create a temporary working directory that is empty 651 td := tempDir(t) 652 653 configDirName := "init-legacy-rc" 654 copy.CopyDir(testFixturePath(configDirName), filepath.Join(td, configDirName)) 655 defer os.RemoveAll(td) 656 defer testChdir(t, td)() 657 658 pluginDir := filepath.Join(td, "custom") 659 pluginPath := filepath.Join(pluginDir, "terraform-provider-legacy") 660 661 ui := new(cli.MockUi) 662 m := Meta{ 663 Ui: ui, 664 PluginOverrides: &PluginOverrides{ 665 Providers: map[string]string{ 666 "legacy": pluginPath, 667 }, 668 }, 669 } 670 671 c := &InitCommand{ 672 Meta: m, 673 providerInstaller: &mockProviderInstaller{}, 674 } 675 676 // make our plugin paths 677 if err := os.MkdirAll(pluginDir, 0755); err != nil { 678 t.Fatal(err) 679 } 680 681 if err := ioutil.WriteFile(pluginPath, []byte("test bin"), 0755); err != nil { 682 t.Fatal(err) 683 } 684 685 args := []string{configDirName} 686 if code := c.Run(args); code != 0 { 687 t.Fatalf("bad: \n%s", ui.ErrorWriter.String()) 688 } 689 } 690 691 func TestInit_getUpgradePlugins(t *testing.T) { 692 // Create a temporary working directory that is empty 693 td := tempDir(t) 694 copy.CopyDir(testFixturePath("init-get-providers"), td) 695 defer os.RemoveAll(td) 696 defer testChdir(t, td)() 697 698 ui := new(cli.MockUi) 699 m := Meta{ 700 testingOverrides: metaOverridesForProvider(testProvider()), 701 Ui: ui, 702 } 703 704 installer := &mockProviderInstaller{ 705 Providers: map[string][]string{ 706 // looking for an exact version 707 "exact": []string{"1.2.3"}, 708 // config requires >= 2.3.3 709 "greater_than": []string{"2.3.4", "2.3.3", "2.3.0"}, 710 // config specifies 711 "between": []string{"3.4.5", "2.3.4", "1.2.3"}, 712 }, 713 714 Dir: m.pluginDir(), 715 } 716 717 err := os.MkdirAll(m.pluginDir(), os.ModePerm) 718 if err != nil { 719 t.Fatal(err) 720 } 721 exactUnwanted := filepath.Join(m.pluginDir(), installer.FileName("exact", "0.0.1")) 722 err = ioutil.WriteFile(exactUnwanted, []byte{}, os.ModePerm) 723 if err != nil { 724 t.Fatal(err) 725 } 726 greaterThanUnwanted := filepath.Join(m.pluginDir(), installer.FileName("greater_than", "2.3.3")) 727 err = ioutil.WriteFile(greaterThanUnwanted, []byte{}, os.ModePerm) 728 if err != nil { 729 t.Fatal(err) 730 } 731 betweenOverride := installer.FileName("between", "2.3.4") // intentionally directly in cwd, and should override auto-install 732 err = ioutil.WriteFile(betweenOverride, []byte{}, os.ModePerm) 733 if err != nil { 734 t.Fatal(err) 735 } 736 737 c := &InitCommand{ 738 Meta: m, 739 providerInstaller: installer, 740 } 741 742 args := []string{ 743 "-upgrade=true", 744 } 745 if code := c.Run(args); code != 0 { 746 t.Fatalf("command did not complete successfully:\n%s", ui.ErrorWriter.String()) 747 } 748 749 files, err := ioutil.ReadDir(m.pluginDir()) 750 if err != nil { 751 t.Fatal(err) 752 } 753 754 if !installer.PurgeUnusedCalled { 755 t.Errorf("init -upgrade didn't purge providers, but should have") 756 } 757 758 gotFilenames := make([]string, len(files)) 759 for i, info := range files { 760 gotFilenames[i] = info.Name() 761 } 762 sort.Strings(gotFilenames) 763 764 wantFilenames := []string{ 765 "lock.json", 766 767 // no "between" because the file in cwd overrides it 768 769 // The mock PurgeUnused doesn't actually purge anything, so the dir 770 // includes both our old and new versions. 771 "terraform-provider-exact_v0.0.1_x4", 772 "terraform-provider-exact_v1.2.3_x4", 773 "terraform-provider-greater_than_v2.3.3_x4", 774 "terraform-provider-greater_than_v2.3.4_x4", 775 } 776 777 if !reflect.DeepEqual(gotFilenames, wantFilenames) { 778 t.Errorf("wrong directory contents after upgrade\ngot: %#v\nwant: %#v", gotFilenames, wantFilenames) 779 } 780 781 } 782 783 func TestInit_getProviderMissing(t *testing.T) { 784 // Create a temporary working directory that is empty 785 td := tempDir(t) 786 copy.CopyDir(testFixturePath("init-get-providers"), td) 787 defer os.RemoveAll(td) 788 defer testChdir(t, td)() 789 790 ui := new(cli.MockUi) 791 m := Meta{ 792 testingOverrides: metaOverridesForProvider(testProvider()), 793 Ui: ui, 794 } 795 796 installer := &mockProviderInstaller{ 797 Providers: map[string][]string{ 798 // looking for exact version 1.2.3 799 "exact": []string{"1.2.4"}, 800 // config requires >= 2.3.3 801 "greater_than": []string{"2.3.4", "2.3.3", "2.3.0"}, 802 // config specifies 803 "between": []string{"3.4.5", "2.3.4", "1.2.3"}, 804 }, 805 806 Dir: m.pluginDir(), 807 } 808 809 c := &InitCommand{ 810 Meta: m, 811 providerInstaller: installer, 812 } 813 814 args := []string{} 815 if code := c.Run(args); code == 0 { 816 t.Fatalf("expceted error, got output: \n%s", ui.OutputWriter.String()) 817 } 818 819 if !strings.Contains(ui.ErrorWriter.String(), "no suitable version for provider") { 820 t.Fatalf("unexpected error output: %s", ui.ErrorWriter) 821 } 822 } 823 824 func TestInit_getProviderHaveLegacyVersion(t *testing.T) { 825 // Create a temporary working directory that is empty 826 td := tempDir(t) 827 copy.CopyDir(testFixturePath("init-providers-lock"), td) 828 defer os.RemoveAll(td) 829 defer testChdir(t, td)() 830 831 if err := ioutil.WriteFile("terraform-provider-test", []byte("provider bin"), 0755); err != nil { 832 t.Fatal(err) 833 } 834 835 // provider test has a version constraint in the config, which should 836 // trigger the getProvider error below. 837 ui := new(cli.MockUi) 838 c := &InitCommand{ 839 Meta: Meta{ 840 testingOverrides: metaOverridesForProvider(testProvider()), 841 Ui: ui, 842 }, 843 providerInstaller: callbackPluginInstaller(func(provider string, req discovery.Constraints) (discovery.PluginMeta, error) { 844 return discovery.PluginMeta{}, fmt.Errorf("EXPECTED PROVIDER ERROR %s", provider) 845 }), 846 } 847 848 args := []string{} 849 if code := c.Run(args); code == 0 { 850 t.Fatalf("expceted error, got output: \n%s", ui.OutputWriter.String()) 851 } 852 853 if !strings.Contains(ui.ErrorWriter.String(), "EXPECTED PROVIDER ERROR test") { 854 t.Fatalf("unexpected error output: %s", ui.ErrorWriter) 855 } 856 } 857 858 func TestInit_getProviderCheckRequiredVersion(t *testing.T) { 859 // Create a temporary working directory that is empty 860 td := tempDir(t) 861 copy.CopyDir(testFixturePath("init-check-required-version"), td) 862 defer os.RemoveAll(td) 863 defer testChdir(t, td)() 864 865 ui := new(cli.MockUi) 866 c := &InitCommand{ 867 Meta: Meta{ 868 testingOverrides: metaOverridesForProvider(testProvider()), 869 Ui: ui, 870 }, 871 } 872 873 args := []string{} 874 if code := c.Run(args); code != 1 { 875 t.Fatalf("bad: \n%s", ui.ErrorWriter.String()) 876 } 877 } 878 879 func TestInit_providerLockFile(t *testing.T) { 880 // Create a temporary working directory that is empty 881 td := tempDir(t) 882 copy.CopyDir(testFixturePath("init-provider-lock-file"), td) 883 defer os.RemoveAll(td) 884 defer testChdir(t, td)() 885 886 ui := new(cli.MockUi) 887 m := Meta{ 888 testingOverrides: metaOverridesForProvider(testProvider()), 889 Ui: ui, 890 } 891 892 installer := &mockProviderInstaller{ 893 Providers: map[string][]string{ 894 "test": []string{"1.2.3"}, 895 }, 896 897 Dir: m.pluginDir(), 898 } 899 900 c := &InitCommand{ 901 Meta: m, 902 providerInstaller: installer, 903 } 904 905 args := []string{} 906 if code := c.Run(args); code != 0 { 907 t.Fatalf("bad: \n%s", ui.ErrorWriter.String()) 908 } 909 910 providersLockFile := fmt.Sprintf( 911 ".terraform/plugins/%s_%s/lock.json", 912 runtime.GOOS, runtime.GOARCH, 913 ) 914 buf, err := ioutil.ReadFile(providersLockFile) 915 if err != nil { 916 t.Fatalf("failed to read providers lock file %s: %s", providersLockFile, err) 917 } 918 // The hash in here is for the empty files that mockGetProvider produces 919 wantLockFile := strings.TrimSpace(` 920 { 921 "test": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" 922 } 923 `) 924 if string(buf) != wantLockFile { 925 t.Errorf("wrong provider lock file contents\ngot: %s\nwant: %s", buf, wantLockFile) 926 } 927 } 928 929 // Test user-supplied -plugin-dir 930 func TestInit_pluginDirProviders(t *testing.T) { 931 td := tempDir(t) 932 copy.CopyDir(testFixturePath("init-get-providers"), td) 933 defer os.RemoveAll(td) 934 defer testChdir(t, td)() 935 936 ui := new(cli.MockUi) 937 m := Meta{ 938 testingOverrides: metaOverridesForProvider(testProvider()), 939 Ui: ui, 940 } 941 942 c := &InitCommand{ 943 Meta: m, 944 providerInstaller: &mockProviderInstaller{}, 945 } 946 947 // make our vendor paths 948 pluginPath := []string{"a", "b", "c"} 949 for _, p := range pluginPath { 950 if err := os.MkdirAll(p, 0755); err != nil { 951 t.Fatal(err) 952 } 953 } 954 955 // add some dummy providers in our plugin dirs 956 for i, name := range []string{ 957 "terraform-provider-exact_v1.2.3_x4", 958 "terraform-provider-greater_than_v2.3.4_x4", 959 "terraform-provider-between_v2.3.4_x4", 960 } { 961 962 if err := ioutil.WriteFile(filepath.Join(pluginPath[i], name), []byte("test bin"), 0755); err != nil { 963 t.Fatal(err) 964 } 965 } 966 967 args := []string{ 968 "-plugin-dir", "a", 969 "-plugin-dir", "b", 970 "-plugin-dir", "c", 971 } 972 if code := c.Run(args); code != 0 { 973 t.Fatalf("bad: \n%s", ui.ErrorWriter) 974 } 975 } 976 977 // Test user-supplied -plugin-dir doesn't allow auto-install 978 func TestInit_pluginDirProvidersDoesNotGet(t *testing.T) { 979 td := tempDir(t) 980 copy.CopyDir(testFixturePath("init-get-providers"), td) 981 defer os.RemoveAll(td) 982 defer testChdir(t, td)() 983 984 ui := new(cli.MockUi) 985 m := Meta{ 986 testingOverrides: metaOverridesForProvider(testProvider()), 987 Ui: ui, 988 } 989 990 c := &InitCommand{ 991 Meta: m, 992 providerInstaller: callbackPluginInstaller(func(provider string, req discovery.Constraints) (discovery.PluginMeta, error) { 993 t.Fatalf("plugin installer should not have been called for %q", provider) 994 return discovery.PluginMeta{}, nil 995 }), 996 } 997 998 // make our vendor paths 999 pluginPath := []string{"a", "b"} 1000 for _, p := range pluginPath { 1001 if err := os.MkdirAll(p, 0755); err != nil { 1002 t.Fatal(err) 1003 } 1004 } 1005 1006 // add some dummy providers in our plugin dirs 1007 for i, name := range []string{ 1008 "terraform-provider-exact_v1.2.3_x4", 1009 "terraform-provider-greater_than_v2.3.4_x4", 1010 } { 1011 1012 if err := ioutil.WriteFile(filepath.Join(pluginPath[i], name), []byte("test bin"), 0755); err != nil { 1013 t.Fatal(err) 1014 } 1015 } 1016 1017 args := []string{ 1018 "-plugin-dir", "a", 1019 "-plugin-dir", "b", 1020 } 1021 if code := c.Run(args); code == 0 { 1022 // should have been an error 1023 t.Fatalf("bad: \n%s", ui.OutputWriter) 1024 } 1025 }