-
Notifications
You must be signed in to change notification settings - Fork 787
/
helpers.go
192 lines (175 loc) · 5.96 KB
/
helpers.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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
package cmd
import (
"fmt"
"net/url"
"os"
"strings"
"github.com/golang/glog"
"github.com/spf13/cobra"
)
const (
DefaultErrorExitCode = 1
DefaultWritePermissions = 0760
)
type debugError interface {
DebugError() (msg string, args []interface{})
}
var fatalErrHandler = fatal
// BehaviorOnFatal allows you to override the default behavior when a fatal
// error occurs, which is to call os.Exit(code). You can pass 'panic' as a function
// here if you prefer the panic() over os.Exit(1).
func BehaviorOnFatal(f func(string, int)) {
fatalErrHandler = f
}
// DefaultBehaviorOnFatal allows you to undo any previous override. Useful in
// tests.
func DefaultBehaviorOnFatal() {
fatalErrHandler = fatal
}
// fatal prints the message (if provided) and then exits. If V(2) or greater,
// glog.Fatal is invoked for extended information.
func fatal(msg string, code int) {
/*
if glog.V(2) {
glog.FatalDepth(2, msg)
}
*/
if len(msg) > 0 {
// add newline if needed
if !strings.HasSuffix(msg, "\n") {
msg += "\n"
}
fmt.Fprint(os.Stderr, msg)
}
os.Exit(code)
}
// ErrExit may be passed to CheckError to instruct it to output nothing but exit with
// status code 1.
var ErrExit = fmt.Errorf("exit")
// CheckErr prints a user friendly error to STDERR and exits with a non-zero
// exit code. Unrecognized errors will be printed with an "error: " prefix.
//
// This method is generic to the command in use and may be used by non-Kubectl
// commands.
func CheckErr(err error) {
checkErr("", err, fatalErrHandler)
}
// checkErrWithPrefix works like CheckErr, but adds a caller-defined prefix to non-nil errors
func checkErrWithPrefix(prefix string, err error) {
checkErr(prefix, err, fatalErrHandler)
}
// checkErr formats a given error as a string and calls the passed handleErr
// func with that string and an kubectl exit code.
func checkErr(prefix string, err error, handleErr func(string, int)) {
// unwrap aggregates of 1
/*
if agg, ok := err.(utilerrors.Aggregate); ok && len(agg.Errors()) == 1 {
err = agg.Errors()[0]
}
*/
switch {
case err == nil:
return
case err == ErrExit:
handleErr("", DefaultErrorExitCode)
return
/*
case kerrors.IsInvalid(err):
details := err.(*kerrors.StatusError).Status().Details
s := fmt.Sprintf("%sThe %s %q is invalid", prefix, details.Kind, details.Name)
if len(details.Causes) > 0 {
errs := statusCausesToAggrError(details.Causes)
handleErr(MultilineError(s+": ", errs), DefaultErrorExitCode)
} else {
handleErr(s, DefaultErrorExitCode)
}
case clientcmd.IsConfigurationInvalid(err):
handleErr(MultilineError(fmt.Sprintf("%sError in configuration: ", prefix), err), DefaultErrorExitCode)
*/
default:
switch err := err.(type) {
/*
case *meta.NoResourceMatchError:
switch {
case len(err.PartialResource.Group) > 0 && len(err.PartialResource.Version) > 0:
handleErr(fmt.Sprintf("%sthe server doesn't have a resource type %q in group %q and version %q", prefix, err.PartialResource.Resource, err.PartialResource.Group, err.PartialResource.Version), DefaultErrorExitCode)
case len(err.PartialResource.Group) > 0:
handleErr(fmt.Sprintf("%sthe server doesn't have a resource type %q in group %q", prefix, err.PartialResource.Resource, err.PartialResource.Group), DefaultErrorExitCode)
case len(err.PartialResource.Version) > 0:
handleErr(fmt.Sprintf("%sthe server doesn't have a resource type %q in version %q", prefix, err.PartialResource.Resource, err.PartialResource.Version), DefaultErrorExitCode)
default:
handleErr(fmt.Sprintf("%sthe server doesn't have a resource type %q", prefix, err.PartialResource.Resource), DefaultErrorExitCode)
}
case utilerrors.Aggregate:
handleErr(MultipleErrors(prefix, err.Errors()), DefaultErrorExitCode)
case utilexec.ExitError:
// do not print anything, only terminate with given error
handleErr("", err.ExitStatus())
*/
default: // for any other error type
msg, ok := StandardErrorMessage(err)
if !ok {
msg = err.Error()
if !strings.HasPrefix(msg, "error: ") {
msg = fmt.Sprintf("error: %s", msg)
}
}
handleErr(msg, DefaultErrorExitCode)
}
}
}
// StandardErrorMessage translates common errors into a human readable message, or returns
// false if the error is not one of the recognized types. It may also log extended
// information to glog.
//
// This method is generic to the command in use and may be used by non-Kubectl
// commands.
func StandardErrorMessage(err error) (string, bool) {
/*
if debugErr, ok := err.(debugError); ok {
glog.V(4).Infof(debugErr.DebugError())
}
status, isStatus := err.(kerrors.APIStatus)
switch {
case isStatus:
switch s := status.Status(); {
case s.Reason == unversioned.StatusReasonUnauthorized:
return fmt.Sprintf("error: You must be logged in to the server (%s)", s.Message), true
case len(s.Reason) > 0:
return fmt.Sprintf("Error from server (%s): %s", s.Reason, err.Error()), true
default:
return fmt.Sprintf("Error from server: %s", err.Error()), true
}
case kerrors.IsUnexpectedObjectError(err):
return fmt.Sprintf("Server returned an unexpected response: %s", err.Error()), true
}
*/
switch t := err.(type) {
case *url.Error:
glog.V(4).Infof("Connection error: %s %s: %v", t.Op, t.URL, t.Err)
switch {
case strings.Contains(t.Err.Error(), "connection refused"):
host := t.URL
if server, err := url.Parse(t.URL); err == nil {
host = server.Host
}
return fmt.Sprintf("The connection to the server %s was refused - did you specify the right host or port?", host), true
}
return fmt.Sprintf("Unable to connect to the server: %v", t.Err), true
}
return "", false
}
func UsageError(cmd *cobra.Command, format string, args ...interface{}) error {
msg := fmt.Sprintf(format, args...)
return fmt.Errorf("%s\nSee '%s -h' for help and examples.", msg, cmd.CommandPath())
}
func HomeDir() string {
if h := os.Getenv("HOME"); h != "" {
return h
}
h := os.Getenv("USERPROFILE") // windows
if h == "" {
h = "."
}
return h
}