From 2938ec43fa0e6a09d0cf1a80778329f72fc7ca3c Mon Sep 17 00:00:00 2001 From: Brandon Croft Date: Wed, 15 Dec 2021 10:02:48 -0700 Subject: [PATCH] [cloud] handle unreachable run tasks --- internal/cloud/backend_plan.go | 3 ++- internal/cloud/backend_runTasks.go | 36 +++++++++++++------------ internal/cloud/backend_runTasks_test.go | 10 +++++++ 3 files changed, 31 insertions(+), 18 deletions(-) diff --git a/internal/cloud/backend_plan.go b/internal/cloud/backend_plan.go index 2ec1439ea..0a7975d64 100644 --- a/internal/cloud/backend_plan.go +++ b/internal/cloud/backend_plan.go @@ -351,9 +351,10 @@ in order to capture the filesystem context the remote workspace expects: } } - // Await collective run tasks + // Await pre-apply run tasks if len(r.TaskStage) > 0 { context := NewIntegrationContext(stopCtx, cancelCtx, b, op, r) + // TODO: this only works while there is exactly 1 task stage err = b.runTasks(context, context.BeginOutput("Run Tasks (pre-apply)"), r.TaskStage[0].ID) if err != nil { diff --git a/internal/cloud/backend_runTasks.go b/internal/cloud/backend_runTasks.go index 8ef8679e4..ab00a6aac 100644 --- a/internal/cloud/backend_runTasks.go +++ b/internal/cloud/backend_runTasks.go @@ -9,6 +9,7 @@ import ( ) type taskResultSummary struct { + unreachable bool pending int failed int failedMandatory int @@ -17,10 +18,14 @@ type taskResultSummary struct { type taskStageReadFunc func(b *Cloud, stopCtx context.Context) (*tfe.TaskStage, error) -func summarizeTaskResults(taskResults []*tfe.TaskResult) taskResultSummary { +func summarizeTaskResults(taskResults []*tfe.TaskResult) *taskResultSummary { var pe, er, erm, pa int for _, task := range taskResults { - if task.Status == "running" || task.Status == "pending" { + if task.Status == "unreachable" { + return &taskResultSummary{ + unreachable: true, + } + } else if task.Status == "running" || task.Status == "pending" { pe++ } else if task.Status == "passed" { pa++ @@ -33,7 +38,8 @@ func summarizeTaskResults(taskResults []*tfe.TaskResult) taskResultSummary { } } - return taskResultSummary{ + return &taskResultSummary{ + unreachable: false, pending: pe, failed: er, failedMandatory: erm, @@ -41,19 +47,7 @@ func summarizeTaskResults(taskResults []*tfe.TaskResult) taskResultSummary { } } -// elapsedMessageMax is 50 chars: the length of this message with 6 digits -// 99 tasks still pending, 99 passed, 99 failed ... -const elapsedMessageMax int = 50 - func (b *Cloud) runTasksWithTaskResults(context *IntegrationContext, output IntegrationOutputWriter, fetchTaskStage taskStageReadFunc) error { - // TODO: Do not fetch run tasks if there are no changes to infrastructure - // if !context.Run.HasChanges { - // output.Output("No Changes. Tasks will not run") - // output.End() - - // return nil - // } - return context.Poll(func(i int) (bool, error) { // TODO: get the stage that corresponds to an argument passed to this function stage, err := fetchTaskStage(b, context.StopContext) @@ -63,12 +57,20 @@ func (b *Cloud) runTasksWithTaskResults(context *IntegrationContext, output Inte } summary := summarizeTaskResults(stage.TaskResults) + + if summary.unreachable { + output.Output("Skipping task results.") + output.End() + return false, nil + } + if summary.pending > 0 { - message := fmt.Sprintf("%d tasks still pending, %d passed, %d failed ... ", summary.pending, summary.passed, summary.failed) + pendingMessage := "%d tasks still pending, %d passed, %d failed ... " + message := fmt.Sprintf(pendingMessage, summary.pending, summary.passed, summary.failed) if i%4 == 0 { if i > 0 { - output.OutputElapsed(message, elapsedMessageMax) + output.OutputElapsed(message, len(pendingMessage)) // Up to 2 digits are allowed by the max message allocation } } return true, nil diff --git a/internal/cloud/backend_runTasks_test.go b/internal/cloud/backend_runTasks_test.go index 9cb133cd5..d33220446 100644 --- a/internal/cloud/backend_runTasks_test.go +++ b/internal/cloud/backend_runTasks_test.go @@ -118,6 +118,16 @@ func TestCloud_runTasksWithTaskResults(t *testing.T) { expectedOutputs: []string{"Failed (Advisory)", "Overall Result: Passed with advisory failure"}, isError: false, }, + "unreachable": { + taskResults: []*tfe.TaskResult{ + {ID: "1", TaskName: "Mandatory", Message: "", Status: "unreachable", WorkspaceTaskEnforcementLevel: "mandatory"}, + {ID: "2", TaskName: "Advisory", Message: "", Status: "unreachable", WorkspaceTaskEnforcementLevel: "advisory"}, + }, + writer: writer, + context: integrationContext, + expectedOutputs: []string{"Skipping"}, + isError: false, + }, } for caseName, c := range cases {