mirror of
https://github.com/turbot/steampipe.git
synced 2025-12-19 18:12:43 -05:00
160 lines
3.7 KiB
Go
160 lines
3.7 KiB
Go
package error_helpers
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
|
|
"golang.org/x/exp/maps"
|
|
|
|
"github.com/fatih/color"
|
|
"github.com/shiena/ansicolor"
|
|
"github.com/spf13/viper"
|
|
pconstants "github.com/turbot/pipe-fittings/v2/constants"
|
|
"github.com/turbot/steampipe/v2/pkg/statushooks"
|
|
)
|
|
|
|
func init() {
|
|
color.Output = ansicolor.NewAnsiColorWriter(os.Stderr)
|
|
}
|
|
|
|
func WrapError(err error) error {
|
|
if err == nil {
|
|
return nil
|
|
}
|
|
return HandleCancelError(err)
|
|
}
|
|
|
|
func FailOnError(err error) {
|
|
if err != nil {
|
|
err = HandleCancelError(err)
|
|
panic(err)
|
|
}
|
|
}
|
|
|
|
func FailOnErrorWithMessage(err error, message string) {
|
|
if err != nil {
|
|
err = HandleCancelError(err)
|
|
panic(fmt.Sprintf("%s: %s", message, err.Error()))
|
|
}
|
|
}
|
|
|
|
func ShowError(ctx context.Context, err error) {
|
|
if err == nil {
|
|
return
|
|
}
|
|
err = HandleCancelError(err)
|
|
statushooks.Done(ctx)
|
|
fmt.Fprintf(color.Error, "%s: %v\n", pconstants.ColoredErr, TransformErrorToSteampipe(err))
|
|
}
|
|
|
|
// ShowErrorWithMessage displays the given error nicely with the given message
|
|
func ShowErrorWithMessage(ctx context.Context, err error, message string) {
|
|
if err == nil {
|
|
return
|
|
}
|
|
err = HandleCancelError(err)
|
|
statushooks.Done(ctx)
|
|
fmt.Fprintf(color.Error, "%s: %s - %v\n", pconstants.ColoredErr, message, TransformErrorToSteampipe(err))
|
|
}
|
|
|
|
// TransformErrorToSteampipe removes the pq: and rpc error prefixes along
|
|
// with all the unnecessary information that comes from the
|
|
// drivers and libraries
|
|
func TransformErrorToSteampipe(err error) error {
|
|
if err == nil {
|
|
return err
|
|
}
|
|
// transform to a context
|
|
err = HandleCancelError(err)
|
|
|
|
errString := strings.TrimSpace(err.Error())
|
|
|
|
// an error that originated from our database/sql driver (always prefixed with "ERROR:")
|
|
if strings.HasPrefix(errString, "ERROR:") {
|
|
errString = strings.TrimSpace(strings.TrimPrefix(errString, "ERROR:"))
|
|
|
|
// if this is an RPC Error while talking with the plugin
|
|
if strings.HasPrefix(errString, "rpc error") {
|
|
// trim out "rpc error: code = Unknown desc ="
|
|
errString = strings.TrimPrefix(errString, "rpc error: code = Unknown desc =")
|
|
}
|
|
}
|
|
return fmt.Errorf("%s", strings.TrimSpace(errString))
|
|
}
|
|
|
|
// HandleCancelError modifies a context.Canceled error into a readable error that can
|
|
// be printed on the console
|
|
func HandleCancelError(err error) error {
|
|
if IsCancelledError(err) {
|
|
err = errors.New("execution cancelled")
|
|
}
|
|
|
|
return err
|
|
}
|
|
|
|
func HandleQueryTimeoutError(err error) error {
|
|
if errors.Is(err, context.DeadlineExceeded) {
|
|
err = fmt.Errorf("query timeout exceeded (%ds)", viper.GetInt(pconstants.ArgDatabaseQueryTimeout))
|
|
}
|
|
return err
|
|
}
|
|
|
|
func IsCancelledError(err error) bool {
|
|
return errors.Is(err, context.Canceled) || strings.Contains(err.Error(), "canceling statement due to user request")
|
|
}
|
|
|
|
func ShowWarning(warning string) {
|
|
if len(warning) == 0 {
|
|
return
|
|
}
|
|
fmt.Fprintf(color.Error, "%s: %v\n", pconstants.ColoredWarn, warning)
|
|
}
|
|
|
|
func CombineErrorsWithPrefix(prefix string, errors ...error) error {
|
|
if len(errors) == 0 {
|
|
return nil
|
|
}
|
|
|
|
if allErrorsNil(errors...) {
|
|
return nil
|
|
}
|
|
|
|
if len(errors) == 1 {
|
|
if len(prefix) == 0 {
|
|
return errors[0]
|
|
} else {
|
|
return fmt.Errorf("%s - %s", prefix, errors[0].Error())
|
|
}
|
|
}
|
|
|
|
combinedErrorString := map[string]struct{}{prefix: {}}
|
|
for _, e := range errors {
|
|
if e == nil {
|
|
continue
|
|
}
|
|
combinedErrorString[e.Error()] = struct{}{}
|
|
}
|
|
|
|
return fmt.Errorf("%s", strings.Join(maps.Keys(combinedErrorString), "\n\t"))
|
|
}
|
|
|
|
func allErrorsNil(errors ...error) bool {
|
|
for _, e := range errors {
|
|
if e != nil {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
func CombineErrors(errors ...error) error {
|
|
return CombineErrorsWithPrefix("", errors...)
|
|
}
|
|
|
|
func PrefixError(err error, prefix string) error {
|
|
return fmt.Errorf("%s: %s\n", prefix, TransformErrorToSteampipe(err).Error())
|
|
}
|