github.com/turtlemonvh/terraform@v0.6.9-0.20151204001754-8e40b6b855e8/command/refresh_test.go (about)

     1  package command
     2  
     3  import (
     4  	"bytes"
     5  	"io/ioutil"
     6  	"os"
     7  	"path/filepath"
     8  	"reflect"
     9  	"strings"
    10  	"testing"
    11  
    12  	"github.com/hashicorp/terraform/terraform"
    13  	"github.com/mitchellh/cli"
    14  )
    15  
    16  func TestRefresh(t *testing.T) {
    17  	state := testState()
    18  	statePath := testStateFile(t, state)
    19  
    20  	p := testProvider()
    21  	ui := new(cli.MockUi)
    22  	c := &RefreshCommand{
    23  		Meta: Meta{
    24  			ContextOpts: testCtxConfig(p),
    25  			Ui:          ui,
    26  		},
    27  	}
    28  
    29  	p.RefreshFn = nil
    30  	p.RefreshReturn = &terraform.InstanceState{ID: "yes"}
    31  
    32  	args := []string{
    33  		"-state", statePath,
    34  		testFixturePath("refresh"),
    35  	}
    36  	if code := c.Run(args); code != 0 {
    37  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
    38  	}
    39  
    40  	if !p.RefreshCalled {
    41  		t.Fatal("refresh should be called")
    42  	}
    43  
    44  	f, err := os.Open(statePath)
    45  	if err != nil {
    46  		t.Fatalf("err: %s", err)
    47  	}
    48  
    49  	newState, err := terraform.ReadState(f)
    50  	f.Close()
    51  	if err != nil {
    52  		t.Fatalf("err: %s", err)
    53  	}
    54  
    55  	actual := strings.TrimSpace(newState.String())
    56  	expected := strings.TrimSpace(testRefreshStr)
    57  	if actual != expected {
    58  		t.Fatalf("bad:\n\n%s", actual)
    59  	}
    60  }
    61  
    62  func TestRefresh_badState(t *testing.T) {
    63  	p := testProvider()
    64  	ui := new(cli.MockUi)
    65  	c := &RefreshCommand{
    66  		Meta: Meta{
    67  			ContextOpts: testCtxConfig(p),
    68  			Ui:          ui,
    69  		},
    70  	}
    71  
    72  	args := []string{
    73  		"-state", "i-should-not-exist-ever",
    74  		testFixturePath("refresh"),
    75  	}
    76  	if code := c.Run(args); code != 1 {
    77  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
    78  	}
    79  }
    80  
    81  func TestRefresh_cwd(t *testing.T) {
    82  	cwd, err := os.Getwd()
    83  	if err != nil {
    84  		t.Fatalf("err: %s", err)
    85  	}
    86  	if err := os.Chdir(testFixturePath("refresh")); err != nil {
    87  		t.Fatalf("err: %s", err)
    88  	}
    89  	defer os.Chdir(cwd)
    90  
    91  	state := testState()
    92  	statePath := testStateFile(t, state)
    93  
    94  	p := testProvider()
    95  	ui := new(cli.MockUi)
    96  	c := &RefreshCommand{
    97  		Meta: Meta{
    98  			ContextOpts: testCtxConfig(p),
    99  			Ui:          ui,
   100  		},
   101  	}
   102  
   103  	p.RefreshFn = nil
   104  	p.RefreshReturn = &terraform.InstanceState{ID: "yes"}
   105  
   106  	args := []string{
   107  		"-state", statePath,
   108  	}
   109  	if code := c.Run(args); code != 0 {
   110  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
   111  	}
   112  
   113  	if !p.RefreshCalled {
   114  		t.Fatal("refresh should be called")
   115  	}
   116  
   117  	f, err := os.Open(statePath)
   118  	if err != nil {
   119  		t.Fatalf("err: %s", err)
   120  	}
   121  
   122  	newState, err := terraform.ReadState(f)
   123  	f.Close()
   124  	if err != nil {
   125  		t.Fatalf("err: %s", err)
   126  	}
   127  
   128  	actual := strings.TrimSpace(newState.String())
   129  	expected := strings.TrimSpace(testRefreshCwdStr)
   130  	if actual != expected {
   131  		t.Fatalf("bad:\n\n%s", actual)
   132  	}
   133  }
   134  
   135  func TestRefresh_defaultState(t *testing.T) {
   136  	originalState := testState()
   137  
   138  	// Write the state file in a temporary directory with the
   139  	// default filename.
   140  	td, err := ioutil.TempDir("", "tf")
   141  	if err != nil {
   142  		t.Fatalf("err: %s", err)
   143  	}
   144  	statePath := filepath.Join(td, DefaultStateFilename)
   145  
   146  	f, err := os.Create(statePath)
   147  	if err != nil {
   148  		t.Fatalf("err: %s", err)
   149  	}
   150  	err = terraform.WriteState(originalState, f)
   151  	f.Close()
   152  	if err != nil {
   153  		t.Fatalf("err: %s", err)
   154  	}
   155  
   156  	// Change to that directory
   157  	cwd, err := os.Getwd()
   158  	if err != nil {
   159  		t.Fatalf("err: %s", err)
   160  	}
   161  	if err := os.Chdir(filepath.Dir(statePath)); err != nil {
   162  		t.Fatalf("err: %s", err)
   163  	}
   164  	defer os.Chdir(cwd)
   165  
   166  	p := testProvider()
   167  	ui := new(cli.MockUi)
   168  	c := &RefreshCommand{
   169  		Meta: Meta{
   170  			ContextOpts: testCtxConfig(p),
   171  			Ui:          ui,
   172  		},
   173  	}
   174  
   175  	p.RefreshFn = nil
   176  	p.RefreshReturn = &terraform.InstanceState{ID: "yes"}
   177  
   178  	args := []string{
   179  		testFixturePath("refresh"),
   180  	}
   181  	if code := c.Run(args); code != 0 {
   182  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
   183  	}
   184  
   185  	if !p.RefreshCalled {
   186  		t.Fatal("refresh should be called")
   187  	}
   188  
   189  	f, err = os.Open(statePath)
   190  	if err != nil {
   191  		t.Fatalf("err: %s", err)
   192  	}
   193  
   194  	newState, err := terraform.ReadState(f)
   195  	f.Close()
   196  	if err != nil {
   197  		t.Fatalf("err: %s", err)
   198  	}
   199  
   200  	actual := newState.RootModule().Resources["test_instance.foo"].Primary
   201  	expected := p.RefreshReturn
   202  	if !reflect.DeepEqual(actual, expected) {
   203  		t.Fatalf("bad: %#v", actual)
   204  	}
   205  
   206  	f, err = os.Open(statePath + DefaultBackupExtension)
   207  	if err != nil {
   208  		t.Fatalf("err: %s", err)
   209  	}
   210  
   211  	backupState, err := terraform.ReadState(f)
   212  	f.Close()
   213  	if err != nil {
   214  		t.Fatalf("err: %s", err)
   215  	}
   216  
   217  	actual = backupState.RootModule().Resources["test_instance.foo"].Primary
   218  	expected = originalState.RootModule().Resources["test_instance.foo"].Primary
   219  	if !reflect.DeepEqual(actual, expected) {
   220  		t.Fatalf("bad: %#v", actual)
   221  	}
   222  }
   223  
   224  func TestRefresh_outPath(t *testing.T) {
   225  	state := testState()
   226  	statePath := testStateFile(t, state)
   227  
   228  	// Output path
   229  	outf, err := ioutil.TempFile("", "tf")
   230  	if err != nil {
   231  		t.Fatalf("err: %s", err)
   232  	}
   233  	outPath := outf.Name()
   234  	outf.Close()
   235  	os.Remove(outPath)
   236  
   237  	p := testProvider()
   238  	ui := new(cli.MockUi)
   239  	c := &RefreshCommand{
   240  		Meta: Meta{
   241  			ContextOpts: testCtxConfig(p),
   242  			Ui:          ui,
   243  		},
   244  	}
   245  
   246  	p.RefreshFn = nil
   247  	p.RefreshReturn = &terraform.InstanceState{ID: "yes"}
   248  
   249  	args := []string{
   250  		"-state", statePath,
   251  		"-state-out", outPath,
   252  		testFixturePath("refresh"),
   253  	}
   254  	if code := c.Run(args); code != 0 {
   255  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
   256  	}
   257  
   258  	f, err := os.Open(statePath)
   259  	if err != nil {
   260  		t.Fatalf("err: %s", err)
   261  	}
   262  
   263  	newState, err := terraform.ReadState(f)
   264  	f.Close()
   265  	if err != nil {
   266  		t.Fatalf("err: %s", err)
   267  	}
   268  
   269  	if !reflect.DeepEqual(newState, state) {
   270  		t.Fatalf("bad: %#v", newState)
   271  	}
   272  
   273  	f, err = os.Open(outPath)
   274  	if err != nil {
   275  		t.Fatalf("err: %s", err)
   276  	}
   277  
   278  	newState, err = terraform.ReadState(f)
   279  	f.Close()
   280  	if err != nil {
   281  		t.Fatalf("err: %s", err)
   282  	}
   283  
   284  	actual := newState.RootModule().Resources["test_instance.foo"].Primary
   285  	expected := p.RefreshReturn
   286  	if !reflect.DeepEqual(actual, expected) {
   287  		t.Fatalf("bad: %#v", actual)
   288  	}
   289  
   290  	f, err = os.Open(outPath + DefaultBackupExtension)
   291  	if err != nil {
   292  		t.Fatalf("err: %s", err)
   293  	}
   294  
   295  	backupState, err := terraform.ReadState(f)
   296  	f.Close()
   297  	if err != nil {
   298  		t.Fatalf("err: %s", err)
   299  	}
   300  
   301  	actualStr := strings.TrimSpace(backupState.String())
   302  	expectedStr := strings.TrimSpace(state.String())
   303  	if actualStr != expectedStr {
   304  		t.Fatalf("bad:\n\n%s\n\n%s", actualStr, expectedStr)
   305  	}
   306  }
   307  
   308  func TestRefresh_var(t *testing.T) {
   309  	state := testState()
   310  	statePath := testStateFile(t, state)
   311  
   312  	p := testProvider()
   313  	ui := new(cli.MockUi)
   314  	c := &RefreshCommand{
   315  		Meta: Meta{
   316  			ContextOpts: testCtxConfig(p),
   317  			Ui:          ui,
   318  		},
   319  	}
   320  
   321  	args := []string{
   322  		"-var", "foo=bar",
   323  		"-state", statePath,
   324  		testFixturePath("refresh-var"),
   325  	}
   326  	if code := c.Run(args); code != 0 {
   327  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
   328  	}
   329  
   330  	if !p.ConfigureCalled {
   331  		t.Fatal("configure should be called")
   332  	}
   333  	if p.ConfigureConfig.Config["value"].(string) != "bar" {
   334  		t.Fatalf("bad: %#v", p.ConfigureConfig.Config)
   335  	}
   336  }
   337  
   338  func TestRefresh_varFile(t *testing.T) {
   339  	state := testState()
   340  	statePath := testStateFile(t, state)
   341  
   342  	p := testProvider()
   343  	ui := new(cli.MockUi)
   344  	c := &RefreshCommand{
   345  		Meta: Meta{
   346  			ContextOpts: testCtxConfig(p),
   347  			Ui:          ui,
   348  		},
   349  	}
   350  
   351  	varFilePath := testTempFile(t)
   352  	if err := ioutil.WriteFile(varFilePath, []byte(refreshVarFile), 0644); err != nil {
   353  		t.Fatalf("err: %s", err)
   354  	}
   355  
   356  	args := []string{
   357  		"-var-file", varFilePath,
   358  		"-state", statePath,
   359  		testFixturePath("refresh-var"),
   360  	}
   361  	if code := c.Run(args); code != 0 {
   362  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
   363  	}
   364  
   365  	if !p.ConfigureCalled {
   366  		t.Fatal("configure should be called")
   367  	}
   368  	if p.ConfigureConfig.Config["value"].(string) != "bar" {
   369  		t.Fatalf("bad: %#v", p.ConfigureConfig.Config)
   370  	}
   371  }
   372  
   373  func TestRefresh_varFileDefault(t *testing.T) {
   374  	state := testState()
   375  	statePath := testStateFile(t, state)
   376  
   377  	p := testProvider()
   378  	ui := new(cli.MockUi)
   379  	c := &RefreshCommand{
   380  		Meta: Meta{
   381  			ContextOpts: testCtxConfig(p),
   382  			Ui:          ui,
   383  		},
   384  	}
   385  
   386  	varFileDir := testTempDir(t)
   387  	varFilePath := filepath.Join(varFileDir, "terraform.tfvars")
   388  	if err := ioutil.WriteFile(varFilePath, []byte(refreshVarFile), 0644); err != nil {
   389  		t.Fatalf("err: %s", err)
   390  	}
   391  
   392  	cwd, err := os.Getwd()
   393  	if err != nil {
   394  		t.Fatalf("err: %s", err)
   395  	}
   396  	if err := os.Chdir(varFileDir); err != nil {
   397  		t.Fatalf("err: %s", err)
   398  	}
   399  	defer os.Chdir(cwd)
   400  
   401  	args := []string{
   402  		"-state", statePath,
   403  		testFixturePath("refresh-var"),
   404  	}
   405  	if code := c.Run(args); code != 0 {
   406  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
   407  	}
   408  
   409  	if !p.ConfigureCalled {
   410  		t.Fatal("configure should be called")
   411  	}
   412  	if p.ConfigureConfig.Config["value"].(string) != "bar" {
   413  		t.Fatalf("bad: %#v", p.ConfigureConfig.Config)
   414  	}
   415  }
   416  
   417  func TestRefresh_varsUnset(t *testing.T) {
   418  	// Disable test mode so input would be asked
   419  	test = false
   420  	defer func() { test = true }()
   421  
   422  	defaultInputReader = bytes.NewBufferString("bar\n")
   423  
   424  	state := testState()
   425  	statePath := testStateFile(t, state)
   426  
   427  	p := testProvider()
   428  	ui := new(cli.MockUi)
   429  	c := &RefreshCommand{
   430  		Meta: Meta{
   431  			ContextOpts: testCtxConfig(p),
   432  			Ui:          ui,
   433  		},
   434  	}
   435  
   436  	args := []string{
   437  		"-state", statePath,
   438  		testFixturePath("refresh-unset-var"),
   439  	}
   440  	if code := c.Run(args); code != 0 {
   441  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
   442  	}
   443  }
   444  
   445  func TestRefresh_backup(t *testing.T) {
   446  	state := testState()
   447  	statePath := testStateFile(t, state)
   448  
   449  	// Output path
   450  	outf, err := ioutil.TempFile("", "tf")
   451  	if err != nil {
   452  		t.Fatalf("err: %s", err)
   453  	}
   454  	outPath := outf.Name()
   455  	outf.Close()
   456  	os.Remove(outPath)
   457  
   458  	// Backup path
   459  	backupf, err := ioutil.TempFile("", "tf")
   460  	if err != nil {
   461  		t.Fatalf("err: %s", err)
   462  	}
   463  	backupPath := backupf.Name()
   464  	backupf.Close()
   465  	os.Remove(backupPath)
   466  
   467  	p := testProvider()
   468  	ui := new(cli.MockUi)
   469  	c := &RefreshCommand{
   470  		Meta: Meta{
   471  			ContextOpts: testCtxConfig(p),
   472  			Ui:          ui,
   473  		},
   474  	}
   475  
   476  	p.RefreshFn = nil
   477  	p.RefreshReturn = &terraform.InstanceState{ID: "yes"}
   478  
   479  	args := []string{
   480  		"-state", statePath,
   481  		"-state-out", outPath,
   482  		"-backup", backupPath,
   483  		testFixturePath("refresh"),
   484  	}
   485  	if code := c.Run(args); code != 0 {
   486  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
   487  	}
   488  
   489  	f, err := os.Open(statePath)
   490  	if err != nil {
   491  		t.Fatalf("err: %s", err)
   492  	}
   493  
   494  	newState, err := terraform.ReadState(f)
   495  	f.Close()
   496  	if err != nil {
   497  		t.Fatalf("err: %s", err)
   498  	}
   499  
   500  	if !reflect.DeepEqual(newState, state) {
   501  		t.Fatalf("bad: %#v", newState)
   502  	}
   503  
   504  	f, err = os.Open(outPath)
   505  	if err != nil {
   506  		t.Fatalf("err: %s", err)
   507  	}
   508  
   509  	newState, err = terraform.ReadState(f)
   510  	f.Close()
   511  	if err != nil {
   512  		t.Fatalf("err: %s", err)
   513  	}
   514  
   515  	actual := newState.RootModule().Resources["test_instance.foo"].Primary
   516  	expected := p.RefreshReturn
   517  	if !reflect.DeepEqual(actual, expected) {
   518  		t.Fatalf("bad: %#v", actual)
   519  	}
   520  
   521  	f, err = os.Open(backupPath)
   522  	if err != nil {
   523  		t.Fatalf("err: %s", err)
   524  	}
   525  
   526  	backupState, err := terraform.ReadState(f)
   527  	f.Close()
   528  	if err != nil {
   529  		t.Fatalf("err: %s", err)
   530  	}
   531  
   532  	actualStr := strings.TrimSpace(backupState.String())
   533  	expectedStr := strings.TrimSpace(state.String())
   534  	if actualStr != expectedStr {
   535  		t.Fatalf("bad:\n\n%s\n\n%s", actualStr, expectedStr)
   536  	}
   537  }
   538  
   539  func TestRefresh_disableBackup(t *testing.T) {
   540  	state := testState()
   541  	statePath := testStateFile(t, state)
   542  
   543  	// Output path
   544  	outf, err := ioutil.TempFile("", "tf")
   545  	if err != nil {
   546  		t.Fatalf("err: %s", err)
   547  	}
   548  	outPath := outf.Name()
   549  	outf.Close()
   550  	os.Remove(outPath)
   551  
   552  	p := testProvider()
   553  	ui := new(cli.MockUi)
   554  	c := &RefreshCommand{
   555  		Meta: Meta{
   556  			ContextOpts: testCtxConfig(p),
   557  			Ui:          ui,
   558  		},
   559  	}
   560  
   561  	p.RefreshFn = nil
   562  	p.RefreshReturn = &terraform.InstanceState{ID: "yes"}
   563  
   564  	args := []string{
   565  		"-state", statePath,
   566  		"-state-out", outPath,
   567  		"-backup", "-",
   568  		testFixturePath("refresh"),
   569  	}
   570  	if code := c.Run(args); code != 0 {
   571  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
   572  	}
   573  
   574  	f, err := os.Open(statePath)
   575  	if err != nil {
   576  		t.Fatalf("err: %s", err)
   577  	}
   578  
   579  	newState, err := terraform.ReadState(f)
   580  	f.Close()
   581  	if err != nil {
   582  		t.Fatalf("err: %s", err)
   583  	}
   584  
   585  	if !reflect.DeepEqual(newState, state) {
   586  		t.Fatalf("bad: %#v", newState)
   587  	}
   588  
   589  	f, err = os.Open(outPath)
   590  	if err != nil {
   591  		t.Fatalf("err: %s", err)
   592  	}
   593  
   594  	newState, err = terraform.ReadState(f)
   595  	f.Close()
   596  	if err != nil {
   597  		t.Fatalf("err: %s", err)
   598  	}
   599  
   600  	actual := newState.RootModule().Resources["test_instance.foo"].Primary
   601  	expected := p.RefreshReturn
   602  	if !reflect.DeepEqual(actual, expected) {
   603  		t.Fatalf("bad: %#v", actual)
   604  	}
   605  
   606  	// Ensure there is no backup
   607  	_, err = os.Stat(outPath + DefaultBackupExtension)
   608  	if err == nil || !os.IsNotExist(err) {
   609  		t.Fatalf("backup should not exist")
   610  	}
   611  }
   612  
   613  func TestRefresh_displaysOutputs(t *testing.T) {
   614  	state := testState()
   615  	statePath := testStateFile(t, state)
   616  
   617  	p := testProvider()
   618  	ui := new(cli.MockUi)
   619  	c := &RefreshCommand{
   620  		Meta: Meta{
   621  			ContextOpts: testCtxConfig(p),
   622  			Ui:          ui,
   623  		},
   624  	}
   625  
   626  	args := []string{
   627  		"-state", statePath,
   628  		testFixturePath("refresh-output"),
   629  	}
   630  	if code := c.Run(args); code != 0 {
   631  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
   632  	}
   633  
   634  	// Test that outputs were displayed
   635  	outputValue := "foo.example.com"
   636  	actual := ui.OutputWriter.String()
   637  	if !strings.Contains(actual, outputValue) {
   638  		t.Fatalf("Expected:\n%s\n\nTo include: %q", actual, outputValue)
   639  	}
   640  }
   641  
   642  const refreshVarFile = `
   643  foo = "bar"
   644  `
   645  
   646  const testRefreshStr = `
   647  test_instance.foo:
   648    ID = yes
   649  `
   650  const testRefreshCwdStr = `
   651  test_instance.foo:
   652    ID = yes
   653  `