github.com/lymingtonprecision/terraform@v0.9.9-0.20170613092852-62acef9611a9/command/init_test.go (about)

     1  package command
     2  
     3  import (
     4  	"fmt"
     5  	"io/ioutil"
     6  	"os"
     7  	"path/filepath"
     8  	"runtime"
     9  	"strings"
    10  	"testing"
    11  
    12  	"github.com/hashicorp/terraform/helper/copy"
    13  	"github.com/hashicorp/terraform/plugin/discovery"
    14  	"github.com/mitchellh/cli"
    15  )
    16  
    17  func TestInit_empty(t *testing.T) {
    18  	// Create a temporary working directory that is empty
    19  	td := tempDir(t)
    20  	os.MkdirAll(td, 0755)
    21  	defer os.RemoveAll(td)
    22  	defer testChdir(t, td)()
    23  
    24  	ui := new(cli.MockUi)
    25  	c := &InitCommand{
    26  		Meta: Meta{
    27  			testingOverrides: metaOverridesForProvider(testProvider()),
    28  			Ui:               ui,
    29  		},
    30  	}
    31  
    32  	args := []string{}
    33  	if code := c.Run(args); code != 0 {
    34  		t.Fatalf("bad: \n%s", ui.ErrorWriter.String())
    35  	}
    36  }
    37  
    38  func TestInit_multipleArgs(t *testing.T) {
    39  	ui := new(cli.MockUi)
    40  	c := &InitCommand{
    41  		Meta: Meta{
    42  			testingOverrides: metaOverridesForProvider(testProvider()),
    43  			Ui:               ui,
    44  		},
    45  	}
    46  
    47  	args := []string{
    48  		"bad",
    49  		"bad",
    50  	}
    51  	if code := c.Run(args); code != 1 {
    52  		t.Fatalf("bad: \n%s", ui.OutputWriter.String())
    53  	}
    54  }
    55  
    56  func TestInit_get(t *testing.T) {
    57  	// Create a temporary working directory that is empty
    58  	td := tempDir(t)
    59  	copy.CopyDir(testFixturePath("init-get"), td)
    60  	defer os.RemoveAll(td)
    61  	defer testChdir(t, td)()
    62  
    63  	ui := new(cli.MockUi)
    64  	c := &InitCommand{
    65  		Meta: Meta{
    66  			testingOverrides: metaOverridesForProvider(testProvider()),
    67  			Ui:               ui,
    68  		},
    69  	}
    70  
    71  	args := []string{}
    72  	if code := c.Run(args); code != 0 {
    73  		t.Fatalf("bad: \n%s", ui.ErrorWriter.String())
    74  	}
    75  
    76  	// Check output
    77  	output := ui.OutputWriter.String()
    78  	if !strings.Contains(output, "Get: file://") {
    79  		t.Fatalf("doesn't look like get: %s", output)
    80  	}
    81  }
    82  
    83  func TestInit_backend(t *testing.T) {
    84  	// Create a temporary working directory that is empty
    85  	td := tempDir(t)
    86  	copy.CopyDir(testFixturePath("init-backend"), td)
    87  	defer os.RemoveAll(td)
    88  	defer testChdir(t, td)()
    89  
    90  	ui := new(cli.MockUi)
    91  	c := &InitCommand{
    92  		Meta: Meta{
    93  			testingOverrides: metaOverridesForProvider(testProvider()),
    94  			Ui:               ui,
    95  		},
    96  	}
    97  
    98  	args := []string{}
    99  	if code := c.Run(args); code != 0 {
   100  		t.Fatalf("bad: \n%s", ui.ErrorWriter.String())
   101  	}
   102  
   103  	if _, err := os.Stat(filepath.Join(DefaultDataDir, DefaultStateFilename)); err != nil {
   104  		t.Fatalf("err: %s", err)
   105  	}
   106  }
   107  
   108  func TestInit_backendUnset(t *testing.T) {
   109  	// Create a temporary working directory that is empty
   110  	td := tempDir(t)
   111  	copy.CopyDir(testFixturePath("init-backend"), td)
   112  	defer os.RemoveAll(td)
   113  	defer testChdir(t, td)()
   114  
   115  	{
   116  		ui := new(cli.MockUi)
   117  		c := &InitCommand{
   118  			Meta: Meta{
   119  				testingOverrides: metaOverridesForProvider(testProvider()),
   120  				Ui:               ui,
   121  			},
   122  		}
   123  
   124  		// Init
   125  		args := []string{}
   126  		if code := c.Run(args); code != 0 {
   127  			t.Fatalf("bad: \n%s", ui.ErrorWriter.String())
   128  		}
   129  
   130  		if _, err := os.Stat(filepath.Join(DefaultDataDir, DefaultStateFilename)); err != nil {
   131  			t.Fatalf("err: %s", err)
   132  		}
   133  	}
   134  
   135  	{
   136  		// Unset
   137  		if err := ioutil.WriteFile("main.tf", []byte(""), 0644); err != nil {
   138  			t.Fatalf("err: %s", err)
   139  		}
   140  
   141  		ui := new(cli.MockUi)
   142  		c := &InitCommand{
   143  			Meta: Meta{
   144  				testingOverrides: metaOverridesForProvider(testProvider()),
   145  				Ui:               ui,
   146  			},
   147  		}
   148  
   149  		args := []string{"-force-copy"}
   150  		if code := c.Run(args); code != 0 {
   151  			t.Fatalf("bad: \n%s", ui.ErrorWriter.String())
   152  		}
   153  
   154  		s := testStateRead(t, filepath.Join(
   155  			DefaultDataDir, DefaultStateFilename))
   156  		if !s.Backend.Empty() {
   157  			t.Fatal("should not have backend config")
   158  		}
   159  	}
   160  }
   161  
   162  func TestInit_backendConfigFile(t *testing.T) {
   163  	// Create a temporary working directory that is empty
   164  	td := tempDir(t)
   165  	copy.CopyDir(testFixturePath("init-backend-config-file"), td)
   166  	defer os.RemoveAll(td)
   167  	defer testChdir(t, td)()
   168  
   169  	ui := new(cli.MockUi)
   170  	c := &InitCommand{
   171  		Meta: Meta{
   172  			testingOverrides: metaOverridesForProvider(testProvider()),
   173  			Ui:               ui,
   174  		},
   175  	}
   176  
   177  	args := []string{"-backend-config", "input.config"}
   178  	if code := c.Run(args); code != 0 {
   179  		t.Fatalf("bad: \n%s", ui.ErrorWriter.String())
   180  	}
   181  
   182  	// Read our saved backend config and verify we have our settings
   183  	state := testStateRead(t, filepath.Join(DefaultDataDir, DefaultStateFilename))
   184  	if v := state.Backend.Config["path"]; v != "hello" {
   185  		t.Fatalf("bad: %#v", v)
   186  	}
   187  }
   188  
   189  func TestInit_backendConfigFileChange(t *testing.T) {
   190  	// Create a temporary working directory that is empty
   191  	td := tempDir(t)
   192  	copy.CopyDir(testFixturePath("init-backend-config-file-change"), td)
   193  	defer os.RemoveAll(td)
   194  	defer testChdir(t, td)()
   195  
   196  	// Ask input
   197  	defer testInputMap(t, map[string]string{
   198  		"backend-migrate-to-new": "no",
   199  	})()
   200  
   201  	ui := new(cli.MockUi)
   202  	c := &InitCommand{
   203  		Meta: Meta{
   204  			testingOverrides: metaOverridesForProvider(testProvider()),
   205  			Ui:               ui,
   206  		},
   207  	}
   208  
   209  	args := []string{"-backend-config", "input.config"}
   210  	if code := c.Run(args); code != 0 {
   211  		t.Fatalf("bad: \n%s", ui.ErrorWriter.String())
   212  	}
   213  
   214  	// Read our saved backend config and verify we have our settings
   215  	state := testStateRead(t, filepath.Join(DefaultDataDir, DefaultStateFilename))
   216  	if v := state.Backend.Config["path"]; v != "hello" {
   217  		t.Fatalf("bad: %#v", v)
   218  	}
   219  }
   220  
   221  func TestInit_backendConfigKV(t *testing.T) {
   222  	// Create a temporary working directory that is empty
   223  	td := tempDir(t)
   224  	copy.CopyDir(testFixturePath("init-backend-config-kv"), td)
   225  	defer os.RemoveAll(td)
   226  	defer testChdir(t, td)()
   227  
   228  	ui := new(cli.MockUi)
   229  	c := &InitCommand{
   230  		Meta: Meta{
   231  			testingOverrides: metaOverridesForProvider(testProvider()),
   232  			Ui:               ui,
   233  		},
   234  	}
   235  
   236  	args := []string{"-backend-config", "path=hello"}
   237  	if code := c.Run(args); code != 0 {
   238  		t.Fatalf("bad: \n%s", ui.ErrorWriter.String())
   239  	}
   240  
   241  	// Read our saved backend config and verify we have our settings
   242  	state := testStateRead(t, filepath.Join(DefaultDataDir, DefaultStateFilename))
   243  	if v := state.Backend.Config["path"]; v != "hello" {
   244  		t.Fatalf("bad: %#v", v)
   245  	}
   246  }
   247  
   248  func TestInit_targetSubdir(t *testing.T) {
   249  	// Create a temporary working directory that is empty
   250  	td := tempDir(t)
   251  	os.MkdirAll(td, 0755)
   252  	defer os.RemoveAll(td)
   253  	defer testChdir(t, td)()
   254  
   255  	// copy the source into a subdir
   256  	copy.CopyDir(testFixturePath("init-backend"), filepath.Join(td, "source"))
   257  
   258  	ui := new(cli.MockUi)
   259  	c := &InitCommand{
   260  		Meta: Meta{
   261  			testingOverrides: metaOverridesForProvider(testProvider()),
   262  			Ui:               ui,
   263  		},
   264  	}
   265  
   266  	args := []string{
   267  		"source",
   268  	}
   269  	if code := c.Run(args); code != 0 {
   270  		t.Fatalf("bad: \n%s", ui.ErrorWriter.String())
   271  	}
   272  
   273  	if _, err := os.Stat(filepath.Join(td, "source", DefaultDataDir, DefaultStateFilename)); err != nil {
   274  		t.Fatalf("err: %s", err)
   275  	}
   276  
   277  	// a data directory should not have been added to out working dir
   278  	if _, err := os.Stat(filepath.Join(td, DefaultDataDir)); !os.IsNotExist(err) {
   279  		t.Fatalf("err: %s", err)
   280  	}
   281  }
   282  
   283  func TestInit_backendReinitWithExtra(t *testing.T) {
   284  	td := tempDir(t)
   285  	copy.CopyDir(testFixturePath("init-backend-empty"), td)
   286  	defer os.RemoveAll(td)
   287  	defer testChdir(t, td)()
   288  
   289  	m := testMetaBackend(t, nil)
   290  	opts := &BackendOpts{
   291  		ConfigExtra: map[string]interface{}{"path": "hello"},
   292  		Init:        true,
   293  	}
   294  
   295  	b, err := m.backendConfig(opts)
   296  	if err != nil {
   297  		t.Fatal(err)
   298  	}
   299  
   300  	ui := new(cli.MockUi)
   301  	c := &InitCommand{
   302  		Meta: Meta{
   303  			testingOverrides: metaOverridesForProvider(testProvider()),
   304  			Ui:               ui,
   305  		},
   306  	}
   307  
   308  	args := []string{"-backend-config", "path=hello"}
   309  	if code := c.Run(args); code != 0 {
   310  		t.Fatalf("bad: \n%s", ui.ErrorWriter.String())
   311  	}
   312  
   313  	// Read our saved backend config and verify we have our settings
   314  	state := testStateRead(t, filepath.Join(DefaultDataDir, DefaultStateFilename))
   315  	if v := state.Backend.Config["path"]; v != "hello" {
   316  		t.Fatalf("bad: %#v", v)
   317  	}
   318  
   319  	if state.Backend.Hash != b.Hash {
   320  		t.Fatal("mismatched state and config backend hashes")
   321  	}
   322  
   323  	if state.Backend.Rehash() != b.Rehash() {
   324  		t.Fatal("mismatched state and config re-hashes")
   325  	}
   326  
   327  	// init again and make sure nothing changes
   328  	if code := c.Run(args); code != 0 {
   329  		t.Fatalf("bad: \n%s", ui.ErrorWriter.String())
   330  	}
   331  	state = testStateRead(t, filepath.Join(DefaultDataDir, DefaultStateFilename))
   332  	if v := state.Backend.Config["path"]; v != "hello" {
   333  		t.Fatalf("bad: %#v", v)
   334  	}
   335  
   336  	if state.Backend.Hash != b.Hash {
   337  		t.Fatal("mismatched state and config backend hashes")
   338  	}
   339  }
   340  
   341  // move option from config to -backend-config args
   342  func TestInit_backendReinitConfigToExtra(t *testing.T) {
   343  	td := tempDir(t)
   344  	copy.CopyDir(testFixturePath("init-backend"), td)
   345  	defer os.RemoveAll(td)
   346  	defer testChdir(t, td)()
   347  
   348  	ui := new(cli.MockUi)
   349  	c := &InitCommand{
   350  		Meta: Meta{
   351  			testingOverrides: metaOverridesForProvider(testProvider()),
   352  			Ui:               ui,
   353  		},
   354  	}
   355  
   356  	if code := c.Run([]string{"-input=false"}); code != 0 {
   357  		t.Fatalf("bad: \n%s", ui.ErrorWriter.String())
   358  	}
   359  
   360  	// Read our saved backend config and verify we have our settings
   361  	state := testStateRead(t, filepath.Join(DefaultDataDir, DefaultStateFilename))
   362  	if v := state.Backend.Config["path"]; v != "foo" {
   363  		t.Fatalf("bad: %#v", v)
   364  	}
   365  
   366  	backendHash := state.Backend.Hash
   367  
   368  	// init again but remove the path option from the config
   369  	cfg := "terraform {\n  backend \"local\" {}\n}\n"
   370  	if err := ioutil.WriteFile("main.tf", []byte(cfg), 0644); err != nil {
   371  		t.Fatal(err)
   372  	}
   373  
   374  	args := []string{"-input=false", "-backend-config=path=foo"}
   375  	if code := c.Run(args); code != 0 {
   376  		t.Fatalf("bad: \n%s", ui.ErrorWriter.String())
   377  	}
   378  	state = testStateRead(t, filepath.Join(DefaultDataDir, DefaultStateFilename))
   379  
   380  	if state.Backend.Hash == backendHash {
   381  		t.Fatal("state.Backend.Hash was not updated")
   382  	}
   383  }
   384  
   385  // make sure inputFalse stops execution on migrate
   386  func TestInit_inputFalse(t *testing.T) {
   387  	td := tempDir(t)
   388  	copy.CopyDir(testFixturePath("init-backend"), td)
   389  	defer os.RemoveAll(td)
   390  	defer testChdir(t, td)()
   391  
   392  	ui := new(cli.MockUi)
   393  	c := &InitCommand{
   394  		Meta: Meta{
   395  			testingOverrides: metaOverridesForProvider(testProvider()),
   396  			Ui:               ui,
   397  		},
   398  	}
   399  
   400  	args := []string{"-input=false", "-backend-config=path=foo"}
   401  	if code := c.Run([]string{"-input=false"}); code != 0 {
   402  		t.Fatalf("bad: \n%s", ui.ErrorWriter)
   403  	}
   404  
   405  	args = []string{"-input=false", "-backend-config=path=bar"}
   406  	if code := c.Run(args); code == 0 {
   407  		t.Fatal("init should have failed", ui.OutputWriter)
   408  	}
   409  }
   410  
   411  func TestInit_getProvider(t *testing.T) {
   412  	// Create a temporary working directory that is empty
   413  	td := tempDir(t)
   414  	copy.CopyDir(testFixturePath("init-get-providers"), td)
   415  	defer os.RemoveAll(td)
   416  	defer testChdir(t, td)()
   417  
   418  	getter := &mockGetProvider{
   419  		Providers: map[string][]string{
   420  			// looking for an exact version
   421  			"exact": []string{"1.2.3"},
   422  			// config requires >= 2.3.3
   423  			"greater_than": []string{"2.3.4", "2.3.3", "2.3.0"},
   424  			// config specifies
   425  			"between": []string{"3.4.5", "2.3.4", "1.2.3"},
   426  		},
   427  	}
   428  
   429  	ui := new(cli.MockUi)
   430  	c := &InitCommand{
   431  		Meta: Meta{
   432  			testingOverrides: metaOverridesForProvider(testProvider()),
   433  			Ui:               ui,
   434  		},
   435  		getProvider: getter.GetProvider,
   436  	}
   437  
   438  	args := []string{}
   439  	if code := c.Run(args); code != 0 {
   440  		t.Fatalf("bad: \n%s", ui.ErrorWriter.String())
   441  	}
   442  
   443  	// check that we got the providers for our config
   444  	exactPath := filepath.Join(c.pluginDir(), getter.FileName("exact", "1.2.3"))
   445  	if _, err := os.Stat(exactPath); os.IsNotExist(err) {
   446  		t.Fatal("provider 'exact' not downloaded")
   447  	}
   448  	greaterThanPath := filepath.Join(c.pluginDir(), getter.FileName("greater_than", "2.3.4"))
   449  	if _, err := os.Stat(greaterThanPath); os.IsNotExist(err) {
   450  		t.Fatal("provider 'greater_than' not downloaded")
   451  	}
   452  	betweenPath := filepath.Join(c.pluginDir(), getter.FileName("between", "2.3.4"))
   453  	if _, err := os.Stat(betweenPath); os.IsNotExist(err) {
   454  		t.Fatal("provider 'between' not downloaded")
   455  	}
   456  }
   457  
   458  func TestInit_getProviderMissing(t *testing.T) {
   459  	// Create a temporary working directory that is empty
   460  	td := tempDir(t)
   461  	copy.CopyDir(testFixturePath("init-get-providers"), td)
   462  	defer os.RemoveAll(td)
   463  	defer testChdir(t, td)()
   464  
   465  	getter := &mockGetProvider{
   466  		Providers: map[string][]string{
   467  			// looking for exact version 1.2.3
   468  			"exact": []string{"1.2.4"},
   469  			// config requires >= 2.3.3
   470  			"greater_than": []string{"2.3.4", "2.3.3", "2.3.0"},
   471  			// config specifies
   472  			"between": []string{"3.4.5", "2.3.4", "1.2.3"},
   473  		},
   474  	}
   475  
   476  	ui := new(cli.MockUi)
   477  	c := &InitCommand{
   478  		Meta: Meta{
   479  			testingOverrides: metaOverridesForProvider(testProvider()),
   480  			Ui:               ui,
   481  		},
   482  		getProvider: getter.GetProvider,
   483  	}
   484  
   485  	args := []string{}
   486  	if code := c.Run(args); code == 0 {
   487  		t.Fatalf("expceted error, got output: \n%s", ui.OutputWriter.String())
   488  	}
   489  
   490  	if !strings.Contains(ui.ErrorWriter.String(), "no suitable version for provider") {
   491  		t.Fatalf("unexpected error output: %s", ui.ErrorWriter)
   492  	}
   493  }
   494  
   495  func TestInit_getProviderHaveLegacyVersion(t *testing.T) {
   496  	// Create a temporary working directory that is empty
   497  	td := tempDir(t)
   498  	copy.CopyDir(testFixturePath("init-providers-lock"), td)
   499  	defer os.RemoveAll(td)
   500  	defer testChdir(t, td)()
   501  
   502  	if err := ioutil.WriteFile("terraform-provider-test", []byte("provider bin"), 0755); err != nil {
   503  		t.Fatal(err)
   504  	}
   505  
   506  	// provider test has a version constraint in the config, which should
   507  	// trigger the getProvider error below.
   508  	ui := new(cli.MockUi)
   509  	c := &InitCommand{
   510  		Meta: Meta{
   511  			testingOverrides: metaOverridesForProvider(testProvider()),
   512  			Ui:               ui,
   513  		},
   514  		getProvider: func(dst, provider string, req discovery.Constraints, protoVersion uint) error {
   515  			return fmt.Errorf("EXPECTED PROVIDER ERROR %s", provider)
   516  		},
   517  	}
   518  
   519  	args := []string{}
   520  	if code := c.Run(args); code == 0 {
   521  		t.Fatalf("expceted error, got output: \n%s", ui.OutputWriter.String())
   522  	}
   523  
   524  	if !strings.Contains(ui.ErrorWriter.String(), "EXPECTED PROVIDER ERROR test") {
   525  		t.Fatalf("unexpected error output: %s", ui.ErrorWriter)
   526  	}
   527  }
   528  
   529  func TestInit_providerLockFile(t *testing.T) {
   530  	// Create a temporary working directory that is empty
   531  	td := tempDir(t)
   532  	copy.CopyDir(testFixturePath("init-provider-lock-file"), td)
   533  	defer os.RemoveAll(td)
   534  	defer testChdir(t, td)()
   535  
   536  	getter := &mockGetProvider{
   537  		Providers: map[string][]string{
   538  			"test": []string{"1.2.3"},
   539  		},
   540  	}
   541  
   542  	ui := new(cli.MockUi)
   543  	c := &InitCommand{
   544  		Meta: Meta{
   545  			testingOverrides: metaOverridesForProvider(testProvider()),
   546  			Ui:               ui,
   547  		},
   548  		getProvider: getter.GetProvider,
   549  	}
   550  
   551  	args := []string{}
   552  	if code := c.Run(args); code != 0 {
   553  		t.Fatalf("bad: \n%s", ui.ErrorWriter.String())
   554  	}
   555  
   556  	providersLockFile := fmt.Sprintf(
   557  		".terraform/plugins/%s_%s/lock.json",
   558  		runtime.GOOS, runtime.GOARCH,
   559  	)
   560  	buf, err := ioutil.ReadFile(providersLockFile)
   561  	if err != nil {
   562  		t.Fatalf("failed to read providers lock file %s: %s", providersLockFile, err)
   563  	}
   564  	// The hash in here is for the empty files that mockGetProvider produces
   565  	wantLockFile := strings.TrimSpace(`
   566  {
   567    "test": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
   568  }
   569  `)
   570  	if string(buf) != wantLockFile {
   571  		t.Errorf("wrong provider lock file contents\ngot:  %s\nwant: %s", buf, wantLockFile)
   572  	}
   573  }