github.com/hooklift/terraform@v0.11.0-beta1.0.20171117000744-6786c1361ffe/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  }