Merge pull request #31617 from glennsarti/gs/TF-410-add-prep-plan

Add Pre-Plan Run Tasks to Terraform CLI
This commit is contained in:
Brandon Croft 2022-08-18 10:14:46 -06:00 committed by GitHub
commit 76d40d281d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 43 additions and 30 deletions

View File

@ -36,6 +36,7 @@ ENHANCEMENTS:
* The COS backend now supports global acceleration. ([#31425](https://github.com/hashicorp/terraform/issues/31425))
* providercache: include host in provider installation error ([#31524](https://github.com/hashicorp/terraform/issues/31524))
* refactoring: `moved` blocks can now be used to move resources to and from external modules ([#31556](https://github.com/hashicorp/terraform/issues/31556))
* 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))
BUG FIXES:

2
go.mod
View File

@ -40,7 +40,7 @@ require (
github.com/hashicorp/go-multierror v1.1.1
github.com/hashicorp/go-plugin v1.4.3
github.com/hashicorp/go-retryablehttp v0.7.1
github.com/hashicorp/go-tfe v1.6.0
github.com/hashicorp/go-tfe v1.7.0
github.com/hashicorp/go-uuid v1.0.3
github.com/hashicorp/go-version v1.6.0
github.com/hashicorp/hcl v0.0.0-20170504190234-a4b07c25de5f

4
go.sum
View File

@ -375,8 +375,8 @@ github.com/hashicorp/go-slug v0.9.1/go.mod h1:Ib+IWBYfEfJGI1ZyXMGNbu2BU+aa3Dzu41
github.com/hashicorp/go-sockaddr v1.0.0 h1:GeH6tui99pF4NJgfnhp+L6+FfobzVW3Ah46sLo0ICXs=
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
github.com/hashicorp/go-tfe v1.6.0 h1:lRfyTVLBP1njo2wShE9FimALzVZBfOqMGNuBdsor38w=
github.com/hashicorp/go-tfe v1.6.0/go.mod h1:E8a90lC4kjU5Lc2c0D+SnWhUuyuoCIVm4Ewzv3jCD3A=
github.com/hashicorp/go-tfe v1.7.0 h1:GELRhS5dizF6giwjZBqUC/xPaSuNYB+hWRtUnf6i8K8=
github.com/hashicorp/go-tfe v1.7.0/go.mod h1:E8a90lC4kjU5Lc2c0D+SnWhUuyuoCIVm4Ewzv3jCD3A=
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=

View File

@ -199,6 +199,17 @@ func (b *Cloud) waitForRun(stopCtx, cancelCtx context.Context, op *backend.Opera
}
}
func (b *Cloud) waitTaskStage(stopCtx, cancelCtx context.Context, op *backend.Operation, r *tfe.Run, stageID string, outputTitle string) error {
integration := &IntegrationContext{
B: b,
StopContext: stopCtx,
CancelContext: cancelCtx,
Op: op,
Run: r,
}
return b.runTasks(integration, integration.BeginOutput(outputTitle), stageID)
}
func (b *Cloud) costEstimate(stopCtx, cancelCtx context.Context, op *backend.Operation, r *tfe.Run) error {
if r.CostEstimate == nil {
return nil

View File

@ -291,6 +291,28 @@ in order to capture the filesystem context the remote workspace expects:
runHeader, b.hostname, b.organization, op.Workspace, r.ID)) + "\n"))
}
// Retrieve the run to get task stages.
// Task Stages are calculated upfront so we only need to call this once for the run.
taskStages := make([]*tfe.TaskStage, 0)
result, err := b.client.Runs.ReadWithOptions(stopCtx, r.ID, &tfe.RunReadOptions{
Include: []tfe.RunIncludeOpt{tfe.RunTaskStages},
})
if err == nil {
taskStages = result.TaskStages
} else {
// This error would be expected for older versions of TFE that do not allow
// fetching task_stages.
if !strings.HasSuffix(err.Error(), "Invalid include parameter") {
return r, generalError("Failed to retrieve run", err)
}
}
if stageID := getTaskStageIDByName(taskStages, tfe.PrePlan); stageID != nil {
if err := b.waitTaskStage(stopCtx, cancelCtx, op, r, *stageID, "Pre-plan Tasks"); err != nil {
return r, err
}
}
r, err = b.waitForRun(stopCtx, cancelCtx, op, "plan", r, w)
if err != nil {
return r, err
@ -324,21 +346,10 @@ in order to capture the filesystem context the remote workspace expects:
}
// Retrieve the run to get its current status.
runID := r.ID
r, err = b.client.Runs.ReadWithOptions(stopCtx, runID, &tfe.RunReadOptions{
Include: []tfe.RunIncludeOpt{tfe.RunTaskStages},
})
if err != nil {
// This error would be expected for older versions of TFE that do not allow
// fetching task_stages.
if strings.HasSuffix(err.Error(), "Invalid include parameter") {
r, err = b.client.Runs.Read(stopCtx, runID)
}
r, err = b.client.Runs.Read(stopCtx, r.ID)
if err != nil {
return r, generalError("Failed to retrieve run", err)
}
}
// If the run is canceled or errored, we still continue to the
// cost-estimation and policy check phases to ensure we render any
@ -346,18 +357,8 @@ in order to capture the filesystem context the remote workspace expects:
// status of the run will be "errored", but there is still policy
// information which should be shown.
// Await post-plan run tasks
integration := &IntegrationContext{
B: b,
StopContext: stopCtx,
CancelContext: cancelCtx,
Op: op,
Run: r,
}
if stageID := getTaskStageIDByName(r.TaskStages, tfe.PostPlan); stageID != nil {
err = b.runTasks(integration, integration.BeginOutput("Run Tasks (post-plan)"), *stageID)
if err != nil {
if stageID := getTaskStageIDByName(taskStages, tfe.PostPlan); stageID != nil {
if err := b.waitTaskStage(stopCtx, cancelCtx, op, r, *stageID, "Post-plan Tasks"); err != nil {
return r, err
}
}

View File

@ -52,7 +52,7 @@ func (b *Cloud) runTasksWithTaskResults(context *IntegrationContext, output Inte
stage, err := fetchTaskStage(b, context.StopContext)
if err != nil {
return false, generalError("Failed to retrieve pre-apply task stage", err)
return false, generalError("Failed to retrieve task stage", err)
}
summary := summarizeTaskResults(stage.TaskResults)