Refactor generalError to use appName

In order to inject the value of TFP-AppName, we will need a backend.Cloud ref available
to use. This change modifies generalError as a receiver method for backend.Cloud types.
We also duplicate this method as a receiver for TestSuiteRunner, since TestSuiteRunner does
not have a backend.Cloud ref.
pull/35050/head
Sebastian Rivera 2 years ago
parent 015f795ff0
commit fb06df80fc

@ -904,7 +904,7 @@ func (b *Cloud) Operation(ctx context.Context, op *backendrun.Operation) (*backe
r, err := b.client.Runs.Read(cancelCtx, r.ID)
if err != nil {
var diags tfdiags.Diagnostics
diags = diags.Append(generalError("Failed to retrieve run", err))
diags = diags.Append(b.generalError("Failed to retrieve run", err))
op.ReportResult(runningOp, diags)
return
}
@ -915,7 +915,7 @@ func (b *Cloud) Operation(ctx context.Context, op *backendrun.Operation) (*backe
if opErr == context.Canceled {
if err := b.cancel(cancelCtx, op, r); err != nil {
var diags tfdiags.Diagnostics
diags = diags.Append(generalError("Failed to retrieve run", err))
diags = diags.Append(b.generalError("Failed to retrieve run", err))
op.ReportResult(runningOp, diags)
return
}
@ -942,7 +942,7 @@ func (b *Cloud) cancel(cancelCtx context.Context, op *backendrun.Operation, r *t
Description: "Only 'yes' will be accepted to cancel.",
})
if err != nil {
return generalError("Failed asking to cancel", err)
return b.generalError("Failed asking to cancel", err)
}
if v != "yes" {
if b.CLI != nil {
@ -960,7 +960,7 @@ func (b *Cloud) cancel(cancelCtx context.Context, op *backendrun.Operation, r *t
// Try to cancel the remote operation.
err := b.client.Runs.Cancel(cancelCtx, r.ID, tfe.RunCancelOptions{})
if err != nil {
return generalError("Failed to cancel run", err)
return b.generalError("Failed to cancel run", err)
}
if b.CLI != nil {
b.CLI.Output(b.Colorize().Color(strings.TrimSpace(operationCanceled)))
@ -1280,7 +1280,7 @@ func (wm WorkspaceMapping) tfeTags() []*tfe.Tag {
return tags
}
func generalError(msg string, err error) error {
func (b *Cloud) generalError(msg string, err error) error {
var diags tfdiags.Diagnostics
if urlErr, ok := err.(*url.Error); ok {
@ -1294,7 +1294,7 @@ func generalError(msg string, err error) error {
diags = diags.Append(tfdiags.Sourceless(
tfdiags.Error,
fmt.Sprintf("%s: %v", msg, err),
"For security, HCP Terraform and Terraform Enterprise return '404 Not Found' responses for resources\n"+
fmt.Sprintf("For security, %s returns '404 Not Found' responses for resources\n", b.appName)+
"for resources that a user doesn't have access to, in addition to resources that\n"+
"do not exist. If the resource does exist, please check the permissions of the provided token.",
))
@ -1303,7 +1303,7 @@ func generalError(msg string, err error) error {
diags = diags.Append(tfdiags.Sourceless(
tfdiags.Error,
fmt.Sprintf("%s: %v", msg, err),
`HCP Terraform or Terraform Enterprise returned an unexpected error. Sometimes `+
fmt.Sprintf(`%s returned an unexpected error. Sometimes `, b.appName)+
`this is caused by network connection problems, in which case you could retry `+
`the command. If the issue persists please open a support ticket to get help `+
`resolving the problem.`,

@ -143,7 +143,7 @@ func (b *Cloud) opApply(stopCtx, cancelCtx context.Context, op *backendrun.Opera
// Retrieve the run to get its current status.
r, err = b.client.Runs.Read(stopCtx, r.ID)
if err != nil {
return r, generalError("Failed to retrieve run", err)
return r, b.generalError("Failed to retrieve run", err)
}
// Return if the run cannot be confirmed.
@ -184,7 +184,7 @@ func (b *Cloud) opApply(stopCtx, cancelCtx context.Context, op *backendrun.Opera
// Do the apply!
if !op.AutoApprove && err != errRunApproved {
if err = b.client.Runs.Apply(stopCtx, r.ID, tfe.RunApplyOptions{}); err != nil {
return r, generalError("Failed to approve the apply command", err)
return r, b.generalError("Failed to approve the apply command", err)
}
}
@ -232,7 +232,7 @@ func (b *Cloud) renderApplyLogs(ctx context.Context, run *tfe.Run) error {
l, isPrefix, err = reader.ReadLine()
if err != nil {
if err != io.EOF {
return generalError("Failed to read logs", err)
return b.generalError("Failed to read logs", err)
}
next = false
}

@ -61,7 +61,7 @@ func (b *Cloud) waitForRun(stopCtx, cancelCtx context.Context, op *backendrun.Op
// Retrieve the run to get its current status.
r, err := b.client.Runs.Read(stopCtx, r.ID)
if err != nil {
return r, generalError("Failed to retrieve run", err)
return r, b.generalError("Failed to retrieve run", err)
}
// Return if the run is no longer pending.
@ -92,7 +92,7 @@ func (b *Cloud) waitForRun(stopCtx, cancelCtx context.Context, op *backendrun.Op
// Retrieve the workspace used to run this operation in.
w, err = b.client.Workspaces.Read(stopCtx, b.Organization, w.Name)
if err != nil {
return nil, generalError("Failed to retrieve workspace", err)
return nil, b.generalError("Failed to retrieve workspace", err)
}
// If the workspace is locked the run will not be queued and we can
@ -100,7 +100,7 @@ func (b *Cloud) waitForRun(stopCtx, cancelCtx context.Context, op *backendrun.Op
if w.Locked && w.CurrentRun != nil {
cr, err := b.client.Runs.Read(stopCtx, w.CurrentRun.ID)
if err != nil {
return r, generalError("Failed to retrieve current run", err)
return r, b.generalError("Failed to retrieve current run", err)
}
if cr.Status == tfe.RunPending {
b.CLI.Output(b.Colorize().Color(
@ -117,7 +117,7 @@ func (b *Cloud) waitForRun(stopCtx, cancelCtx context.Context, op *backendrun.Op
for {
rl, err := b.client.Runs.List(stopCtx, w.ID, options)
if err != nil {
return r, generalError("Failed to retrieve run list", err)
return r, b.generalError("Failed to retrieve run list", err)
}
// Loop through all runs to calculate the workspace queue position.
@ -172,7 +172,7 @@ func (b *Cloud) waitForRun(stopCtx, cancelCtx context.Context, op *backendrun.Op
for {
rq, err := b.client.Organizations.ReadRunQueue(stopCtx, b.Organization, options)
if err != nil {
return r, generalError("Failed to retrieve queue", err)
return r, b.generalError("Failed to retrieve queue", err)
}
// Search through all queued items to find our run.
@ -195,7 +195,7 @@ func (b *Cloud) waitForRun(stopCtx, cancelCtx context.Context, op *backendrun.Op
if position > 0 {
c, err := b.client.Organizations.ReadCapacity(stopCtx, b.Organization)
if err != nil {
return r, generalError("Failed to retrieve capacity", err)
return r, b.generalError("Failed to retrieve capacity", err)
}
b.CLI.Output(b.Colorize().Color(fmt.Sprintf(
"Waiting for %d queued run(s) to finish before starting...%s",
@ -242,7 +242,7 @@ func (b *Cloud) costEstimate(stopCtx, cancelCtx context.Context, op *backendrun.
// Retrieve the cost estimate to get its current status.
ce, err := b.client.CostEstimates.Read(stopCtx, r.CostEstimate.ID)
if err != nil {
return generalError("Failed to retrieve cost estimate", err)
return b.generalError("Failed to retrieve cost estimate", err)
}
// If the run is canceled or errored, but the cost-estimate still has
@ -263,7 +263,7 @@ func (b *Cloud) costEstimate(stopCtx, cancelCtx context.Context, op *backendrun.
case tfe.CostEstimateFinished:
delta, err := strconv.ParseFloat(ce.DeltaMonthlyCost, 64)
if err != nil {
return generalError("Unexpected error", err)
return b.generalError("Unexpected error", err)
}
sign := "+"
@ -326,14 +326,14 @@ func (b *Cloud) checkPolicy(stopCtx, cancelCtx context.Context, op *backendrun.O
// return once the policy check is complete.
logs, err := b.client.PolicyChecks.Logs(stopCtx, pc.ID)
if err != nil {
return generalError("Failed to retrieve policy check logs", err)
return b.generalError("Failed to retrieve policy check logs", err)
}
reader := bufio.NewReaderSize(logs, 64*1024)
// Retrieve the policy check to get its current status.
pc, err := b.client.PolicyChecks.Read(stopCtx, pc.ID)
if err != nil {
return generalError("Failed to retrieve policy check", err)
return b.generalError("Failed to retrieve policy check", err)
}
// If the run is canceled or errored, but the policy check still has
@ -367,7 +367,7 @@ func (b *Cloud) checkPolicy(stopCtx, cancelCtx context.Context, op *backendrun.O
l, isPrefix, err = reader.ReadLine()
if err != nil {
if err != io.EOF {
return generalError("Failed to read logs", err)
return b.generalError("Failed to read logs", err)
}
next = false
}
@ -400,7 +400,7 @@ func (b *Cloud) checkPolicy(stopCtx, cancelCtx context.Context, op *backendrun.O
if op.AutoApprove {
if _, err = b.client.PolicyChecks.Override(stopCtx, pc.ID); err != nil {
return generalError(fmt.Sprintf("Failed to override policy check.\n%s", runURL), err)
return b.generalError(fmt.Sprintf("Failed to override policy check.\n%s", runURL), err)
}
} else if !b.input {
return errPolicyOverrideNeedsUIConfirmation
@ -419,7 +419,7 @@ func (b *Cloud) checkPolicy(stopCtx, cancelCtx context.Context, op *backendrun.O
if err != errRunOverridden {
if _, err = b.client.PolicyChecks.Override(stopCtx, pc.ID); err != nil {
return generalError(fmt.Sprintf("Failed to override policy check.\n%s", runURL), err)
return b.generalError(fmt.Sprintf("Failed to override policy check.\n%s", runURL), err)
}
} else {
runURL := fmt.Sprintf(runHeader, b.Hostname, b.Organization, op.Workspace, r.ID)
@ -457,7 +457,7 @@ func (b *Cloud) confirm(stopCtx context.Context, op *backendrun.Operation, opts
// Retrieve the run again to get its current status.
r, err := b.client.Runs.Read(stopCtx, r.ID)
if err != nil {
result <- generalError("Failed to retrieve run", err)
result <- b.generalError("Failed to retrieve run", err)
return
}
@ -524,7 +524,7 @@ func (b *Cloud) confirm(stopCtx context.Context, op *backendrun.Operation, opts
// Retrieve the run again to get its current status.
r, err = b.client.Runs.Read(stopCtx, r.ID)
if err != nil {
return generalError("Failed to retrieve run", err)
return b.generalError("Failed to retrieve run", err)
}
// Make sure we discard the run if possible.
@ -532,9 +532,9 @@ func (b *Cloud) confirm(stopCtx context.Context, op *backendrun.Operation, opts
err = b.client.Runs.Discard(stopCtx, r.ID, tfe.RunDiscardOptions{})
if err != nil {
if op.PlanMode == plans.DestroyMode {
return generalError("Failed to discard destroy", err)
return b.generalError("Failed to discard destroy", err)
}
return generalError("Failed to discard apply", err)
return b.generalError("Failed to discard apply", err)
}
}

@ -139,7 +139,7 @@ func (b *Cloud) plan(stopCtx, cancelCtx context.Context, op *backendrun.Operatio
cv, err := b.client.ConfigurationVersions.Create(stopCtx, w.ID, configOptions)
if err != nil {
return nil, generalError("Failed to create configuration version", err)
return nil, b.generalError("Failed to create configuration version", err)
}
var configDir string
@ -147,7 +147,7 @@ func (b *Cloud) plan(stopCtx, cancelCtx context.Context, op *backendrun.Operatio
// De-normalize the configuration directory path.
configDir, err = filepath.Abs(op.ConfigDir)
if err != nil {
return nil, generalError(
return nil, b.generalError(
"Failed to get absolute path of the configuration directory: %v", err)
}
@ -185,21 +185,21 @@ in order to capture the filesystem context the remote workspace expects:
// be executed when we are destroying and doesn't need the config.
configDir, err = ioutil.TempDir("", "tf")
if err != nil {
return nil, generalError("Failed to create temporary directory", err)
return nil, b.generalError("Failed to create temporary directory", err)
}
defer os.RemoveAll(configDir)
// Make sure the configured working directory exists.
err = os.MkdirAll(filepath.Join(configDir, w.WorkingDirectory), 0700)
if err != nil {
return nil, generalError(
return nil, b.generalError(
"Failed to create temporary working directory", err)
}
}
err = b.client.ConfigurationVersions.Upload(stopCtx, cv.UploadURL, configDir)
if err != nil {
return nil, generalError("Failed to upload configuration files", err)
return nil, b.generalError("Failed to upload configuration files", err)
}
uploaded := false
@ -212,7 +212,7 @@ in order to capture the filesystem context the remote workspace expects:
case <-time.After(planConfigurationVersionsPollInterval):
cv, err = b.client.ConfigurationVersions.Read(stopCtx, cv.ID)
if err != nil {
return nil, generalError("Failed to retrieve configuration version", err)
return nil, b.generalError("Failed to retrieve configuration version", err)
}
if cv.Status == tfe.ConfigurationUploaded {
@ -222,7 +222,7 @@ in order to capture the filesystem context the remote workspace expects:
}
if !uploaded {
return nil, generalError(
return nil, b.generalError(
"Failed to upload configuration files", errors.New("operation timed out"))
}
@ -245,7 +245,7 @@ in order to capture the filesystem context the remote workspace expects:
// Shouldn't get here because we should update this for each new
// plan mode we add, mapping it to the corresponding RunCreateOptions
// field.
return nil, generalError(
return nil, b.generalError(
"Invalid plan mode",
fmt.Errorf("%s doesn't support %s", b.appName, op.PlanMode),
)
@ -291,7 +291,7 @@ in order to capture the filesystem context the remote workspace expects:
r, err := b.client.Runs.Create(stopCtx, runOptions)
if err != nil {
return r, generalError("Failed to create run", err)
return r, b.generalError("Failed to create run", err)
}
// When the lock timeout is set, if the run is still pending and
@ -367,7 +367,7 @@ in order to capture the filesystem context the remote workspace expects:
// Retrieve the run to get its current status.
r, err = b.client.Runs.Read(stopCtx, r.ID)
if err != nil {
return r, generalError("Failed to retrieve run", err)
return r, b.generalError("Failed to retrieve run", err)
}
// If the run is canceled or errored, we still continue to the
@ -453,7 +453,7 @@ func (b *Cloud) renderPlanLogs(ctx context.Context, op *backendrun.Operation, ru
l, isPrefix, err = reader.ReadLine()
if err != nil {
if err != io.EOF {
return generalError("Failed to read logs", err)
return b.generalError("Failed to read logs", err)
}
next = false
}
@ -523,11 +523,11 @@ func (b *Cloud) renderPlanLogs(ctx context.Context, op *backendrun.Operation, ru
if renderSRO || shouldGenerateConfig {
jsonBytes, err := readRedactedPlan(ctx, b.client.BaseURL(), b.Token, run.Plan.ID)
if err != nil {
return generalError("Failed to read JSON plan", err)
return b.generalError("Failed to read JSON plan", err)
}
redactedPlan, err = decodeRedactedPlan(jsonBytes)
if err != nil {
return generalError("Failed to decode JSON plan", err)
return b.generalError("Failed to decode JSON plan", err)
}
}

@ -51,7 +51,7 @@ func (b *Cloud) runTaskStages(ctx context.Context, client *tfe.Client, runId str
// 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 taskStages, generalError("Failed to retrieve run", err)
return taskStages, b.generalError("Failed to retrieve run", err)
}
}
@ -64,7 +64,7 @@ func (b *Cloud) getTaskStageWithAllOptions(ctx *IntegrationContext, stageID stri
}
stage, err := b.client.TaskStages.Read(ctx.StopContext, stageID, &options)
if err != nil {
return nil, generalError("Failed to retrieve task stage", err)
return nil, b.generalError("Failed to retrieve task stage", err)
} else {
return stage, nil
}
@ -94,7 +94,7 @@ func (b *Cloud) runTaskStage(ctx *IntegrationContext, output IntegrationOutputWr
}
stage, err := b.client.TaskStages.Read(ctx.StopContext, stageID, &options)
if err != nil {
return false, generalError("Failed to retrieve task stage", err)
return false, b.generalError("Failed to retrieve task stage", err)
}
switch stage.Status {
@ -198,7 +198,7 @@ func (b *Cloud) processStageOverrides(context *IntegrationContext, output Integr
if err != errRunOverridden {
if _, err = b.client.TaskStages.Override(context.StopContext, taskStageID, tfe.TaskStageOverrideOptions{}); err != nil {
return false, generalError(fmt.Sprintf("Failed to override policy check.\n%s", runURL), err)
return false, b.generalError(fmt.Sprintf("Failed to override policy check.\n%s", runURL), err)
} else {
return true, nil
}

@ -170,7 +170,7 @@ func (runner *TestSuiteRunner) Test() (moduletest.Status, tfdiags.Diagnostics) {
configurationVersion, err := client.ConfigurationVersions.CreateForRegistryModule(runner.StoppedCtx, id)
if err != nil {
diags = diags.Append(generalError("Failed to create configuration version", err))
diags = diags.Append(runner.generalError("Failed to create configuration version", err))
return moduletest.Error, diags
}
@ -179,7 +179,7 @@ func (runner *TestSuiteRunner) Test() (moduletest.Status, tfdiags.Diagnostics) {
}
if err := client.ConfigurationVersions.Upload(runner.StoppedCtx, configurationVersion.UploadURL, configDirectory); err != nil {
diags = diags.Append(generalError("Failed to upload configuration version", err))
diags = diags.Append(runner.generalError("Failed to upload configuration version", err))
return moduletest.Error, diags
}
@ -216,7 +216,7 @@ func (runner *TestSuiteRunner) Test() (moduletest.Status, tfdiags.Diagnostics) {
run, err := client.TestRuns.Create(context.Background(), opts)
if err != nil {
diags = diags.Append(generalError("Failed to create test run", err))
diags = diags.Append(runner.generalError("Failed to create test run", err))
return moduletest.Error, diags
}
@ -235,7 +235,7 @@ func (runner *TestSuiteRunner) Test() (moduletest.Status, tfdiags.Diagnostics) {
for i := 0; !completed; i++ {
run, err := client.TestRuns.Read(context.Background(), id, run.ID)
if err != nil {
diags = diags.Append(generalError("Failed to retrieve test run", err))
diags = diags.Append(runner.generalError("Failed to retrieve test run", err))
return // exit early
}
@ -277,7 +277,7 @@ func (runner *TestSuiteRunner) Test() (moduletest.Status, tfdiags.Diagnostics) {
// Refresh the run now we know it is finished.
run, err = client.TestRuns.Read(context.Background(), id, run.ID)
if err != nil {
diags = diags.Append(generalError("Failed to retrieve completed test run", err))
diags = diags.Append(runner.generalError("Failed to retrieve completed test run", err))
return moduletest.Error, diags
}
@ -483,7 +483,7 @@ func (runner *TestSuiteRunner) renderLogs(client *tfe.Client, run *tfe.TestRun,
logs, err := client.TestRuns.Logs(context.Background(), moduleId, run.ID)
if err != nil {
diags = diags.Append(generalError("Failed to retrieve logs", err))
diags = diags.Append(runner.generalError("Failed to retrieve logs", err))
return diags
}
@ -497,7 +497,7 @@ func (runner *TestSuiteRunner) renderLogs(client *tfe.Client, run *tfe.TestRun,
l, isPrefix, err = reader.ReadLine()
if err != nil {
if err != io.EOF {
diags = diags.Append(generalError("Failed to read logs", err))
diags = diags.Append(runner.generalError("Failed to read logs", err))
return diags
}
next = false
@ -601,3 +601,35 @@ func (runner *TestSuiteRunner) renderLogs(client *tfe.Client, run *tfe.TestRun,
return diags
}
func (runner *TestSuiteRunner) generalError(msg string, err error) error {
var diags tfdiags.Diagnostics
if urlErr, ok := err.(*url.Error); ok {
err = urlErr.Err
}
switch err {
case context.Canceled:
return err
case tfe.ErrResourceNotFound:
diags = diags.Append(tfdiags.Sourceless(
tfdiags.Error,
fmt.Sprintf("%s: %v", msg, err),
fmt.Sprintf("For security, %s return '404 Not Found' responses for resources\n", runner.appName)+
"for resources that a user doesn't have access to, in addition to resources that\n"+
"do not exist. If the resource does exist, please check the permissions of the provided token.",
))
return diags.Err()
default:
diags = diags.Append(tfdiags.Sourceless(
tfdiags.Error,
fmt.Sprintf("%s: %v", msg, err),
fmt.Sprintf(`%s returned an unexpected error. Sometimes `, runner.appName)+
`this is caused by network connection problems, in which case you could retry `+
`the command. If the issue persists please open a support ticket to get help `+
`resolving the problem.`,
))
return diags.Err()
}
}

Loading…
Cancel
Save