command/show: fix issue with show and aliased provider (#23848)

The formatter in `command/format/state.go`, when formatting a resource
with an aliased provider, was looking for a schema with the alias (ie,
test.foo), but the schemas are only listed by provider type (test).
Update the state formatter to lookup schemas by provider type only.

Some of the show tests (and a couple others) were not properly cleaning
up the created tmpdirs, so I fixed those. Also, the show tests are using
a statefile named `state.tfstate`, but were not passing that path to the
show command, so we were getting some false positives (a `show` command
that returns `no state` exits 0).

Fixes #21462
This commit is contained in:
Kristin Laemmert 2020-01-13 15:10:00 -05:00 committed by GitHub
parent 272cb44d3d
commit 92f427779d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 69 additions and 5 deletions

View File

@ -139,7 +139,7 @@ func formatStateModule(p blockBodyDiffPrinter, m *states.Module, schemas *terraf
}
var schema *configschema.Block
provider := m.Resources[key].ProviderConfig.ProviderConfig.StringCompact()
provider := addr.DefaultProviderConfig().Absolute(m.Addr).ProviderConfig.StringCompact()
if _, exists := schemas.Providers[provider]; !exists {
// This should never happen in normal use because we should've
// loaded all of the schemas and checked things prior to this

View File

@ -1237,6 +1237,7 @@ func TestInit_providerLockFile(t *testing.T) {
func TestInit_pluginDirReset(t *testing.T) {
td := testTempDir(t)
defer os.RemoveAll(td)
defer testChdir(t, td)()
ui := new(cli.MockUi)

View File

@ -99,6 +99,7 @@ func TestMultiVersionProviderResolver(t *testing.T) {
func TestPluginPath(t *testing.T) {
td := testTempDir(t)
defer os.RemoveAll(td)
defer testChdir(t, td)()
pluginPath := []string{"a", "b", "c"}

View File

@ -2,6 +2,7 @@ package command
import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
"path/filepath"
@ -41,7 +42,9 @@ func TestShow(t *testing.T) {
func TestShow_noArgs(t *testing.T) {
// Create the default state
statePath := testStateFile(t, testState())
defer testChdir(t, filepath.Dir(statePath))()
stateDir := filepath.Dir(statePath)
defer os.RemoveAll(stateDir)
defer testChdir(t, stateDir)()
ui := new(cli.MockUi)
c := &ShowCommand{
@ -51,16 +54,73 @@ func TestShow_noArgs(t *testing.T) {
},
}
args := []string{}
// the statefile created by testStateFile is named state.tfstate
// so one arg is required
args := []string{"state.tfstate"}
if code := c.Run(args); code != 0 {
t.Fatalf("bad: \n%s", ui.OutputWriter.String())
}
if !strings.Contains(ui.OutputWriter.String(), "# test_instance.foo:") {
t.Fatalf("bad: \n%s", ui.ErrorWriter.String())
}
}
// https://github.com/hashicorp/terraform/issues/21462
func TestShow_aliasedProvider(t *testing.T) {
// Create the default state with aliased resource
testState := states.BuildState(func(s *states.SyncState) {
s.SetResourceInstanceCurrent(
addrs.Resource{
Mode: addrs.ManagedResourceMode,
Type: "test_instance",
Name: "foo",
}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
&states.ResourceInstanceObjectSrc{
// The weird whitespace here is reflective of how this would
// get written out in a real state file, due to the indentation
// of all of the containing wrapping objects and arrays.
AttrsJSON: []byte("{\n \"id\": \"bar\"\n }"),
Status: states.ObjectReady,
Dependencies: []addrs.AbsResource{},
DependsOn: []addrs.Referenceable{},
},
addrs.RootModuleInstance.ProviderConfigAliased("test", "alias"),
)
})
statePath := testStateFile(t, testState)
stateDir := filepath.Dir(statePath)
defer os.RemoveAll(stateDir)
defer testChdir(t, stateDir)()
ui := new(cli.MockUi)
c := &ShowCommand{
Meta: Meta{
testingOverrides: metaOverridesForProvider(testProvider()),
Ui: ui,
},
}
fmt.Println(os.Getwd())
// the statefile created by testStateFile is named state.tfstate
args := []string{"state.tfstate"}
if code := c.Run(args); code != 0 {
t.Fatalf("bad exit code: \n%s", ui.OutputWriter.String())
}
if strings.Contains(ui.OutputWriter.String(), "# missing schema for provider \"test.alias\"") {
t.Fatalf("bad output: \n%s", ui.OutputWriter.String())
}
}
func TestShow_noArgsNoState(t *testing.T) {
// Create the default state
statePath := testStateFile(t, testState())
defer testChdir(t, filepath.Dir(statePath))()
stateDir := filepath.Dir(statePath)
defer os.RemoveAll(stateDir)
defer testChdir(t, stateDir)()
ui := new(cli.MockUi)
c := &ShowCommand{
@ -70,7 +130,8 @@ func TestShow_noArgsNoState(t *testing.T) {
},
}
args := []string{}
// the statefile created by testStateFile is named state.tfstate
args := []string{"state.tfstate"}
if code := c.Run(args); code != 0 {
t.Fatalf("bad: \n%s", ui.OutputWriter.String())
}
@ -150,6 +211,7 @@ func TestShow_plan_json(t *testing.T) {
func TestShow_state(t *testing.T) {
originalState := testState()
statePath := testStateFile(t, originalState)
defer os.RemoveAll(filepath.Dir(statePath))
ui := new(cli.MockUi)
c := &ShowCommand{