-
Notifications
You must be signed in to change notification settings - Fork 262
/
utils.go
158 lines (133 loc) · 3.71 KB
/
utils.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
package error_helpers
import (
"context"
"errors"
"fmt"
"golang.org/x/exp/maps"
"os"
"strings"
"github.com/fatih/color"
"github.com/shiena/ansicolor"
"github.com/spf13/viper"
"github.com/turbot/steampipe/pkg/constants"
"github.com/turbot/steampipe/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.Output, "%s: %v\n", constants.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.Output, "%s: %s - %v\n", constants.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(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(constants.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.Output, "%s: %v\n", constants.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(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())
}