Experimental `-allow-deferral` flag for enabling deferred actions on CLI

Now that deferred actions is a top-level per-plan option, here's a lil
command-line option for turning it on!

- It's called `-allow-deferral`.
- It is ONLY legal to use if this is an experimental build, i.e. compiled with
  `go build -ldflags "-w -s -X 'main.experimentsAllowed=yes'"` or the like.

Implementation notes: The design constraint here was, "please avoid having to
change the build infrastructure or alter the function of every args parsing
function". So, since `extendedFlagSet()` doesn't have access to the var that
says we're in an experimental build, I had to move the validation for that
particular flag to later in the process, when we're building the operation
request.
pull/34914/head
Nick Fagerlund 2 years ago
parent 4d46cc81e3
commit 1781c8e8e9

@ -124,6 +124,13 @@ type Operation struct {
// the variables set in the plan are used instead, and they must be valid.
AllowUnsetVariables bool
// DeferralAllowed enables experimental support for automatically performing
// a partial plan if some objects are not yet plannable.
//
// IMPORTANT: When configuring an Operation, you should only set a value for
// this field if Terraform was built with experimental features enabled.
DeferralAllowed bool
// View implements the logic for all UI interactions.
View views.Operation

@ -204,6 +204,7 @@ func (b *Local) localRunDirect(op *backendrun.Operation, run *backendrun.LocalRu
SetVariables: variables,
SkipRefresh: op.Type != backendrun.OperationTypeRefresh && !op.PlanRefresh,
GenerateConfigPath: op.GenerateConfigOut,
DeferralAllowed: op.DeferralAllowed,
}
run.PlanOpts = planOpts

@ -280,6 +280,20 @@ func (c *ApplyCommand) OperationRequest(
opReq.Type = backendrun.OperationTypeApply
opReq.View = view.Operation()
// EXPERIMENTAL: maybe enable deferred actions
if c.AllowExperimentalFeatures {
opReq.DeferralAllowed = args.DeferralAllowed
} else if args.DeferralAllowed {
// Belated flag parse error, since we don't know about experiments
// support at actual parse time.
diags = diags.Append(tfdiags.Sourceless(
tfdiags.Error,
"Failed to parse command-line flags",
"The -allow-deferral flag is only valid in experimental builds of Terraform.",
))
return nil, diags
}
var err error
opReq.ConfigLoader, err = c.initConfigLoader()
if err != nil {

@ -78,6 +78,18 @@ type Operation struct {
// learn a use-case for broader matching.
ForceReplace []addrs.AbsResourceInstance
// DeferralAllowed enables experimental support for automatically performing
// a partial plan if some objects are not yet plannable (due to unknown
// values in count/for_each, or due to other missing dependencies that can't
// be resolved in a single plan/apply cycle).
//
// IMPORTANT: This feature should only be available when Terraform is built
// with experimental features enabled. Since extendedFlagSet can't currently
// test whether experimental features are enabled, the check needs to happen
// when _reading_ these Operation arguments and transferring values to the
// backendrun.Operation struct.
DeferralAllowed bool
// These private fields are used only temporarily during decoding. Use
// method Parse to populate the exported fields from these, validating
// the raw values in the process.
@ -223,6 +235,7 @@ func extendedFlagSet(name string, state *State, operation *Operation, vars *Vars
if operation != nil {
f.IntVar(&operation.Parallelism, "parallelism", DefaultParallelism, "parallelism")
f.BoolVar(&operation.DeferralAllowed, "allow-deferral", false, "allow-deferral")
f.BoolVar(&operation.Refresh, "refresh", true, "refresh")
f.BoolVar(&operation.destroyRaw, "destroy", false, "destroy")
f.BoolVar(&operation.refreshOnlyRaw, "refresh-only", false, "refresh-only")

@ -165,6 +165,20 @@ func (c *PlanCommand) OperationRequest(
opReq.Type = backendrun.OperationTypePlan
opReq.View = view.Operation()
// EXPERIMENTAL: maybe enable deferred actions
if c.AllowExperimentalFeatures {
opReq.DeferralAllowed = args.DeferralAllowed
} else if args.DeferralAllowed {
// Belated flag parse error, since we don't know about experiments
// support at actual parse time.
diags = diags.Append(tfdiags.Sourceless(
tfdiags.Error,
"Failed to parse command-line flags",
"The -allow-deferral flag is only valid in experimental builds of Terraform.",
))
return nil, diags
}
var err error
opReq.ConfigLoader, err = c.initConfigLoader()
if err != nil {

@ -147,6 +147,20 @@ func (c *RefreshCommand) OperationRequest(be backendrun.OperationsBackend, view
opReq.Type = backendrun.OperationTypeRefresh
opReq.View = view.Operation()
// EXPERIMENTAL: maybe enable deferred actions
if c.AllowExperimentalFeatures {
opReq.DeferralAllowed = args.DeferralAllowed
} else if args.DeferralAllowed {
// Belated flag parse error, since we don't know about experiments
// support at actual parse time.
diags = diags.Append(tfdiags.Sourceless(
tfdiags.Error,
"Failed to parse command-line flags",
"The -allow-deferral flag is only valid in experimental builds of Terraform.",
))
return nil, diags
}
var err error
opReq.ConfigLoader, err = c.initConfigLoader()
if err != nil {

Loading…
Cancel
Save