Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

terraform test: remove planned state from plan #35049

Merged
merged 2 commits into from
May 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 4 additions & 4 deletions internal/backend/local/test.go
Original file line number Diff line number Diff line change
Expand Up @@ -463,7 +463,7 @@ func (runner *TestFileRunner) run(run *moduletest.Run, file *moduletest.File, st
defer resetVariables()

if runner.Suite.Verbose {
schemas, diags := tfCtx.Schemas(config, plan.PlannedState)
schemas, diags := tfCtx.Schemas(config, plan.PriorState)

// If we're going to fail to render the plan, let's not fail the overall
// test. It can still have succeeded. So we'll add the diagnostics, but
Expand All @@ -477,7 +477,7 @@ func (runner *TestFileRunner) run(run *moduletest.Run, file *moduletest.File, st
} else {
run.Verbose = &moduletest.Verbose{
Plan: plan,
State: plan.PlannedState,
State: nil, // We don't have a state to show in plan mode.
Config: config,
Providers: schemas.Providers,
Provisioners: schemas.Provisioners,
Expand Down Expand Up @@ -551,7 +551,7 @@ func (runner *TestFileRunner) run(run *moduletest.Run, file *moduletest.File, st
}

if runner.Suite.Verbose {
schemas, diags := tfCtx.Schemas(config, plan.PlannedState)
schemas, diags := tfCtx.Schemas(config, updated)

// If we're going to fail to render the plan, let's not fail the overall
// test. It can still have succeeded. So we'll add the diagnostics, but
Expand All @@ -564,7 +564,7 @@ func (runner *TestFileRunner) run(run *moduletest.Run, file *moduletest.File, st
fmt.Sprintf("Terraform failed to print the verbose output for %s, other diagnostics will contain more details as to why.", filepath.Join(file.Name, run.Name))))
} else {
run.Verbose = &moduletest.Verbose{
Plan: plan,
Plan: nil, // We don't have a plan to show in apply mode.
State: updated,
Config: config,
Providers: schemas.Providers,
Expand Down
22 changes: 5 additions & 17 deletions internal/plans/plan.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,34 +118,22 @@ type Plan struct {
PrevRunState *states.State
PriorState *states.State

// PlannedState is the temporary planned state that was created during the
// graph walk that generated this plan.
//
// This is required by the testing framework when evaluating run blocks
// executing in plan mode. The graph updates the state with certain values
// that are difficult to retrieve later, such as local values that reference
// updated resources. It is easier to build the testing scope with access
// to same temporary state the plan used/built.
// ExternalReferences are references that are being made to resources within
// the plan from external sources.
//
// This is never recorded outside of Terraform. It is not written into the
// binary plan file, and it is not written into the JSON structured outputs.
// The testing framework never writes the plans out but holds everything in
// memory as it executes, so there is no need to add any kind of
// serialization for this field. This does mean that you shouldn't rely on
// this field existing unless you have just generated the plan.
PlannedState *states.State

// ExternalReferences are references that are being made to resources within
// the plan from external sources. As with PlannedState this is used by the
// terraform testing framework, and so isn't written into any external
// representation of the plan.
ExternalReferences []*addrs.Reference

// Overrides contains the set of overrides that were applied while making
// this plan. We need to provide the same set of overrides when applying
// the plan so we preserve them here. As with PlannedState and
// ExternalReferences, this is only used by the testing framework and so
// isn't written into any external representation of the plan.
// the plan so we preserve them here. As with ExternalReferences, this is
// only used by the testing framework and so isn't written into any external
// representation of the plan.
Overrides *mocking.Overrides

// Timestamp is the record of truth for when the plan happened.
Expand Down
14 changes: 0 additions & 14 deletions internal/terraform/context_eval_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,13 +195,6 @@ func TestContextPlanAndEval(t *testing.T) {
} else {
t.Fatalf("plan has no Changes")
}
if plan.PlannedState != nil {
if rs := plan.PlannedState.ResourceInstance(riAddr); rs == nil {
t.Errorf("planned satte does not include test_thing.a")
}
} else {
t.Fatalf("plan has no PlannedState")
}
if plan.PriorState == nil {
t.Fatalf("plan has no PriorState")
}
Expand Down Expand Up @@ -297,13 +290,6 @@ func TestContextApplyAndEval(t *testing.T) {
} else {
t.Fatalf("plan has no Changes")
}
if plan.PlannedState != nil {
if rs := plan.PlannedState.ResourceInstance(riAddr); rs == nil {
t.Errorf("planned satte does not include test_thing.a")
}
} else {
t.Fatalf("plan has no PlannedState")
}
if plan.PriorState == nil {
t.Fatalf("plan has no PriorState")
}
Expand Down
1 change: 0 additions & 1 deletion internal/terraform/context_plan.go
Original file line number Diff line number Diff line change
Expand Up @@ -759,7 +759,6 @@ func (c *Context) planWalk(config *configs.Config, prevRunState *states.State, o
DeferredResources: deferredResources,
PrevRunState: prevRunState,
PriorState: priorState,
PlannedState: walker.State.Close(),
ExternalReferences: opts.ExternalReferences,
Overrides: opts.Overrides,
Checks: states.NewCheckResults(walker.Checks),
Expand Down
62 changes: 0 additions & 62 deletions internal/terraform/context_plan2_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4579,61 +4579,6 @@ resource "test_object" "a" {
}
}

func TestContext2Plan_plannedState(t *testing.T) {
addr := mustResourceInstanceAddr("test_object.a")
m := testModuleInline(t, map[string]string{
"main.tf": `
resource "test_object" "a" {
test_string = "foo"
}

locals {
local_value = test_object.a.test_string
}

output "from_local_value" {
value = local.local_value
}
`,
})

p := simpleMockProvider()
ctx := testContext2(t, &ContextOpts{
Providers: map[addrs.Provider]providers.Factory{
addrs.NewDefaultProvider("test"): testProviderFuncFixed(p),
},
})

state := states.NewState()
plan, diags := ctx.Plan(m, state, nil)
if diags.HasErrors() {
t.Errorf("expected no errors, but got %s", diags)
}

module := state.RootModule()

// So, the original state shouldn't have been updated at all.
if len(state.RootOutputValues) > 0 {
t.Errorf("expected no root output values in the state but found %d", len(state.RootOutputValues))
}

if len(module.Resources) > 0 {
t.Errorf("expected no resources in the state but found %d", len(module.Resources))
}

// But, this makes it hard for the testing framework to valid things about
// the returned plan. So, the plan contains the planned state:
module = plan.PlannedState.RootModule()

if got, want := plan.PlannedState.RootOutputValues["from_local_value"].Value.AsString(), "foo"; got != want {
t.Errorf("expected local value to be %q but was %q", want, got)
}

if module.ResourceInstance(addr.Resource).Current.Status != states.ObjectPlanned {
t.Errorf("expected resource to be in planned state")
}
}

func TestContext2Plan_externalProviders(t *testing.T) {
// This test exercises the option for callers to pass in their own
// already-configured provider instances, instead of the modules runtime
Expand Down Expand Up @@ -5475,13 +5420,6 @@ resource "test_object" "obj" {
if len(ch.AfterSensitivePaths) == 0 {
t.Fatal("expected marked values in test_object.obj")
}

data := plan.PlannedState.RootModule().ResourceInstance(mustResourceInstanceAddr("data.test_data_source.foo").Resource)
if len(data.Current.AttrSensitivePaths) == 0 {
// we may not always store data source states in the future, but for now
// this is a good indication that the read value was correctly marked.
t.Fatal("data.test_data_source.foo schema contains a sensitive attribute, should be marked in state")
}
}

// When a schema declares that attributes nested within sets are sensitive, the
Expand Down