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