Don't ForceLocal for the import backend

While the `local.Local` backend is the only implementation of
`backend.Local`, creating the backend with `ForceLocal` bypasses the
`backend.Backend` in the `local.Local` causing a local state to be
implicitly created rather than using the configured state backend.

Add a test that imports into a configured backend (using the "local"
backend as a remote state proxy). This further confirms the confusing
nature of ForceLocal, as the backend _is_ local, but not from the
viewpoint of meta.Backend.
This commit is contained in:
James Bardin 2017-08-08 18:41:00 -04:00
parent 8b3b678c2f
commit e3748901b4
3 changed files with 100 additions and 3 deletions

View File

@ -123,15 +123,18 @@ func (c *ImportCommand) Run(args []string) int {
// Load the backend
b, err := c.Backend(&BackendOpts{
Config: mod.Config(),
ForceLocal: true,
Config: mod.Config(),
})
if err != nil {
c.Ui.Error(fmt.Sprintf("Failed to load backend: %s", err))
return 1
}
// We require a local backend
// We require a backend.Local to build a context.
// This isn't necessarily a "local.Local" backend, which provides local
// operations, however that is the only current implementation. A
// "local.Local" backend also doesn't necessarily provide local state, as
// that may be delegated to a "remotestate.Backend".
local, ok := b.(backend.Local)
if !ok {
c.Ui.Error(ErrUnsupportedLocalOp)

View File

@ -110,6 +110,88 @@ func TestImport_providerConfig(t *testing.T) {
testStateOutput(t, statePath, testImportStr)
}
// "remote" state provided by the "local" backend
func TestImport_remoteState(t *testing.T) {
td := tempDir(t)
copy.CopyDir(testFixturePath("import-provider-remote-state"), td)
defer os.RemoveAll(td)
defer testChdir(t, td)()
statePath := "imported.tfstate"
// init our backend
ui := new(cli.MockUi)
m := Meta{
testingOverrides: metaOverridesForProvider(testProvider()),
Ui: ui,
}
ic := &InitCommand{
Meta: m,
providerInstaller: &mockProviderInstaller{
Providers: map[string][]string{
"test": []string{"1.2.3"},
},
Dir: m.pluginDir(),
},
}
if code := ic.Run([]string{}); code != 0 {
t.Fatalf("bad: \n%s", ui.ErrorWriter)
}
p := testProvider()
ui = new(cli.MockUi)
c := &ImportCommand{
Meta: Meta{
testingOverrides: metaOverridesForProvider(p),
Ui: ui,
},
}
p.ImportStateFn = nil
p.ImportStateReturn = []*terraform.InstanceState{
&terraform.InstanceState{
ID: "yay",
Ephemeral: terraform.EphemeralState{
Type: "test_instance",
},
},
}
configured := false
p.ConfigureFn = func(c *terraform.ResourceConfig) error {
configured = true
if v, ok := c.Get("foo"); !ok || v.(string) != "bar" {
return fmt.Errorf("bad value: %#v", v)
}
return nil
}
args := []string{
"test_instance.foo",
"bar",
}
if code := c.Run(args); code != 0 {
fmt.Println(ui.OutputWriter)
t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
}
// Verify that we were called
if !configured {
t.Fatal("Configure should be called")
}
if !p.ImportStateCalled {
t.Fatal("ImportState should be called")
}
testStateOutput(t, statePath, testImportStr)
}
func TestImport_providerConfigWithVar(t *testing.T) {
defer testChdir(t, testFixturePath("import-provider-var"))()

View File

@ -0,0 +1,12 @@
terraform {
backend "local" {
path = "imported.tfstate"
}
}
provider "test" {
foo = "bar"
}
resource "test_instance" "foo" {
}