Skip to content

Commit c5445d4

Browse files
author
Liam Cervante
authored
stacks: move the RPCAPI and deferred actions out of experimental (#37067)
* stacks: move the RPCAPI and deferred actions out of experimental * add PR number
1 parent b6be635 commit c5445d4

File tree

8 files changed

+26
-61
lines changed

8 files changed

+26
-61
lines changed

.changes/footer-with-experiments.md

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,3 @@
1-
EXPERIMENTS:
2-
3-
Experiments are only enabled in alpha releases of Terraform CLI. The following features are not yet available in stable releases.
4-
5-
- The new command `terraform rpcapi` exposes some Terraform Core functionality through an RPC interface compatible with [`go-plugin`](https://github.com/hashicorp/go-plugin). The exact RPC API exposed here is currently subject to change at any time, because it's here primarily as a vehicle to support the [Terraform Stacks](https://www.hashicorp.com/blog/terraform-stacks-explained) private preview and so will be broken if necessary to respond to feedback from private preview participants, or possibly for other reasons. Do not use this mechanism yet outside of Terraform Stacks private preview.
6-
- The experimental "deferred actions" feature, enabled by passing the `-allow-deferral` option to `terraform plan`, permits `count` and `for_each` arguments in `module`, `resource`, and `data` blocks to have unknown values and allows providers to react more flexibly to unknown values. This experiment is under active development, and so it's not yet useful to participate in this experiment
71

82
## Previous Releases
93

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
kind: NEW FEATURES
2+
body: 'Deferred actions: The `plan`, `apply`, and `refresh` commands now support the `-allow-deferral` flag. The flag enables Terraform and Terraform Providers to defer changes with unresolvable unknown values to future plans instead of failing the entire plan.'
3+
time: 2025-05-15T15:19:04.603403+02:00
4+
custom:
5+
Issue: "37067"
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
kind: NOTES
2+
body: The command `terraform rpcapi` is now generally available. It is not intended for public consumption, but exposes certain Terraform operations through an RPC interface compatible with [go-plugin](https://github.com/hashicorp/go-plugin).
3+
time: 2025-05-15T15:19:22.219798+02:00
4+
custom:
5+
Issue: "37067"

commands.go

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,17 @@ func initCommands(
282282
}, nil
283283
},
284284

285+
// "rpcapi" is handled a bit differently because the whole point of
286+
// this interface is to bypass the CLI layer so wrapping automation can
287+
// get as-direct-as-possible access to Terraform Core functionality,
288+
// without interference from behaviors that are intended for CLI
289+
// end-user convenience. We bypass the "command" package entirely
290+
// for this command in particular.
291+
"rpcapi": rpcapi.CLICommandFactory(rpcapi.CommandFactoryOpts{
292+
ExperimentsAllowed: meta.AllowExperimentalFeatures,
293+
ShutdownCh: meta.ShutdownCh,
294+
}),
295+
285296
"show": func() (cli.Command, error) {
286297
return &command.ShowCommand{
287298
Meta: meta,
@@ -439,17 +450,6 @@ func initCommands(
439450
Meta: meta,
440451
}, nil
441452
}
442-
443-
// "rpcapi" is handled a bit differently because the whole point of
444-
// this interface is to bypass the CLI layer so wrapping automation can
445-
// get as-direct-as-possible access to Terraform Core functionality,
446-
// without interference from behaviors that are intended for CLI
447-
// end-user convenience. We bypass the "command" package entirely
448-
// for this command in particular.
449-
Commands["rpcapi"] = rpcapi.CLICommandFactory(rpcapi.CommandFactoryOpts{
450-
ExperimentsAllowed: meta.AllowExperimentalFeatures,
451-
ShutdownCh: meta.ShutdownCh,
452-
})
453453
}
454454

455455
PrimaryCommands = []string{

internal/command/apply.go

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -274,20 +274,7 @@ func (c *ApplyCommand) OperationRequest(
274274
opReq.Type = backendrun.OperationTypeApply
275275
opReq.View = view.Operation()
276276
opReq.StatePersistInterval = c.Meta.StatePersistInterval()
277-
278-
// EXPERIMENTAL: maybe enable deferred actions
279-
if c.AllowExperimentalFeatures {
280-
opReq.DeferralAllowed = args.DeferralAllowed
281-
} else if args.DeferralAllowed {
282-
// Belated flag parse error, since we don't know about experiments
283-
// support at actual parse time.
284-
diags = diags.Append(tfdiags.Sourceless(
285-
tfdiags.Error,
286-
"Failed to parse command-line flags",
287-
"The -allow-deferral flag is only valid in experimental builds of Terraform.",
288-
))
289-
return nil, diags
290-
}
277+
opReq.DeferralAllowed = args.DeferralAllowed
291278

292279
var err error
293280
opReq.ConfigLoader, err = c.initConfigLoader()

internal/command/plan.go

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -164,20 +164,7 @@ func (c *PlanCommand) OperationRequest(
164164
opReq.ForceReplace = args.ForceReplace
165165
opReq.Type = backendrun.OperationTypePlan
166166
opReq.View = view.Operation()
167-
168-
// EXPERIMENTAL: maybe enable deferred actions
169-
if c.AllowExperimentalFeatures {
170-
opReq.DeferralAllowed = args.DeferralAllowed
171-
} else if args.DeferralAllowed {
172-
// Belated flag parse error, since we don't know about experiments
173-
// support at actual parse time.
174-
diags = diags.Append(tfdiags.Sourceless(
175-
tfdiags.Error,
176-
"Failed to parse command-line flags",
177-
"The -allow-deferral flag is only valid in experimental builds of Terraform.",
178-
))
179-
return nil, diags
180-
}
167+
opReq.DeferralAllowed = args.DeferralAllowed
181168

182169
var err error
183170
opReq.ConfigLoader, err = c.initConfigLoader()

internal/command/refresh.go

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -146,20 +146,7 @@ func (c *RefreshCommand) OperationRequest(be backendrun.OperationsBackend, view
146146
opReq.Targets = args.Targets
147147
opReq.Type = backendrun.OperationTypeRefresh
148148
opReq.View = view.Operation()
149-
150-
// EXPERIMENTAL: maybe enable deferred actions
151-
if c.AllowExperimentalFeatures {
152-
opReq.DeferralAllowed = args.DeferralAllowed
153-
} else if args.DeferralAllowed {
154-
// Belated flag parse error, since we don't know about experiments
155-
// support at actual parse time.
156-
diags = diags.Append(tfdiags.Sourceless(
157-
tfdiags.Error,
158-
"Failed to parse command-line flags",
159-
"The -allow-deferral flag is only valid in experimental builds of Terraform.",
160-
))
161-
return nil, diags
162-
}
149+
opReq.DeferralAllowed = args.DeferralAllowed
163150

164151
var err error
165152
opReq.ConfigLoader, err = c.initConfigLoader()

internal/terraform/eval_for_each.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -219,8 +219,8 @@ func (ev *forEachEvaluator) ensureKnownForImport(forEachVal cty.Value) tfdiags.D
219219
func (ev *forEachEvaluator) ensureKnownForResource(forEachVal cty.Value) tfdiags.Diagnostics {
220220
var diags tfdiags.Diagnostics
221221
ty := forEachVal.Type()
222-
const errInvalidUnknownDetailMap = "The \"for_each\" map includes keys derived from resource attributes that cannot be determined until apply, and so Terraform cannot determine the full set of keys that will identify the instances of this resource.\n\nWhen working with unknown values in for_each, it's better to define the map keys statically in your configuration and place apply-time results only in the map values.\n\nAlternatively, you could use the -target planning option to first apply only the resources that the for_each value depends on, and then apply a second time to fully converge."
223-
const errInvalidUnknownDetailSet = "The \"for_each\" set includes values derived from resource attributes that cannot be determined until apply, and so Terraform cannot determine the full set of keys that will identify the instances of this resource.\n\nWhen working with unknown values in for_each, it's better to use a map value where the keys are defined statically in your configuration and where only the values contain apply-time results.\n\nAlternatively, you could use the -target planning option to first apply only the resources that the for_each value depends on, and then apply a second time to fully converge."
222+
const errInvalidUnknownDetailMap = "The \"for_each\" map includes keys derived from resource attributes that cannot be determined until apply, and so Terraform cannot determine the full set of keys that will identify the instances of this resource.\n\nWhen working with unknown values in for_each, it's better to define the map keys statically in your configuration and place apply-time results only in the map values.\n\nAlternatively, you could either use the -target planning option or the -allow-deferrals planning option to first apply only the resources that the for_each value depends on, and then apply a second time to fully converge."
223+
const errInvalidUnknownDetailSet = "The \"for_each\" set includes values derived from resource attributes that cannot be determined until apply, and so Terraform cannot determine the full set of keys that will identify the instances of this resource.\n\nWhen working with unknown values in for_each, it's better to use a map value where the keys are defined statically in your configuration and where only the values contain apply-time results.\n\nAlternatively, you could either use the -target planning option or the -allow-deferrals planning option to first apply only the resources that the for_each value depends on, and then apply a second time to fully converge."
224224

225225
if !forEachVal.IsKnown() {
226226
var detailMsg string

0 commit comments

Comments
 (0)