core: Generalize the idea of a "plan mode", vs just destroy flag

Previously there were only two planning modes: normal mode and destroy
mode. In that context it made sense for these to be distinguished only by
a boolean flag.

We're now getting ready to add our third mode, "refresh only". This
establishes the idea that planning can be done in one of a number of
mutually-exclusive "modes", which are related to but separate from the
various other options that serve as modifiers for the plan operation.

This commit only introduces the new plans.Mode type and replaces the
existing "destroy" flag with a variable of that type. This doesn't cause
any change in effective behavior because Terraform Core still supports
only NormalMode and DestroyMode, with NewContext rejecting an attempt to
create a RefreshMode context for now.

It is in retrospect a little odd that the "destroy" flag was part of
ContextOpts rather than just an argument to the Plan method, but
refactoring that would be too invasive a change for right now so we'll
leave this as a field of the context for now and save revisiting that for
another day.
This commit is contained in:
Martin Atkins 2021-04-05 15:22:30 -07:00
parent 4997b9b5bb
commit c6a7d080d9
11 changed files with 230 additions and 131 deletions

View File

@ -10,6 +10,7 @@ import (
"github.com/hashicorp/terraform/backend" "github.com/hashicorp/terraform/backend"
"github.com/hashicorp/terraform/configs" "github.com/hashicorp/terraform/configs"
"github.com/hashicorp/terraform/configs/configload" "github.com/hashicorp/terraform/configs/configload"
"github.com/hashicorp/terraform/plans"
"github.com/hashicorp/terraform/plans/planfile" "github.com/hashicorp/terraform/plans/planfile"
"github.com/hashicorp/terraform/states/statemgr" "github.com/hashicorp/terraform/states/statemgr"
"github.com/hashicorp/terraform/terraform" "github.com/hashicorp/terraform/terraform"
@ -65,7 +66,12 @@ func (b *Local) context(op *backend.Operation) (*terraform.Context, *configload.
} }
// Copy set options from the operation // Copy set options from the operation
opts.Destroy = op.Destroy switch {
case op.Destroy:
opts.PlanMode = plans.DestroyMode
default:
opts.PlanMode = plans.NormalMode
}
opts.Targets = op.Targets opts.Targets = op.Targets
opts.UIInput = op.UIIn opts.UIInput = op.UIIn
opts.Hooks = op.Hooks opts.Hooks = op.Hooks

View File

@ -12,6 +12,7 @@ import (
"github.com/hashicorp/hcl/v2/hclsyntax" "github.com/hashicorp/hcl/v2/hclsyntax"
"github.com/hashicorp/terraform/backend" "github.com/hashicorp/terraform/backend"
"github.com/hashicorp/terraform/configs" "github.com/hashicorp/terraform/configs"
"github.com/hashicorp/terraform/plans"
"github.com/hashicorp/terraform/states/statemgr" "github.com/hashicorp/terraform/states/statemgr"
"github.com/hashicorp/terraform/terraform" "github.com/hashicorp/terraform/terraform"
"github.com/hashicorp/terraform/tfdiags" "github.com/hashicorp/terraform/tfdiags"
@ -61,7 +62,12 @@ func (b *Remote) Context(op *backend.Operation) (*terraform.Context, statemgr.Fu
} }
// Copy set options from the operation // Copy set options from the operation
opts.Destroy = op.Destroy switch {
case op.Destroy:
opts.PlanMode = plans.DestroyMode
default:
opts.PlanMode = plans.NormalMode
}
opts.Targets = op.Targets opts.Targets = op.Targets
opts.UIInput = op.UIIn opts.UIInput = op.UIIn

View File

@ -501,6 +501,11 @@ func (c *TestCommand) testSuiteContext(suiteDirs testCommandSuiteDirs, providerF
changes = plan.Changes changes = plan.Changes
} }
planMode := plans.NormalMode
if destroy {
planMode = plans.DestroyMode
}
return terraform.NewContext(&terraform.ContextOpts{ return terraform.NewContext(&terraform.ContextOpts{
Config: suiteDirs.Config, Config: suiteDirs.Config,
Providers: providerFactories, Providers: providerFactories,
@ -515,9 +520,9 @@ func (c *TestCommand) testSuiteContext(suiteDirs testCommandSuiteDirs, providerF
Env: "test_" + suiteDirs.SuiteName, Env: "test_" + suiteDirs.SuiteName,
}, },
State: state, State: state,
Changes: changes, Changes: changes,
Destroy: destroy, PlanMode: planMode,
}) })
} }

31
plans/mode.go Normal file
View File

