github.com/kevholditch/terraform@v0.9.7-0.20170613192930-9706042ddd51/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, "source", 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, 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  	if code := c.Run(args); code != 0 {
   479  		t.Fatalf("bad: \n%s", ui.ErrorWriter.String())
   480  	}
   481  
   482  	// check that we got the providers for our config
   483  	exactPath := filepath.Join(c.pluginDir(), installer.FileName("exact", "1.2.3"))
   484  	if _, err := os.Stat(exactPath); os.IsNotExist(err) {
   485  		t.Fatal("provider 'exact' not downloaded")
   486  	}
   487  	greaterThanPath := filepath.Join(c.pluginDir(), installer.FileName("greater_than", "2.3.4"))
   488  	if _, err := os.Stat(greaterThanPath); os.IsNotExist(err) {
   489  		t.Fatal("provider 'greater_than' not downloaded")
   490  	}
   491  	betweenPath := filepath.Join(c.pluginDir(), installer.FileName("between", "2.3.4"))
   492  	if _, err := os.Stat(betweenPath); os.IsNotExist(err) {
   493  		t.Fatal("provider 'between' not downloaded")
   494  	}
   495  }
   496  
   497  func TestInit_getUpgradePlugins(t *testing.T) {
   498  	// Create a temporary working directory that is empty
   499  	td := tempDir(t)
   500  	copy.CopyDir(testFixturePath("init-get-providers"), td)
   501  	defer os.RemoveAll(td)
   502  	defer testChdir(t, td)()
   503  
   504  	ui := new(cli.MockUi)
   505  	m := Meta{
   506  		testingOverrides: metaOverridesForProvider(testProvider()),
   507  		Ui:               ui,
   508  	}
   509  
   510  	installer := &mockProviderInstaller{
   511  		Providers: map[string][]string{
   512  			// looking for an exact version
   513  			"exact": []string{"1.2.3"},
   514  			// config requires >= 2.3.3
   515  			"greater_than": []string{"2.3.4", "2.3.3", "2.3.0"},
   516  			// config specifies
   517  			"between": []string{"3.4.5", "2.3.4", "1.2.3"},
   518  		},
   519  
   520  		Dir: m.pluginDir(),
   521  	}
   522  
   523  	err := os.MkdirAll(m.pluginDir(), os.ModePerm)
   524  	if err != nil {
   525  		t.Fatal(err)
   526  	}
   527  	exactUnwanted := filepath.Join(m.pluginDir(), installer.FileName("exact", "0.0.1"))
   528  	err = ioutil.WriteFile(exactUnwanted, []byte{}, os.ModePerm)
   529  	if err != nil {
   530  		t.Fatal(err)
   531  	}
   532  	greaterThanUnwanted := filepath.Join(m.pluginDir(), installer.FileName("greater_than", "2.3.3"))
   533  	err = ioutil.WriteFile(greaterThanUnwanted, []byte{}, os.ModePerm)
   534  	if err != nil {
   535  		t.Fatal(err)
   536  	}
   537  	betweenOverride := installer.FileName("between", "2.3.4") // intentionally directly in cwd, and should override auto-install
   538  	err = ioutil.WriteFile(betweenOverride, []byte{}, os.ModePerm)
   539  	if err != nil {
   540  		t.Fatal(err)
   541  	}
   542  
   543  	c := &InitCommand{
   544  		Meta:              m,
   545  		providerInstaller: installer,
   546  	}
   547  
   548  	args := []string{
   549  		"-upgrade=true",
   550  	}
   551  	if code := c.Run(args); code != 0 {
   552  		t.Fatalf("command did not complete successfully:\n%s", ui.ErrorWriter.String())
   553  	}
   554  
   555  	files, err := ioutil.ReadDir(m.pluginDir())
   556  	if err != nil {
   557  		t.Fatal(err)
   558  	}
   559  
   560  	if !installer.PurgeUnusedCalled {
   561  		t.Errorf("init -upgrade didn't purge providers, but should have")
   562  	}
   563  
   564  	gotFilenames := make([]string, len(files))
   565  	for i, info := range files {
   566  		gotFilenames[i] = info.Name()
   567  	}
   568  	sort.Strings(gotFilenames)
   569  
   570  	wantFilenames := []string{
   571  		"lock.json",
   572  
   573  		// no "between" because the file in cwd overrides it
   574  
   575  		// The mock PurgeUnused doesn't actually purge anything, so the dir
   576  		// includes both our old and new versions.
   577  		"terraform-provider-exact_v0.0.1_x4",
   578  		"terraform-provider-exact_v1.2.3_x4",
   579  		"terraform-provider-greater_than_v2.3.3_x4",
   580  		"terraform-provider-greater_than_v2.3.4_x4",
   581  	}
   582  
   583  	if !reflect.DeepEqual(gotFilenames, wantFilenames) {
   584  		t.Errorf("wrong directory contents after upgrade\ngot:  %#v\nwant: %#v", gotFilenames, wantFilenames)
   585  	}
   586  
   587  }
   588  
   589  func TestInit_getProviderMissing(t *testing.T) {
   590  	// Create a temporary working directory that is empty
   591  	td := tempDir(t)
   592  	copy.CopyDir(testFixturePath("init-get-providers"), td)
   593  	defer os.RemoveAll(td)
   594  	defer testChdir(t, td)()
   595  
   596  	ui := new(cli.MockUi)
   597  	m := Meta{
   598  		testingOverrides: metaOverridesForProvider(testProvider()),
   599  		Ui:               ui,
   600  	}
   601  
   602  	installer := &mockProviderInstaller{
   603  		Providers: map[string][]string{
   604  			// looking for exact version 1.2.3
   605  			"exact": []string{"1.2.4"},
   606  			// config requires >= 2.3.3
   607  			"greater_than": []string{"2.3.4", "2.3.3", "2.3.0"},
   608  			// config specifies
   609  			"between": []string{"3.4.5", "2.3.4", "1.2.3"},
   610  		},
   611  
   612  		Dir: m.pluginDir(),
   613  	}
   614  
   615  	c := &InitCommand{
   616  		Meta:              m,
   617  		providerInstaller: installer,
   618  	}
   619  
   620  	args := []string{}
   621  	if code := c.Run(args); code == 0 {
   622  		t.Fatalf("expceted error, got output: \n%s", ui.OutputWriter.String())
   623  	}
   624  
   625  	if !strings.Contains(ui.ErrorWriter.String(), "no suitable version for provider") {
   626  		t.Fatalf("unexpected error output: %s", ui.ErrorWriter)
   627  	}
   628  }
   629  
   630  func TestInit_getProviderHaveLegacyVersion(t *testing.T) {
   631  	// Create a temporary working directory that is empty
   632  	td := tempDir(t)
   633  	copy.CopyDir(testFixturePath("init-providers-lock"), td)
   634  	defer os.RemoveAll(td)
   635  	defer testChdir(t, td)()
   636  
   637  	if err := ioutil.WriteFile("terraform-provider-test", []byte("provider bin"), 0755); err != nil {
   638  		t.Fatal(err)
   639  	}
   640  
   641  	// provider test has a version constraint in the config, which should
   642  	// trigger the getProvider error below.
   643  	ui := new(cli.MockUi)
   644  	c := &InitCommand{
   645  		Meta: Meta{
   646  			testingOverrides: metaOverridesForProvider(testProvider()),
   647  			Ui:               ui,
   648  		},
   649  		providerInstaller: callbackPluginInstaller(func(provider string, req discovery.Constraints) (discovery.PluginMeta, error) {
   650  			return discovery.PluginMeta{}, fmt.Errorf("EXPECTED PROVIDER ERROR %s", provider)
   651  		}),
   652  	}
   653  
   654  	args := []string{}
   655  	if code := c.Run(args); code == 0 {
   656  		t.Fatalf("expceted error, got output: \n%s", ui.OutputWriter.String())
   657  	}
   658  
   659  	if !strings.Contains(ui.ErrorWriter.String(), "EXPECTED PROVIDER ERROR test") {
   660  		t.Fatalf("unexpected error output: %s", ui.ErrorWriter)
   661  	}
   662  }
   663  
   664  func TestInit_providerLockFile(t *testing.T) {
   665  	// Create a temporary working directory that is empty
   666  	td := tempDir(t)
   667  	copy.CopyDir(testFixturePath("init-provider-lock-file"), td)
   668  	defer os.RemoveAll(td)
   669  	defer testChdir(t, td)()
   670  
   671  	ui := new(cli.MockUi)
   672  	m := Meta{
   673  		testingOverrides: metaOverridesForProvider(testProvider()),
   674  		Ui:               ui,
   675  	}
   676  
   677  	installer := &mockProviderInstaller{
   678  		Providers: map[string][]string{
   679  			"test": []string{"1.2.3"},
   680  		},
   681  
   682  		Dir: m.pluginDir(),
   683  	}
   684  
   685  	c := &InitCommand{
   686  		Meta:              m,
   687  		providerInstaller: installer,
   688  	}
   689  
   690  	args := []string{}
   691  	if code := c.Run(args); code != 0 {
   692  		t.Fatalf("bad: \n%s", ui.ErrorWriter.String())
   693  	}
   694  
   695  	providersLockFile := fmt.Sprintf(
   696  		".terraform/plugins/%s_%s/lock.json",
   697  		runtime.GOOS, runtime.GOARCH,
   698  	)
   699  	buf, err := ioutil.ReadFile(providersLockFile)
   700  	if err != nil {
   701  		t.Fatalf("failed to read providers lock file %s: %s", providersLockFile, err)
   702  	}
   703  	// The hash in here is for the empty files that mockGetProvider produces
   704  	wantLockFile := strings.TrimSpace(`
   705  {
   706    "test": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
   707  }
   708  `)
   709  	if string(buf) != wantLockFile {
   710  		t.Errorf("wrong provider lock file contents\ngot:  %s\nwant: %s", buf, wantLockFile)
   711  	}
   712  }