refactor runTaskStage func & use multierrors lib

This commit is contained in:
mrinalirao 2023-01-16 11:10:53 +11:00
parent 4d2e75bbda
commit dcd2826277
4 changed files with 42 additions and 95 deletions

View File

@ -104,7 +104,7 @@ func (pes *policyEvaluationSummarizer) taskStageWithPolicyEvaluation(context *In
// Currently only one policy evaluation supported : OPA
for _, polEvaluation := range policyEvaluation {
if polEvaluation.Status == tfe.PolicyEvaluationPassed {
message = "[dim] This result means that all OPA policies passed and the protected behaviour is allowed"
message = "[dim] This result means that all OPA policies passed and the protected behavior is allowed"
result = fmt.Sprintf("[green]%s", strings.ToUpper(string(tfe.PolicyEvaluationPassed)))
if polEvaluation.ResultCount.AdvisoryFailed > 0 {
result += " (with advisory)"

View File

@ -30,7 +30,7 @@ func TestCloud_runTaskStageWithPolicyEvaluation(t *testing.T) {
},
writer: writer,
context: integrationContext,
expectedOutputs: []string{"│ [bold]OPA Policy Evaluation\n\n│ [bold]→→ Overall Result: [green]PASSED\n│ [dim] This result means that all OPA policies passed and the protected behaviour is allowed\n│ 1 policies evaluated\n\n│ → Policy set 1: [bold]policy-set-that-passes (1)\n│ ↳ Policy name: [bold]policy-pass\n│ | [green][bold]✓ Passed\n│ | [dim]This policy will pass\n"},
expectedOutputs: []string{"│ [bold]OPA Policy Evaluation\n\n│ [bold]→→ Overall Result: [green]PASSED\n│ [dim] This result means that all OPA policies passed and the protected behavior is allowed\n│ 1 policies evaluated\n\n│ → Policy set 1: [bold]policy-set-that-passes (1)\n│ ↳ Policy name: [bold]policy-pass\n│ | [green][bold]✓ Passed\n│ | [dim]This policy will pass\n"},
isError: false,
},
"mandatory-failed": {

View File

@ -5,6 +5,7 @@ import (
"fmt"
"strings"
"github.com/hashicorp/go-multierror"
tfe "github.com/hashicorp/go-tfe"
"github.com/hashicorp/terraform/internal/terraform"
)
@ -66,7 +67,7 @@ func (b *Cloud) getTaskStageWithAllOptions(ctx *IntegrationContext, stageID stri
}
func (b *Cloud) runTaskStage(ctx *IntegrationContext, output IntegrationOutputWriter, stageID string) error {
var errs multiErrors
var errs *multierror.Error
// Create our summarizers
summarizers := make([]taskStageSummarizer, 0)
@ -98,60 +99,33 @@ func (b *Cloud) runTaskStage(ctx *IntegrationContext, output IntegrationOutputWr
return true, nil
// Note: Terminal statuses need to print out one last time just in case
case tfe.TaskStageRunning, tfe.TaskStagePassed:
for _, s := range summarizers {
cont, msg, err := s.Summarize(ctx, output, stage)
if err != nil {
errs.Append(err)
break
}
if !cont {
continue
}
// cont is true and we must continue to poll
if msg != nil {
output.OutputElapsed(*msg, len(*msg)) // Up to 2 digits are allowed by the max message allocation
}
ok, e := processSummarizers(ctx, output, stage, summarizers, errs)
if e != nil {
errs = e
}
if ok {
return true, nil
}
case tfe.TaskStageCanceled, tfe.TaskStageErrored, tfe.TaskStageFailed:
for _, s := range summarizers {
cont, msg, err := s.Summarize(ctx, output, stage)
if err != nil {
errs.Append(err)
break
}
if !cont {
continue
}
// cont is true and we must continue to poll
if msg != nil {
output.OutputElapsed(*msg, len(*msg)) // Up to 2 digits are allowed by the max message allocation
}
ok, e := processSummarizers(ctx, output, stage, summarizers, errs)
if e != nil {
errs = e
}
if ok {
return true, nil
}
return false, fmt.Errorf("Task Stage %s.", stage.Status)
case tfe.TaskStageAwaitingOverride:
for _, s := range summarizers {
cont, msg, err := s.Summarize(ctx, output, stage)
if err != nil {
errs.Append(err)
break
}
if !cont {
continue
}
// cont is true and we must continue to poll
if msg != nil {
output.OutputElapsed(*msg, len(*msg)) // Up to 2 digits are allowed by the max message allocation
}
ok, e := processSummarizers(ctx, output, stage, summarizers, errs)
if e != nil {
errs = e
}
if ok {
return true, nil
}
cont, err := b.processStageOverrides(ctx, output, stage.ID)
if err != nil {
errs.Append(err)
errs = multierror.Append(errs, err)
} else {
return cont, nil
}
@ -160,14 +134,31 @@ func (b *Cloud) runTaskStage(ctx *IntegrationContext, output IntegrationOutputWr
default:
return false, fmt.Errorf("Invalid Task stage status: %s ", stage.Status)
}
if len(errs) > 0 {
return false, errs.Err()
}
return false, nil
return false, errs.ErrorOrNil()
})
}
func processSummarizers(ctx *IntegrationContext, output IntegrationOutputWriter, stage *tfe.TaskStage, summarizers []taskStageSummarizer, errs *multierror.Error) (bool, *multierror.Error) {
for _, s := range summarizers {
cont, msg, err := s.Summarize(ctx, output, stage)
if err != nil {
errs = multierror.Append(errs, err)
break
}
if !cont {
continue
}
// cont is true and we must continue to poll
if msg != nil {
output.OutputElapsed(*msg, len(*msg)) // Up to 2 digits are allowed by the max message allocation
}
return true, nil
}
return false, errs
}
func (b *Cloud) processStageOverrides(context *IntegrationContext, output IntegrationOutputWriter, taskStageID string) (bool, error) {
opts := &terraform.InputOpts{
Id: fmt.Sprintf("%c%c [bold]Override", Arrow, Arrow),

View File

@ -58,47 +58,3 @@ func incompatibleWorkspaceTerraformVersion(message string, ignoreVersionConflict
description := strings.TrimSpace(fmt.Sprintf("%s\n\n%s", message, suggestion))
return tfdiags.Sourceless(severity, "Incompatible Terraform version", description)
}
type multiErrors []error
// Append errs to e only if the individual error in errs is not nil
//
// If any of the errs is itself multiErrors, each individual error in errs is appended.
func (e *multiErrors) Append(errs ...error) {
for _, err := range errs {
if err == nil {
continue
}
if errs, ok := err.(multiErrors); ok {
*e = append(*e, errs...)
} else {
*e = append(*e, err)
}
}
}
// multiErrors returns an error string by joining
// all of its nonnil errors with colon separator.
func (e multiErrors) Error() string {
if len(e) == 0 {
return ""
}
es := make([]string, 0, len(e))
for _, err := range e {
if err != nil {
es = append(es, err.Error())
}
}
return strings.Join(es, ":")
}
// Err returns e as an error or returns nil if no errors were collected.
func (e multiErrors) Err() error {
// Only return self if we have at least one nonnil error.
for _, err := range e {
if err != nil {
return e
}
}
return nil
}