@ -0,0 +1,31 @@
package plans
// Mode represents the various mutually-exclusive modes for creating a plan.
type Mode rune
//go:generate go run golang.org/x/tools/cmd/stringer -type Mode
const (
// NormalMode is the default planning mode, which aims to synchronize the
// prior state with remote objects and plan a set of actions intended to
// make those remote objects better match the current configuration.
NormalMode Mode = 0
// DestroyMode is a special planning mode for situations where the goal
// is to destroy all remote objects that are bound to instances in the
// prior state, even if the configuration for those instances is still
// present.
//
// This mode corresponds with the "-destroy" option to "terraform plan",
// and with the plan created by the "terraform destroy" command.
DestroyMode Mode = 'D'
// RefreshOnlyMode is a special planning mode which only performs the
// synchronization of prior state with remote objects, and skips any
// effort to generate any change actions for resource instances even if
// the configuration has changed relative to the state.
//
// This mode corresponds with the "-refresh-only" option to
// "terraform plan".
RefreshOnlyMode Mode = 'R'
)

33
plans/mode_string.go Normal file
View File

@ -0,0 +1,33 @@
// Code generated by "stringer -type Mode"; DO NOT EDIT.
package plans
import "strconv"
func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
var x [1]struct{}
_ = x[NormalMode-0]
_ = x[DestroyMode-68]
_ = x[RefreshOnlyMode-82]
}
const (
_Mode_name_0 = "NormalMode"
_Mode_name_1 = "DestroyMode"
_Mode_name_2 = "RefreshOnlyMode"
)
func (i Mode) String() string {
switch {
case i == 0:
return _Mode_name_0
case i == 68:
return _Mode_name_1
case i == 82:
return _Mode_name_2
default:
return "Mode(" + strconv.FormatInt(int64(i), 10) + ")"
}
}

View File

