github.com/spirius/terraform@v0.10.0-beta2.0.20170714185654-87b2c0cf8fea/command/import_test.go (about)

     1  package command
     2  
     3  import (
     4  	"fmt"
     5  	"io/ioutil"
     6  	"os"
     7  	"strings"
     8  	"testing"
     9  
    10  	"github.com/hashicorp/terraform/helper/copy"
    11  	"github.com/hashicorp/terraform/plugin"
    12  	"github.com/hashicorp/terraform/plugin/discovery"
    13  	"github.com/hashicorp/terraform/terraform"
    14  	"github.com/mitchellh/cli"
    15  )
    16  
    17  func TestImport(t *testing.T) {
    18  	defer testChdir(t, testFixturePath("import-provider-implicit"))()
    19  
    20  	statePath := testTempFile(t)
    21  
    22  	p := testProvider()
    23  	ui := new(cli.MockUi)
    24  	c := &ImportCommand{
    25  		Meta: Meta{
    26  			testingOverrides: metaOverridesForProvider(p),
    27  			Ui:               ui,
    28  		},
    29  	}
    30  
    31  	p.ImportStateFn = nil
    32  	p.ImportStateReturn = []*terraform.InstanceState{
    33  		&terraform.InstanceState{
    34  			ID: "yay",
    35  			Ephemeral: terraform.EphemeralState{
    36  				Type: "test_instance",
    37  			},
    38  		},
    39  	}
    40  
    41  	args := []string{
    42  		"-state", statePath,
    43  		"test_instance.foo",
    44  		"bar",
    45  	}
    46  	if code := c.Run(args); code != 0 {
    47  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
    48  	}
    49  
    50  	if !p.ImportStateCalled {
    51  		t.Fatal("ImportState should be called")
    52  	}
    53  
    54  	testStateOutput(t, statePath, testImportStr)
    55  }
    56  
    57  func TestImport_providerConfig(t *testing.T) {
    58  	defer testChdir(t, testFixturePath("import-provider"))()
    59  
    60  	statePath := testTempFile(t)
    61  
    62  	p := testProvider()
    63  	ui := new(cli.MockUi)
    64  	c := &ImportCommand{
    65  		Meta: Meta{
    66  			testingOverrides: metaOverridesForProvider(p),
    67  			Ui:               ui,
    68  		},
    69  	}
    70  
    71  	p.ImportStateFn = nil
    72  	p.ImportStateReturn = []*terraform.InstanceState{
    73  		&terraform.InstanceState{
    74  			ID: "yay",
    75  			Ephemeral: terraform.EphemeralState{
    76  				Type: "test_instance",
    77  			},
    78  		},
    79  	}
    80  
    81  	configured := false
    82  	p.ConfigureFn = func(c *terraform.ResourceConfig) error {
    83  		configured = true
    84  
    85  		if v, ok := c.Get("foo"); !ok || v.(string) != "bar" {
    86  			return fmt.Errorf("bad value: %#v", v)
    87  		}
    88  
    89  		return nil
    90  	}
    91  
    92  	args := []string{
    93  		"-state", statePath,
    94  		"test_instance.foo",
    95  		"bar",
    96  	}
    97  	if code := c.Run(args); code != 0 {
    98  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
    99  	}
   100  
   101  	// Verify that we were called
   102  	if !configured {
   103  		t.Fatal("Configure should be called")
   104  	}
   105  
   106  	if !p.ImportStateCalled {
   107  		t.Fatal("ImportState should be called")
   108  	}
   109  
   110  	testStateOutput(t, statePath, testImportStr)
   111  }
   112  
   113  func TestImport_providerConfigWithVar(t *testing.T) {
   114  	defer testChdir(t, testFixturePath("import-provider-var"))()
   115  
   116  	statePath := testTempFile(t)
   117  
   118  	p := testProvider()
   119  	ui := new(cli.MockUi)
   120  	c := &ImportCommand{
   121  		Meta: Meta{
   122  			testingOverrides: metaOverridesForProvider(p),
   123  			Ui:               ui,
   124  		},
   125  	}
   126  
   127  	p.ImportStateFn = nil
   128  	p.ImportStateReturn = []*terraform.InstanceState{
   129  		&terraform.InstanceState{
   130  			ID: "yay",
   131  			Ephemeral: terraform.EphemeralState{
   132  				Type: "test_instance",
   133  			},
   134  		},
   135  	}
   136  
   137  	configured := false
   138  	p.ConfigureFn = func(c *terraform.ResourceConfig) error {
   139  		configured = true
   140  
   141  		if v, ok := c.Get("foo"); !ok || v.(string) != "bar" {
   142  			return fmt.Errorf("bad value: %#v", v)
   143  		}
   144  
   145  		return nil
   146  	}
   147  
   148  	args := []string{
   149  		"-state", statePath,
   150  		"-var", "foo=bar",
   151  		"test_instance.foo",
   152  		"bar",
   153  	}
   154  	if code := c.Run(args); code != 0 {
   155  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
   156  	}
   157  
   158  	// Verify that we were called
   159  	if !configured {
   160  		t.Fatal("Configure should be called")
   161  	}
   162  
   163  	if !p.ImportStateCalled {
   164  		t.Fatal("ImportState should be called")
   165  	}
   166  
   167  	testStateOutput(t, statePath, testImportStr)
   168  }
   169  
   170  func TestImport_providerConfigWithVarDefault(t *testing.T) {
   171  	defer testChdir(t, testFixturePath("import-provider-var-default"))()
   172  
   173  	statePath := testTempFile(t)
   174  
   175  	p := testProvider()
   176  	ui := new(cli.MockUi)
   177  	c := &ImportCommand{
   178  		Meta: Meta{
   179  			testingOverrides: metaOverridesForProvider(p),
   180  			Ui:               ui,
   181  		},
   182  	}
   183  
   184  	p.ImportStateFn = nil
   185  	p.ImportStateReturn = []*terraform.InstanceState{
   186  		&terraform.InstanceState{
   187  			ID: "yay",
   188  			Ephemeral: terraform.EphemeralState{
   189  				Type: "test_instance",
   190  			},
   191  		},
   192  	}
   193  
   194  	configured := false
   195  	p.ConfigureFn = func(c *terraform.ResourceConfig) error {
   196  		configured = true
   197  
   198  		if v, ok := c.Get("foo"); !ok || v.(string) != "bar" {
   199  			return fmt.Errorf("bad value: %#v", v)
   200  		}
   201  
   202  		return nil
   203  	}
   204  
   205  	args := []string{
   206  		"-state", statePath,
   207  		"test_instance.foo",
   208  		"bar",
   209  	}
   210  	if code := c.Run(args); code != 0 {
   211  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
   212  	}
   213  
   214  	// Verify that we were called
   215  	if !configured {
   216  		t.Fatal("Configure should be called")
   217  	}
   218  
   219  	if !p.ImportStateCalled {
   220  		t.Fatal("ImportState should be called")
   221  	}
   222  
   223  	testStateOutput(t, statePath, testImportStr)
   224  }
   225  
   226  func TestImport_providerConfigWithVarFile(t *testing.T) {
   227  	defer testChdir(t, testFixturePath("import-provider-var-file"))()
   228  
   229  	statePath := testTempFile(t)
   230  
   231  	p := testProvider()
   232  	ui := new(cli.MockUi)
   233  	c := &ImportCommand{
   234  		Meta: Meta{
   235  			testingOverrides: metaOverridesForProvider(p),
   236  			Ui:               ui,
   237  		},
   238  	}
   239  
   240  	p.ImportStateFn = nil
   241  	p.ImportStateReturn = []*terraform.InstanceState{
   242  		&terraform.InstanceState{
   243  			ID: "yay",
   244  			Ephemeral: terraform.EphemeralState{
   245  				Type: "test_instance",
   246  			},
   247  		},
   248  	}
   249  
   250  	configured := false
   251  	p.ConfigureFn = func(c *terraform.ResourceConfig) error {
   252  		configured = true
   253  
   254  		if v, ok := c.Get("foo"); !ok || v.(string) != "bar" {
   255  			return fmt.Errorf("bad value: %#v", v)
   256  		}
   257  
   258  		return nil
   259  	}
   260  
   261  	args := []string{
   262  		"-state", statePath,
   263  		"-var-file", "blah.tfvars",
   264  		"test_instance.foo",
   265  		"bar",
   266  	}
   267  	if code := c.Run(args); code != 0 {
   268  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
   269  	}
   270  
   271  	// Verify that we were called
   272  	if !configured {
   273  		t.Fatal("Configure should be called")
   274  	}
   275  
   276  	if !p.ImportStateCalled {
   277  		t.Fatal("ImportState should be called")
   278  	}
   279  
   280  	testStateOutput(t, statePath, testImportStr)
   281  }
   282  
   283  func TestImport_customProvider(t *testing.T) {
   284  	defer testChdir(t, testFixturePath("import-provider-aliased"))()
   285  
   286  	statePath := testTempFile(t)
   287  
   288  	p := testProvider()
   289  	ui := new(cli.MockUi)
   290  	c := &ImportCommand{
   291  		Meta: Meta{
   292  			testingOverrides: metaOverridesForProvider(p),
   293  			Ui:               ui,
   294  		},
   295  	}
   296  
   297  	p.ImportStateFn = nil
   298  	p.ImportStateReturn = []*terraform.InstanceState{
   299  		&terraform.InstanceState{
   300  			ID: "yay",
   301  			Ephemeral: terraform.EphemeralState{
   302  				Type: "test_instance",
   303  			},
   304  		},
   305  	}
   306  
   307  	args := []string{
   308  		"-provider", "test.alias",
   309  		"-state", statePath,
   310  		"test_instance.foo",
   311  		"bar",
   312  	}
   313  	if code := c.Run(args); code != 0 {
   314  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
   315  	}
   316  
   317  	if !p.ImportStateCalled {
   318  		t.Fatal("ImportState should be called")
   319  	}
   320  
   321  	testStateOutput(t, statePath, testImportCustomProviderStr)
   322  }
   323  
   324  func TestImport_missingResourceConfig(t *testing.T) {
   325  	defer testChdir(t, testFixturePath("import-missing-resource-config"))()
   326  
   327  	statePath := testTempFile(t)
   328  
   329  	p := testProvider()
   330  	ui := new(cli.MockUi)
   331  	c := &ImportCommand{
   332  		Meta: Meta{
   333  			testingOverrides: metaOverridesForProvider(p),
   334  			Ui:               ui,
   335  		},
   336  	}
   337  
   338  	args := []string{
   339  		"-state", statePath,
   340  		"test_instance.foo",
   341  		"bar",
   342  	}
   343  	code := c.Run(args)
   344  	if code != 1 {
   345  		t.Fatalf("import succeeded; expected failure")
   346  	}
   347  
   348  	msg := ui.ErrorWriter.String()
   349  	if want := `resource address "test_instance.foo" does not exist`; !strings.Contains(msg, want) {
   350  		t.Errorf("incorrect message\nwant substring: %s\ngot:\n%s", want, msg)
   351  	}
   352  }
   353  
   354  func TestImport_missingModuleConfig(t *testing.T) {
   355  	defer testChdir(t, testFixturePath("import-missing-resource-config"))()
   356  
   357  	statePath := testTempFile(t)
   358  
   359  	p := testProvider()
   360  	ui := new(cli.MockUi)
   361  	c := &ImportCommand{
   362  		Meta: Meta{
   363  			testingOverrides: metaOverridesForProvider(p),
   364  			Ui:               ui,
   365  		},
   366  	}
   367  
   368  	args := []string{
   369  		"-state", statePath,
   370  		"module.baz.test_instance.foo",
   371  		"bar",
   372  	}
   373  	code := c.Run(args)
   374  	if code != 1 {
   375  		t.Fatalf("import succeeded; expected failure")
   376  	}
   377  
   378  	msg := ui.ErrorWriter.String()
   379  	if want := `module.baz does not exist in the configuration`; !strings.Contains(msg, want) {
   380  		t.Errorf("incorrect message\nwant substring: %s\ngot:\n%s", want, msg)
   381  	}
   382  }
   383  
   384  func TestImport_dataResource(t *testing.T) {
   385  	defer testChdir(t, testFixturePath("import-missing-resource-config"))()
   386  
   387  	statePath := testTempFile(t)
   388  
   389  	p := testProvider()
   390  	ui := new(cli.MockUi)
   391  	c := &ImportCommand{
   392  		Meta: Meta{
   393  			testingOverrides: metaOverridesForProvider(p),
   394  			Ui:               ui,
   395  		},
   396  	}
   397  
   398  	args := []string{
   399  		"-state", statePath,
   400  		"data.test_data_source.foo",
   401  		"bar",
   402  	}
   403  	code := c.Run(args)
   404  	if code != 1 {
   405  		t.Fatalf("import succeeded; expected failure")
   406  	}
   407  
   408  	msg := ui.ErrorWriter.String()
   409  	if want := `resource address must refer to a managed resource`; !strings.Contains(msg, want) {
   410  		t.Errorf("incorrect message\nwant substring: %s\ngot:\n%s", want, msg)
   411  	}
   412  }
   413  
   414  func TestImport_invalidResourceAddr(t *testing.T) {
   415  	defer testChdir(t, testFixturePath("import-missing-resource-config"))()
   416  
   417  	statePath := testTempFile(t)
   418  
   419  	p := testProvider()
   420  	ui := new(cli.MockUi)
   421  	c := &ImportCommand{
   422  		Meta: Meta{
   423  			testingOverrides: metaOverridesForProvider(p),
   424  			Ui:               ui,
   425  		},
   426  	}
   427  
   428  	args := []string{
   429  		"-state", statePath,
   430  		"bananas",
   431  		"bar",
   432  	}
   433  	code := c.Run(args)
   434  	if code != 1 {
   435  		t.Fatalf("import succeeded; expected failure")
   436  	}
   437  
   438  	msg := ui.ErrorWriter.String()
   439  	if want := `invalid resource address "bananas"`; !strings.Contains(msg, want) {
   440  		t.Errorf("incorrect message\nwant substring: %s\ngot:\n%s", want, msg)
   441  	}
   442  }
   443  
   444  func TestImport_targetIsModule(t *testing.T) {
   445  	defer testChdir(t, testFixturePath("import-missing-resource-config"))()
   446  
   447  	statePath := testTempFile(t)
   448  
   449  	p := testProvider()
   450  	ui := new(cli.MockUi)
   451  	c := &ImportCommand{
   452  		Meta: Meta{
   453  			testingOverrides: metaOverridesForProvider(p),
   454  			Ui:               ui,
   455  		},
   456  	}
   457  
   458  	args := []string{
   459  		"-state", statePath,
   460  		"module.foo",
   461  		"bar",
   462  	}
   463  	code := c.Run(args)
   464  	if code != 1 {
   465  		t.Fatalf("import succeeded; expected failure")
   466  	}
   467  
   468  	msg := ui.ErrorWriter.String()
   469  	if want := `resource address must include a full resource spec`; !strings.Contains(msg, want) {
   470  		t.Errorf("incorrect message\nwant substring: %s\ngot:\n%s", want, msg)
   471  	}
   472  }
   473  
   474  // make sure we search the full plugin path during import
   475  func TestImport_pluginDir(t *testing.T) {
   476  	td := tempDir(t)
   477  	copy.CopyDir(testFixturePath("import-provider"), td)
   478  	defer os.RemoveAll(td)
   479  	defer testChdir(t, td)()
   480  
   481  	// make a fake provider in a custom plugin directory
   482  	if err := os.Mkdir("plugins", 0755); err != nil {
   483  		t.Fatal(err)
   484  	}
   485  	if err := ioutil.WriteFile("plugins/terraform-provider-test_v1.1.1_x4", []byte("invalid binary"), 0755); err != nil {
   486  		t.Fatal(err)
   487  	}
   488  
   489  	ui := new(cli.MockUi)
   490  	c := &ImportCommand{
   491  		Meta: Meta{
   492  			Ui: ui,
   493  		},
   494  	}
   495  
   496  	// store our custom plugin path, which would normally happen during init
   497  	if err := c.storePluginPath([]string{"./plugins"}); err != nil {
   498  		t.Fatal(err)
   499  	}
   500  
   501  	// Now we need to go through some plugin init.
   502  	// This discovers our fake plugin and writes the lock file.
   503  	initCmd := &InitCommand{
   504  		Meta: Meta{
   505  			pluginPath: []string{"./plugins"},
   506  			Ui:         new(cli.MockUi),
   507  		},
   508  		providerInstaller: &discovery.ProviderInstaller{
   509  			PluginProtocolVersion: plugin.Handshake.ProtocolVersion,
   510  		},
   511  	}
   512  	if err := initCmd.getProviders(".", nil, false); err != nil {
   513  		t.Fatal(err)
   514  	}
   515  
   516  	args := []string{
   517  		"test_instance.foo",
   518  		"bar",
   519  	}
   520  	if code := c.Run(args); code == 0 {
   521  		t.Fatalf("expected error, got: %s", ui.OutputWriter)
   522  	}
   523  
   524  	outMsg := ui.OutputWriter.String()
   525  	// if we were missing a plugin, the output will have some explanation
   526  	// about requirements. If discovery starts verifying binary compatibility,
   527  	// we will need to write a dummy provider above.
   528  	if strings.Contains(outMsg, "requirements") {
   529  		t.Fatal("unexpected output:", outMsg)
   530  	}
   531  
   532  	// We wanted a plugin execution error, rather than a requirement error.
   533  	// Looking for "exec" in the error should suffice for now.
   534  	errMsg := ui.ErrorWriter.String()
   535  	if !strings.Contains(errMsg, "exec") {
   536  		t.Fatal("unexpected error:", errMsg)
   537  	}
   538  }
   539  
   540  const testImportStr = `
   541  test_instance.foo:
   542    ID = yay
   543    provider = test
   544  `
   545  
   546  const testImportCustomProviderStr = `
   547  test_instance.foo:
   548    ID = yay
   549    provider = test.alias
   550  `