Skip to content

Commit 76d40d2

Browse files
authored
Merge pull request #31617 from glennsarti/gs/TF-410-add-prep-plan
Add Pre-Plan Run Tasks to Terraform CLI
2 parents 9c9af81 + 8562f8a commit 76d40d2

File tree

6 files changed

+43
-30
lines changed

6 files changed

+43
-30
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ ENHANCEMENTS:
3636
* The COS backend now supports global acceleration. ([#31425](https://github.com/hashicorp/terraform/issues/31425))
3737
* providercache: include host in provider installation error ([#31524](https://github.com/hashicorp/terraform/issues/31524))
3838
* refactoring: `moved` blocks can now be used to move resources to and from external modules ([#31556](https://github.com/hashicorp/terraform/issues/31556))
39+
* When showing the progress of a remote operation running in Terraform Cloud, Terraform CLI will include information about pre-plan run tasks ([#31617](https://github.com/hashicorp/terraform/issues/31617))
3940
4041
BUG FIXES:
4142
@@ -54,7 +55,7 @@ EXPERIMENTS:
5455
* The built-in `defaults` function, previously used to meet the use-case of replacing null values with default values, will not graduate to stable and has been removed. Use the second argument of `optional` inline in your type constraint to declare default values instead.
5556
5657
If you have any experimental modules that were participating in this experiment, you will need to remove the experiment opt-in and adopt the new syntax for declaring default values in order to migrate your existing module to the stablized version of this feature. If you are writing a shared module for others to use, we recommend declaring that your module requires Terraform v1.3.0 or later to give specific feedback when using the new feature on older Terraform versions, in place of the previous declaration to use the experimental form of this feature:
57-
58+
5859
```hcl
5960
terraform {
6061
required_version = ">= 1.3.0"

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ require (
4040
github.com/hashicorp/go-multierror v1.1.1
4141
github.com/hashicorp/go-plugin v1.4.3
4242
github.com/hashicorp/go-retryablehttp v0.7.1
43-
github.com/hashicorp/go-tfe v1.6.0
43+
github.com/hashicorp/go-tfe v1.7.0
4444
github.com/hashicorp/go-uuid v1.0.3
4545
github.com/hashicorp/go-version v1.6.0
4646
github.com/hashicorp/hcl v0.0.0-20170504190234-a4b07c25de5f

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -375,8 +375,8 @@ github.com/hashicorp/go-slug v0.9.1/go.mod h1:Ib+IWBYfEfJGI1ZyXMGNbu2BU+aa3Dzu41
375375
github.com/hashicorp/go-sockaddr v1.0.0 h1:GeH6tui99pF4NJgfnhp+L6+FfobzVW3Ah46sLo0ICXs=
376376
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
377377
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
378-
github.com/hashicorp/go-tfe v1.6.0 h1:lRfyTVLBP1njo2wShE9FimALzVZBfOqMGNuBdsor38w=
379-
github.com/hashicorp/go-tfe v1.6.0/go.mod h1:E8a90lC4kjU5Lc2c0D+SnWhUuyuoCIVm4Ewzv3jCD3A=
378+
github.com/hashicorp/go-tfe v1.7.0 h1:GELRhS5dizF6giwjZBqUC/xPaSuNYB+hWRtUnf6i8K8=
379+
github.com/hashicorp/go-tfe v1.7.0/go.mod h1:E8a90lC4kjU5Lc2c0D+SnWhUuyuoCIVm4Ewzv3jCD3A=
380380
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
381381
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
382382
github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=

internal/cloud/backend_common.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,17 @@ func (b *Cloud) waitForRun(stopCtx, cancelCtx context.Context, op *backend.Opera
199199
}
200200
}
201201

202+
func (b *Cloud) waitTaskStage(stopCtx, cancelCtx context.Context, op *backend.Operation, r *tfe.Run, stageID string, outputTitle string) error {
203+
integration := &IntegrationContext{
204+
B: b,
205+
StopContext: stopCtx,
206+
CancelContext: cancelCtx,
207+
Op: op,
208+
Run: r,
209+
}
210+
return b.runTasks(integration, integration.BeginOutput(outputTitle), stageID)
211+
}
212+
202213
func (b *Cloud) costEstimate(stopCtx, cancelCtx context.Context, op *backend.Operation, r *tfe.Run) error {
203214
if r.CostEstimate == nil {
204215
return nil

internal/cloud/backend_plan.go

Lines changed: 26 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,28 @@ in order to capture the filesystem context the remote workspace expects:
291291
runHeader, b.hostname, b.organization, op.Workspace, r.ID)) + "\n"))
292292
}
293293

294+
// Retrieve the run to get task stages.
295+
// Task Stages are calculated upfront so we only need to call this once for the run.
296+
taskStages := make([]*tfe.TaskStage, 0)
297+
result, err := b.client.Runs.ReadWithOptions(stopCtx, r.ID, &tfe.RunReadOptions{
298+
Include: []tfe.RunIncludeOpt{tfe.RunTaskStages},
299+
})
300+
if err == nil {
301+
taskStages = result.TaskStages
302+
} else {
303+
// This error would be expected for older versions of TFE that do not allow
304+
// fetching task_stages.
305+
if !strings.HasSuffix(err.Error(), "Invalid include parameter") {
306+
return r, generalError("Failed to retrieve run", err)
307+
}
308+
}
309+
310+
if stageID := getTaskStageIDByName(taskStages, tfe.PrePlan); stageID != nil {
311+
if err := b.waitTaskStage(stopCtx, cancelCtx, op, r, *stageID, "Pre-plan Tasks"); err != nil {
312+
return r, err
313+
}
314+
}
315+
294316
r, err = b.waitForRun(stopCtx, cancelCtx, op, "plan", r, w)
295317
if err != nil {
296318
return r, err
@@ -324,20 +346,9 @@ in order to capture the filesystem context the remote workspace expects:
324346
}
325347

326348
// Retrieve the run to get its current status.
327-
runID := r.ID
328-
r, err = b.client.Runs.ReadWithOptions(stopCtx, runID, &tfe.RunReadOptions{
329-
Include: []tfe.RunIncludeOpt{tfe.RunTaskStages},
330-
})
349+
r, err = b.client.Runs.Read(stopCtx, r.ID)
331350
if err != nil {
332-
// This error would be expected for older versions of TFE that do not allow
333-
// fetching task_stages.
334-
if strings.HasSuffix(err.Error(), "Invalid include parameter") {
335-
r, err = b.client.Runs.Read(stopCtx, runID)
336-
}
337-
338-
if err != nil {
339-
return r, generalError("Failed to retrieve run", err)
340-
}
351+
return r, generalError("Failed to retrieve run", err)
341352
}
342353

343354
// If the run is canceled or errored, we still continue to the
@@ -346,18 +357,8 @@ in order to capture the filesystem context the remote workspace expects:
346357
// status of the run will be "errored", but there is still policy
347358
// information which should be shown.
348359

349-
// Await post-plan run tasks
350-
integration := &IntegrationContext{
351-
B: b,
352-
StopContext: stopCtx,
353-
CancelContext: cancelCtx,
354-
Op: op,
355-
Run: r,
356-
}
357-
358-
if stageID := getTaskStageIDByName(r.TaskStages, tfe.PostPlan); stageID != nil {
359-
err = b.runTasks(integration, integration.BeginOutput("Run Tasks (post-plan)"), *stageID)
360-
if err != nil {
360+
if stageID := getTaskStageIDByName(taskStages, tfe.PostPlan); stageID != nil {
361+
if err := b.waitTaskStage(stopCtx, cancelCtx, op, r, *stageID, "Post-plan Tasks"); err != nil {
361362
return r, err
362363
}
363364
}

internal/cloud/backend_runTasks.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ func (b *Cloud) runTasksWithTaskResults(context *IntegrationContext, output Inte
5252
stage, err := fetchTaskStage(b, context.StopContext)
5353

5454
if err != nil {
55-
return false, generalError("Failed to retrieve pre-apply task stage", err)
55+
return false, generalError("Failed to retrieve task stage", err)
5656
}
5757

5858
summary := summarizeTaskResults(stage.TaskResults)

0 commit comments

Comments
 (0)