@ -46,7 +46,7 @@ type ContextOpts struct {
Targets []addrs.Targetable Targets []addrs.Targetable
Variables InputValues Variables InputValues
Meta *ContextMeta Meta *ContextMeta
Destroy bool PlanMode plans.Mode
SkipRefresh bool SkipRefresh bool
Hooks []Hook Hooks []Hook
@ -102,7 +102,7 @@ type Context struct {
targets []addrs.Targetable targets []addrs.Targetable
variables InputValues variables InputValues
meta *ContextMeta meta *ContextMeta
destroy bool planMode plans.Mode
hooks []Hook hooks []Hook
components contextComponentFactory components contextComponentFactory
@ -253,6 +253,20 @@ func NewContext(opts *ContextOpts) (*Context, tfdiags.Diagnostics) {
} }
} }
switch opts.PlanMode {
case plans.NormalMode, plans.DestroyMode:
// OK
default:
// The CLI layer (and other similar callers) should not try to
// create a context for a mode that Terraform Core doesn't support.
diags = diags.Append(tfdiags.Sourceless(
tfdiags.Error,
"Unsupported plan mode",
fmt.Sprintf("Terraform Core doesn't know how to handle plan mode %s. This is a bug in Terraform.", opts.PlanMode),
))
return nil, diags
}
log.Printf("[TRACE] terraform.NewContext: complete") log.Printf("[TRACE] terraform.NewContext: complete")
// By the time we get here, we should have values defined for all of // By the time we get here, we should have values defined for all of
@ -270,7 +284,7 @@ func NewContext(opts *ContextOpts) (*Context, tfdiags.Diagnostics) {
return &Context{ return &Context{
components: components, components: components,
schemas: schemas, schemas: schemas,
destroy: opts.Destroy, planMode: opts.PlanMode,
changes: changes, changes: changes,
hooks: hooks, hooks: hooks,
meta: opts.Meta, meta: opts.Meta,
@ -461,7 +475,7 @@ func (c *Context) Apply() (*states.State, tfdiags.Diagnostics) {
// Determine the operation // Determine the operation
operation := walkApply operation := walkApply
if c.destroy { if c.planMode == plans.DestroyMode {
operation = walkDestroy operation = walkDestroy
} }
@ -470,7 +484,7 @@ func (c *Context) Apply() (*states.State, tfdiags.Diagnostics) {
diags = diags.Append(walker.NonFatalDiagnostics) diags = diags.Append(walker.NonFatalDiagnostics)
diags = diags.Append(walkDiags) diags = diags.Append(walkDiags)
if c.destroy && !diags.HasErrors() { if c.planMode == plans.DestroyMode && !diags.HasErrors() {
// If we know we were trying to destroy objects anyway, and we // If we know we were trying to destroy objects anyway, and we
// completed without any errors, then we'll also prune out any // completed without any errors, then we'll also prune out any
// leftover empty resource husks (left after all of the instances // leftover empty resource husks (left after all of the instances
@ -532,11 +546,13 @@ The -target option is not for routine use, and is provided only for exceptional
var plan *plans.Plan var plan *plans.Plan
var planDiags tfdiags.Diagnostics var planDiags tfdiags.Diagnostics
switch { switch c.planMode {
case c.destroy: case plans.NormalMode:
plan, planDiags = c.plan()
case plans.DestroyMode:
plan, planDiags = c.destroyPlan() plan, planDiags = c.destroyPlan()
default: default:
plan, planDiags = c.plan() panic(fmt.Sprintf("unsupported plan mode %s", c.planMode))
} }
diags = diags.Append(planDiags) diags = diags.Append(planDiags)
if diags.HasErrors() { if diags.HasErrors() {

View File

@ -9,6 +9,7 @@ import (
"github.com/hashicorp/terraform/addrs" "github.com/hashicorp/terraform/addrs"
"github.com/hashicorp/terraform/configs/configschema" "github.com/hashicorp/terraform/configs/configschema"
"github.com/hashicorp/terraform/plans"
"github.com/hashicorp/terraform/providers" "github.com/hashicorp/terraform/providers"
"github.com/hashicorp/terraform/states" "github.com/hashicorp/terraform/states"
"github.com/zclconf/go-cty/cty" "github.com/zclconf/go-cty/cty"
@ -161,7 +162,7 @@ output "data" {
ctx = testContext2(t, &ContextOpts{ ctx = testContext2(t, &ContextOpts{
Config: m, Config: m,
Providers: ps, Providers: ps,
Destroy: true, PlanMode: plans.DestroyMode,
}) })
_, diags = ctx.Plan() _, diags = ctx.Plan()

View File

@ -400,8 +400,8 @@ func TestContext2Apply_resourceDependsOnModuleDestroy(t *testing.T) {
Providers: map[addrs.Provider]providers.Factory{ Providers: map[addrs.Provider]providers.Factory{
addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p), addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p),
}, },
State: globalState, State: globalState,
Destroy: true, PlanMode: plans.DestroyMode,
}) })
if _, diags := ctx.Plan(); diags.HasErrors() { if _, diags := ctx.Plan(); diags.HasErrors() {
@ -1157,8 +1157,8 @@ func TestContext2Apply_destroyComputed(t *testing.T) {
Providers: map[addrs.Provider]providers.Factory{ Providers: map[addrs.Provider]providers.Factory{
addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p), addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p),
}, },
State: state, State: state,
Destroy: true, PlanMode: plans.DestroyMode,
}) })
if p, diags := ctx.Plan(); diags.HasErrors() { if p, diags := ctx.Plan(); diags.HasErrors() {
@ -1226,7 +1226,7 @@ func testContext2Apply_destroyDependsOn(t *testing.T) {
addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p), addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p),
}, },
State: state, State: state,
Destroy: true, PlanMode: plans.DestroyMode,
Parallelism: 1, // To check ordering Parallelism: 1, // To check ordering
}) })
@ -1322,7 +1322,7 @@ func testContext2Apply_destroyDependsOnStateOnly(t *testing.T, state *states.Sta
addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p), addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p),
}, },
State: state, State: state,
Destroy: true, PlanMode: plans.DestroyMode,
Parallelism: 1, // To check ordering Parallelism: 1, // To check ordering
}) })
@ -1419,7 +1419,7 @@ func testContext2Apply_destroyDependsOnStateOnlyModule(t *testing.T, state *stat
addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p), addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p),
}, },
State: state, State: state,
Destroy: true, PlanMode: plans.DestroyMode,
Parallelism: 1, // To check ordering Parallelism: 1, // To check ordering
}) })
@ -1498,9 +1498,9 @@ func TestContext2Apply_destroyData(t *testing.T) {
Providers: map[addrs.Provider]providers.Factory{ Providers: map[addrs.Provider]providers.Factory{
addrs.NewDefaultProvider("null"): testProviderFuncFixed(p), addrs.NewDefaultProvider("null"): testProviderFuncFixed(p),
}, },
State: state, State: state,
Destroy: true, PlanMode: plans.DestroyMode,
Hooks: []Hook{hook}, Hooks: []Hook{hook},
}) })
if p, diags := ctx.Plan(); diags.HasErrors() { if p, diags := ctx.Plan(); diags.HasErrors() {
@ -1566,8 +1566,8 @@ func TestContext2Apply_destroySkipsCBD(t *testing.T) {
Providers: map[addrs.Provider]providers.Factory{ Providers: map[addrs.Provider]providers.Factory{
addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p), addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p),
}, },
State: state, State: state,
Destroy: true, PlanMode: plans.DestroyMode,
}) })
if p, diags := ctx.Plan(); diags.HasErrors() { if p, diags := ctx.Plan(); diags.HasErrors() {
@ -1600,8 +1600,8 @@ func TestContext2Apply_destroyModuleVarProviderConfig(t *testing.T) {
Providers: map[addrs.Provider]providers.Factory{ Providers: map[addrs.Provider]providers.Factory{
addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p), addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p),
}, },
State: state, State: state,
Destroy: true, PlanMode: plans.DestroyMode,
}) })
if _, diags := ctx.Plan(); diags.HasErrors() { if _, diags := ctx.Plan(); diags.HasErrors() {
@ -1687,7 +1687,7 @@ func getContextForApply_destroyCrossProviders(t *testing.T, m *configs.Config, p
Config: m, Config: m,
Providers: providerFactories, Providers: providerFactories,
State: state, State: state,
Destroy: true, PlanMode: plans.DestroyMode,
}) })
return ctx return ctx
@ -2493,8 +2493,8 @@ func TestContext2Apply_moduleDestroyOrder(t *testing.T) {
Providers: map[addrs.Provider]providers.Factory{ Providers: map[addrs.Provider]providers.Factory{
addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p), addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p),
}, },
State: state, State: state,
Destroy: true, PlanMode: plans.DestroyMode,
}) })
if _, diags := ctx.Plan(); diags.HasErrors() { if _, diags := ctx.Plan(); diags.HasErrors() {
@ -2953,8 +2953,8 @@ func TestContext2Apply_moduleProviderCloseNested(t *testing.T) {
Providers: map[addrs.Provider]providers.Factory{ Providers: map[addrs.Provider]providers.Factory{
addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p), addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p),
}, },
State: state, State: state,
Destroy: true, PlanMode: plans.DestroyMode,
}) })
if _, diags := ctx.Plan(); diags.HasErrors() { if _, diags := ctx.Plan(); diags.HasErrors() {
@ -3026,7 +3026,7 @@ func TestContext2Apply_moduleVarResourceCount(t *testing.T) {
SourceType: ValueFromCaller, SourceType: ValueFromCaller,
}, },
}, },
Destroy: true, PlanMode: plans.DestroyMode,
}) })
if _, diags := ctx.Plan(); diags.HasErrors() { if _, diags := ctx.Plan(); diags.HasErrors() {
@ -3266,9 +3266,9 @@ func TestContext2Apply_multiProviderDestroy(t *testing.T) {
p2.ApplyResourceChangeFn = applyFn p2.ApplyResourceChangeFn = applyFn
ctx := testContext2(t, &ContextOpts{ ctx := testContext2(t, &ContextOpts{
Destroy: true, PlanMode: plans.DestroyMode,
State: state, State: state,
Config: m, Config: m,
Providers: map[addrs.Provider]providers.Factory{ Providers: map[addrs.Provider]providers.Factory{
addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p), addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p),
addrs.NewDefaultProvider("vault"): testProviderFuncFixed(p2), addrs.NewDefaultProvider("vault"): testProviderFuncFixed(p2),
@ -3387,9 +3387,9 @@ func TestContext2Apply_multiProviderDestroyChild(t *testing.T) {
p2.ApplyResourceChangeFn = applyFn p2.ApplyResourceChangeFn = applyFn
ctx := testContext2(t, &ContextOpts{ ctx := testContext2(t, &ContextOpts{
Destroy: true, PlanMode: plans.DestroyMode,
State: state, State: state,
Config: m, Config: m,
Providers: map[addrs.Provider]providers.Factory{ Providers: map[addrs.Provider]providers.Factory{
addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p), addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p),
addrs.NewDefaultProvider("vault"): testProviderFuncFixed(p2), addrs.NewDefaultProvider("vault"): testProviderFuncFixed(p2),
@ -4766,9 +4766,9 @@ func TestContext2Apply_provisionerDestroy(t *testing.T) {
) )
ctx := testContext2(t, &ContextOpts{ ctx := testContext2(t, &ContextOpts{
Config: m, Config: m,
State: state, State: state,
Destroy: true, PlanMode: plans.DestroyMode,
Providers: map[addrs.Provider]providers.Factory{ Providers: map[addrs.Provider]providers.Factory{
addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p), addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p),
}, },
@ -4817,9 +4817,9 @@ func TestContext2Apply_provisionerDestroyFail(t *testing.T) {
) )
ctx := testContext2(t, &ContextOpts{ ctx := testContext2(t, &ContextOpts{
Config: m, Config: m,
State: state, State: state,
Destroy: true, PlanMode: plans.DestroyMode,
Providers: map[addrs.Provider]providers.Factory{ Providers: map[addrs.Provider]providers.Factory{
addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p), addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p),
}, },
@ -4885,9 +4885,9 @@ func TestContext2Apply_provisionerDestroyFailContinue(t *testing.T) {
) )
ctx := testContext2(t, &ContextOpts{ ctx := testContext2(t, &ContextOpts{
Config: m, Config: m,
State: state, State: state,
Destroy: true, PlanMode: plans.DestroyMode,
Providers: map[addrs.Provider]providers.Factory{ Providers: map[addrs.Provider]providers.Factory{
addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p), addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p),
}, },
@ -4954,9 +4954,9 @@ func TestContext2Apply_provisionerDestroyFailContinueFail(t *testing.T) {
) )
ctx := testContext2(t, &ContextOpts{ ctx := testContext2(t, &ContextOpts{
Config: m, Config: m,
State: state, State: state,
Destroy: true, PlanMode: plans.DestroyMode,
Providers: map[addrs.Provider]providers.Factory{ Providers: map[addrs.Provider]providers.Factory{
addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p), addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p),
}, },
@ -5324,9 +5324,9 @@ func TestContext2Apply_provisionerExplicitSelfRef(t *testing.T) {
{ {
ctx := testContext2(t, &ContextOpts{ ctx := testContext2(t, &ContextOpts{
Config: m, Config: m,
Destroy: true, PlanMode: plans.DestroyMode,
State: state, State: state,
Providers: map[addrs.Provider]providers.Factory{ Providers: map[addrs.Provider]providers.Factory{
addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p), addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p),
}, },
@ -5559,10 +5559,10 @@ func TestContext2Apply_destroyX(t *testing.T) {
// Next, plan and apply a destroy operation // Next, plan and apply a destroy operation
h.Active = true h.Active = true
ctx = testContext2(t, &ContextOpts{ ctx = testContext2(t, &ContextOpts{
Destroy: true, PlanMode: plans.DestroyMode,
State: state, State: state,
Config: m, Config: m,
Hooks: []Hook{h}, Hooks: []Hook{h},
Providers: map[addrs.Provider]providers.Factory{ Providers: map[addrs.Provider]providers.Factory{
addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p), addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p),
}, },
@ -5620,10 +5620,10 @@ func TestContext2Apply_destroyOrder(t *testing.T) {
// Next, plan and apply a destroy // Next, plan and apply a destroy
h.Active = true h.Active = true
ctx = testContext2(t, &ContextOpts{ ctx = testContext2(t, &ContextOpts{
Destroy: true, PlanMode: plans.DestroyMode,
State: state, State: state,
Config: m, Config: m,
Hooks: []Hook{h}, Hooks: []Hook{h},
Providers: map[addrs.Provider]providers.Factory{ Providers: map[addrs.Provider]providers.Factory{
addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p), addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p),
}, },
@ -5685,10 +5685,10 @@ func TestContext2Apply_destroyModulePrefix(t *testing.T) {
// Next, plan and apply a destroy operation and reset the hook // Next, plan and apply a destroy operation and reset the hook
h = new(MockHook) h = new(MockHook)
ctx = testContext2(t, &ContextOpts{ ctx = testContext2(t, &ContextOpts{
Destroy: true, PlanMode: plans.DestroyMode,
State: state, State: state,
Config: m, Config: m,
Hooks: []Hook{h}, Hooks: []Hook{h},
Providers: map[addrs.Provider]providers.Factory{ Providers: map[addrs.Provider]providers.Factory{
addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p), addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p),
}, },
@ -5826,10 +5826,10 @@ func TestContext2Apply_destroyModuleWithAttrsReferencingResource(t *testing.T) {
{ {
ctx := testContext2(t, &ContextOpts{ ctx := testContext2(t, &ContextOpts{
Destroy: true, PlanMode: plans.DestroyMode,
Config: m, Config: m,
State: state, State: state,
Hooks: []Hook{h}, Hooks: []Hook{h},
Providers: map[addrs.Provider]providers.Factory{ Providers: map[addrs.Provider]providers.Factory{
addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p), addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p),
}, },
@ -5902,10 +5902,10 @@ func TestContext2Apply_destroyWithModuleVariableAndCount(t *testing.T) {
{ {
ctx := testContext2(t, &ContextOpts{ ctx := testContext2(t, &ContextOpts{
Destroy: true, PlanMode: plans.DestroyMode,
Config: m, Config: m,
State: state, State: state,
Hooks: []Hook{h}, Hooks: []Hook{h},
Providers: map[addrs.Provider]providers.Factory{ Providers: map[addrs.Provider]providers.Factory{
addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p), addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p),
}, },
@ -5975,9 +5975,9 @@ func TestContext2Apply_destroyTargetWithModuleVariableAndCount(t *testing.T) {
{ {
ctx := testContext2(t, &ContextOpts{ ctx := testContext2(t, &ContextOpts{
Destroy: true, PlanMode: plans.DestroyMode,
Config: m, Config: m,
State: state, State: state,
Providers: map[addrs.Provider]providers.Factory{ Providers: map[addrs.Provider]providers.Factory{
addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p), addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p),
}, },
@ -6056,10 +6056,10 @@ func TestContext2Apply_destroyWithModuleVariableAndCountNested(t *testing.T) {
{ {
ctx := testContext2(t, &ContextOpts{ ctx := testContext2(t, &ContextOpts{
Destroy: true, PlanMode: plans.DestroyMode,
Config: m, Config: m,
State: state, State: state,
Hooks: []Hook{h}, Hooks: []Hook{h},
Providers: map[addrs.Provider]providers.Factory{ Providers: map[addrs.Provider]providers.Factory{
addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p), addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p),
}, },
@ -6136,9 +6136,9 @@ func TestContext2Apply_destroyOutputs(t *testing.T) {
// Next, plan and apply a destroy operation // Next, plan and apply a destroy operation
ctx = testContext2(t, &ContextOpts{ ctx = testContext2(t, &ContextOpts{
Destroy: true, PlanMode: plans.DestroyMode,
State: state, State: state,
Config: m, Config: m,
Providers: map[addrs.Provider]providers.Factory{ Providers: map[addrs.Provider]providers.Factory{
addrs.NewDefaultProvider("test"): testProviderFuncFixed(p), addrs.NewDefaultProvider("test"): testProviderFuncFixed(p),
}, },
@ -6160,9 +6160,9 @@ func TestContext2Apply_destroyOutputs(t *testing.T) {
// destroying again should produce no errors // destroying again should produce no errors
ctx = testContext2(t, &ContextOpts{ ctx = testContext2(t, &ContextOpts{
Destroy: true, PlanMode: plans.DestroyMode,
State: state, State: state,
Config: m, Config: m,
Providers: map[addrs.Provider]providers.Factory{ Providers: map[addrs.Provider]providers.Factory{
addrs.NewDefaultProvider("test"): testProviderFuncFixed(p), addrs.NewDefaultProvider("test"): testProviderFuncFixed(p),
}, },
@ -6239,8 +6239,8 @@ func TestContext2Apply_destroyTaintedProvisioner(t *testing.T) {
Provisioners: map[string]provisioners.Factory{ Provisioners: map[string]provisioners.Factory{
"shell": testProvisionerFuncFixed(pr), "shell": testProvisionerFuncFixed(pr),
}, },
State: state, State: state,
Destroy: true, PlanMode: plans.DestroyMode,
}) })
if _, diags := ctx.Plan(); diags.HasErrors() { if _, diags := ctx.Plan(); diags.HasErrors() {
@ -7178,7 +7178,7 @@ func TestContext2Apply_targetedDestroy(t *testing.T) {
addrs.ManagedResourceMode, "aws_instance", "a", addrs.ManagedResourceMode, "aws_instance", "a",
), ),
}, },
Destroy: true, PlanMode: plans.DestroyMode,
}) })
if diags := ctx.Validate(); diags.HasErrors() { if diags := ctx.Validate(); diags.HasErrors() {
@ -7257,7 +7257,7 @@ func TestContext2Apply_targetedDestroyCountDeps(t *testing.T) {
addrs.ManagedResourceMode, "aws_instance", "foo", addrs.ManagedResourceMode, "aws_instance", "foo",
), ),
}, },
Destroy: true, PlanMode: plans.DestroyMode,
}) })
if _, diags := ctx.Plan(); diags.HasErrors() { if _, diags := ctx.Plan(); diags.HasErrors() {
@ -7325,7 +7325,7 @@ func TestContext2Apply_targetedDestroyModule(t *testing.T) {
addrs.ManagedResourceMode, "aws_instance", "foo", addrs.ManagedResourceMode, "aws_instance", "foo",
), ),
}, },
Destroy: true, PlanMode: plans.DestroyMode,
}) })
if _, diags := ctx.Plan(); diags.HasErrors() { if _, diags := ctx.Plan(); diags.HasErrors() {
@ -7413,7 +7413,7 @@ func TestContext2Apply_targetedDestroyCountIndex(t *testing.T) {
addrs.ManagedResourceMode, "aws_instance", "bar", addrs.IntKey(1), addrs.ManagedResourceMode, "aws_instance", "bar", addrs.IntKey(1),
), ),
}, },
Destroy: true, PlanMode: plans.DestroyMode,
}) })
if _, diags := ctx.Plan(); diags.HasErrors() { if _, diags := ctx.Plan(); diags.HasErrors() {
@ -8481,9 +8481,9 @@ func TestContext2Apply_destroyNestedModuleWithAttrsReferencingResource(t *testin
{ {
ctx := testContext2(t, &ContextOpts{ ctx := testContext2(t, &ContextOpts{
Destroy: true, PlanMode: plans.DestroyMode,
Config: m, Config: m,
State: state, State: state,
Providers: map[addrs.Provider]providers.Factory{ Providers: map[addrs.Provider]providers.Factory{
addrs.NewDefaultProvider("null"): testProviderFuncFixed(p), addrs.NewDefaultProvider("null"): testProviderFuncFixed(p),
}, },
@ -8803,8 +8803,8 @@ func TestContext2Apply_destroyWithLocals(t *testing.T) {
Providers: map[addrs.Provider]providers.Factory{ Providers: map[addrs.Provider]providers.Factory{
addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p), addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p),
}, },
State: state, State: state,
Destroy: true, PlanMode: plans.DestroyMode,
}) })
if _, diags := ctx.Plan(); diags.HasErrors() { if _, diags := ctx.Plan(); diags.HasErrors() {
@ -8860,8 +8860,8 @@ func TestContext2Apply_providerWithLocals(t *testing.T) {
Providers: map[addrs.Provider]providers.Factory{ Providers: map[addrs.Provider]providers.Factory{
addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p), addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p),
}, },
State: state, State: state,
Destroy: true, PlanMode: plans.DestroyMode,
}) })
if _, diags := ctx.Plan(); diags.HasErrors() { if _, diags := ctx.Plan(); diags.HasErrors() {
@ -8903,8 +8903,8 @@ func TestContext2Apply_destroyWithProviders(t *testing.T) {
Providers: map[addrs.Provider]providers.Factory{ Providers: map[addrs.Provider]providers.Factory{
addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p), addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p),
}, },
State: state, State: state,
Destroy: true, PlanMode: plans.DestroyMode,
}) })
// test that we can't destroy if the provider is missing // test that we can't destroy if the provider is missing
@ -8920,8 +8920,8 @@ func TestContext2Apply_destroyWithProviders(t *testing.T) {
Providers: map[addrs.Provider]providers.Factory{ Providers: map[addrs.Provider]providers.Factory{
addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p), addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p),
}, },
State: state, State: state,
Destroy: true, PlanMode: plans.DestroyMode,
}) })
if _, diags := ctx.Plan(); diags.HasErrors() { if _, diags := ctx.Plan(); diags.HasErrors() {
@ -9124,7 +9124,7 @@ func TestContext2Apply_plannedDestroyInterpolatedCount(t *testing.T) {
Config: m, Config: m,
Providers: providers, Providers: providers,
State: state, State: state,
Destroy: true, PlanMode: plans.DestroyMode,
}) })
plan, diags := ctx.Plan() plan, diags := ctx.Plan()
@ -9608,7 +9608,7 @@ func TestContext2Apply_destroyDataCycle(t *testing.T) {
Config: m, Config: m,
Providers: Providers, Providers: Providers,
State: state, State: state,
Destroy: true, PlanMode: plans.DestroyMode,
}) })
plan, diags := ctx.Plan() plan, diags := ctx.Plan()
@ -11079,7 +11079,7 @@ output "c" {
Providers: map[addrs.Provider]providers.Factory{ Providers: map[addrs.Provider]providers.Factory{
addrs.NewDefaultProvider("test"): testProviderFuncFixed(p), addrs.NewDefaultProvider("test"): testProviderFuncFixed(p),
}, },
Destroy: true, PlanMode: plans.DestroyMode,
}) })
_, diags = ctx.Plan() _, diags = ctx.Plan()
@ -11147,8 +11147,8 @@ output "myoutput" {
Providers: map[addrs.Provider]providers.Factory{ Providers: map[addrs.Provider]providers.Factory{
addrs.NewDefaultProvider("test"): testProviderFuncFixed(p), addrs.NewDefaultProvider("test"): testProviderFuncFixed(p),
}, },
Destroy: true, PlanMode: plans.DestroyMode,
State: state, State: state,
}) })
_, diags = ctx.Plan() _, diags = ctx.Plan()
@ -11471,8 +11471,8 @@ output "output" {
addrs.NewDefaultProvider("null"): testProviderFuncFixed(nullP), addrs.NewDefaultProvider("null"): testProviderFuncFixed(nullP),
}, },
State: state, State: state,
Destroy: true, PlanMode: plans.DestroyMode,
}) })
if _, diags := ctx.Plan(); diags.HasErrors() { if _, diags := ctx.Plan(); diags.HasErrors() {
@ -11569,8 +11569,8 @@ output "outputs" {
addrs.NewDefaultProvider("test"): testProviderFuncFixed(p), addrs.NewDefaultProvider("test"): testProviderFuncFixed(p),
}, },
State: state, State: state,
Destroy: true, PlanMode: plans.DestroyMode,
}) })
if _, diags := ctx.Plan(); diags.HasErrors() { if _, diags := ctx.Plan(); diags.HasErrors() {

View File

@ -359,7 +359,7 @@ resource "test_object" "a" {
Providers: map[addrs.Provider]providers.Factory{ Providers: map[addrs.Provider]providers.Factory{
addrs.NewDefaultProvider("test"): testProviderFuncFixed(p), addrs.NewDefaultProvider("test"): testProviderFuncFixed(p),
}, },
Destroy: true, PlanMode: plans.DestroyMode,
SkipRefresh: true, SkipRefresh: true,
}) })
@ -478,7 +478,7 @@ provider "test" {
Providers: map[addrs.Provider]providers.Factory{ Providers: map[addrs.Provider]providers.Factory{
addrs.NewDefaultProvider("test"): testProviderFuncFixed(p), addrs.NewDefaultProvider("test"): testProviderFuncFixed(p),
}, },
Destroy: true, PlanMode: plans.DestroyMode,
}) })
_, diags := ctx.Plan() _, diags := ctx.Plan()

View File

@ -1616,8 +1616,8 @@ func TestContext2Plan_preventDestroy_destroyPlan(t *testing.T) {
Providers: map[addrs.Provider]providers.Factory{ Providers: map[addrs.Provider]providers.Factory{
addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p), addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p),
}, },
State: state, State: state,
Destroy: true, PlanMode: plans.DestroyMode,
}) })
plan, diags := ctx.Plan() plan, diags := ctx.Plan()
@ -3193,8 +3193,8 @@ func TestContext2Plan_destroy(t *testing.T) {
Providers: map[addrs.Provider]providers.Factory{ Providers: map[addrs.Provider]providers.Factory{
addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p), addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p),
}, },
State: state, State: state,
Destroy: true, PlanMode: plans.DestroyMode,
}) })
plan, diags := ctx.Plan() plan, diags := ctx.Plan()
@ -3256,8 +3256,8 @@ func TestContext2Plan_moduleDestroy(t *testing.T) {
Providers: map[addrs.Provider]providers.Factory{ Providers: map[addrs.Provider]providers.Factory{
addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p), addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p),
}, },
State: state, State: state,
Destroy: true, PlanMode: plans.DestroyMode,
}) })
plan, diags := ctx.Plan() plan, diags := ctx.Plan()
@ -3319,8 +3319,8 @@ func TestContext2Plan_moduleDestroyCycle(t *testing.T) {
Providers: map[addrs.Provider]providers.Factory{ Providers: map[addrs.Provider]providers.Factory{
addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p), addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p),
}, },
State: state, State: state,
Destroy: true, PlanMode: plans.DestroyMode,
}) })
plan, diags := ctx.Plan() plan, diags := ctx.Plan()
@ -3381,8 +3381,8 @@ func TestContext2Plan_moduleDestroyMultivar(t *testing.T) {
Providers: map[addrs.Provider]providers.Factory{ Providers: map[addrs.Provider]providers.Factory{
addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p), addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p),
}, },
State: state, State: state,
Destroy: true, PlanMode: plans.DestroyMode,
}) })
plan, diags := ctx.Plan() plan, diags := ctx.Plan()
@ -4152,8 +4152,8 @@ func TestContext2Plan_targetedOrphan(t *testing.T) {
Providers: map[addrs.Provider]providers.Factory{ Providers: map[addrs.Provider]providers.Factory{
addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p), addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p),
}, },
State: state, State: state,
Destroy: true, PlanMode: plans.DestroyMode,
Targets: []addrs.Targetable{ Targets: []addrs.Targetable{
addrs.RootModuleInstance.Resource( addrs.RootModuleInstance.Resource(
addrs.ManagedResourceMode, "aws_instance", "orphan", addrs.ManagedResourceMode, "aws_instance", "orphan",
@ -4219,8 +4219,8 @@ func TestContext2Plan_targetedModuleOrphan(t *testing.T) {
Providers: map[addrs.Provider]providers.Factory{ Providers: map[addrs.Provider]providers.Factory{
addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p), addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p),
}, },
State: state, State: state,
Destroy: true, PlanMode: plans.DestroyMode,
Targets: []addrs.Targetable{ Targets: []addrs.Targetable{
addrs.RootModuleInstance.Child("child", addrs.NoKey).Resource( addrs.RootModuleInstance.Child("child", addrs.NoKey).Resource(
addrs.ManagedResourceMode, "aws_instance", "orphan", addrs.ManagedResourceMode, "aws_instance", "orphan",

View File

@ -10,6 +10,7 @@ import (
"github.com/hashicorp/terraform/addrs" "github.com/hashicorp/terraform/addrs"
"github.com/hashicorp/terraform/configs/configschema" "github.com/hashicorp/terraform/configs/configschema"
"github.com/hashicorp/terraform/plans"
"github.com/hashicorp/terraform/providers" "github.com/hashicorp/terraform/providers"
"github.com/hashicorp/terraform/provisioners" "github.com/hashicorp/terraform/provisioners"
"github.com/hashicorp/terraform/states" "github.com/hashicorp/terraform/states"
@ -1056,7 +1057,7 @@ func TestContext2Validate_targetedDestroy(t *testing.T) {
addrs.ManagedResourceMode, "aws_instance", "foo", addrs.ManagedResourceMode, "aws_instance", "foo",
), ),
}, },
Destroy: true, PlanMode: plans.DestroyMode,
}) })
diags := ctx.Validate() diags := ctx.Validate()