Merge pull request #30205 from hashicorp/alisdair/fix-show-plan-against-non-default-state

command/show: Disable plan state lineage checks
This commit is contained in:
Alisdair McDiarmid 2022-01-05 12:03:28 -05:00 committed by GitHub
commit 535da4ebc7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 57 additions and 1 deletions

View File

@ -275,6 +275,13 @@ type Operation struct {
// the variables set in the plan are used instead, and they must be valid.
AllowUnsetVariables bool
// When loading a plan file for a read-only operation, we may want to
// disable the state lineage checks which are only relevant for operations
// which can modify state. An example where this is important is showing
// a plan which was prepared against a non-default state file, because the
// lineage checks are always against the default state.
DisablePlanFileStateLineageChecks bool
// View implements the logic for all UI interactions.
View views.Operation

View File

@ -284,7 +284,7 @@ func (b *Local) localRunForPlanFile(op *backend.Operation, pf *planfile.Reader,
))
return nil, snap, diags
}
if currentStateMeta != nil {
if !op.DisablePlanFileStateLineageChecks && currentStateMeta != nil {
// If the caller sets this, we require that the stored prior state
// has the same metadata, which is an extra safety check that nothing
// has changed since the plan was created. (All of the "real-world"

View File

@ -94,6 +94,7 @@ func (c *ShowCommand) Run(args []string) int {
opReq.PlanFile = planFile
opReq.ConfigLoader, err = c.initConfigLoader()
opReq.AllowUnsetVariables = true
opReq.DisablePlanFileStateLineageChecks = true
if err != nil {
diags = diags.Append(err)
c.showDiagnostics(diags)

View File

@ -15,7 +15,9 @@ import (
"github.com/hashicorp/terraform/internal/plans"
"github.com/hashicorp/terraform/internal/providers"
"github.com/hashicorp/terraform/internal/states"
"github.com/hashicorp/terraform/internal/states/statemgr"
"github.com/hashicorp/terraform/internal/terraform"
"github.com/hashicorp/terraform/version"
"github.com/mitchellh/cli"
"github.com/zclconf/go-cty/cty"
)
@ -575,6 +577,52 @@ func TestShow_json_output_state(t *testing.T) {
}
}
func TestShow_planWithNonDefaultStateLineage(t *testing.T) {
// Create a temporary working directory that is empty
td := tempDir(t)
testCopyDir(t, testFixturePath("show"), td)
defer os.RemoveAll(td)
defer testChdir(t, td)()
// Write default state file with a testing lineage ("fake-for-testing")
testStateFileDefault(t, testState())
// Create a plan with a different lineage, which we should still be able
// to show
_, snap := testModuleWithSnapshot(t, "show")
state := testState()
plan := testPlan(t)
stateMeta := statemgr.SnapshotMeta{
Lineage: "fake-for-plan",
Serial: 1,
TerraformVersion: version.SemVer,
}
planPath := testPlanFileMatchState(t, snap, state, plan, stateMeta)
ui := cli.NewMockUi()
view, done := testView(t)
c := &ShowCommand{
Meta: Meta{
testingOverrides: metaOverridesForProvider(testProvider()),
Ui: ui,
View: view,
},
}
args := []string{
planPath,
}
if code := c.Run(args); code != 0 {
t.Fatalf("bad: \n%s", ui.ErrorWriter.String())
}
want := `No changes. Your infrastructure matches the configuration.`
got := done(t).Stdout()
if !strings.Contains(got, want) {
t.Errorf("missing expected output\nwant: %s\ngot:\n%s", want, got)
}
}
// showFixtureSchema returns a schema suitable for processing the configuration
// in testdata/show. This schema should be assigned to a mock provider
// named "test".