...
1
2
3
4 package errors
5
6 import (
7 "bytes"
8 "fmt"
9 "io"
10 "os"
11 "reflect"
12 "strings"
13 "text/template"
14
15 cmdutil "k8s.io/kubectl/pkg/cmd/util"
16 "sigs.k8s.io/cli-utils/pkg/inventory"
17 "sigs.k8s.io/cli-utils/pkg/manifestreader"
18 )
19
20 const (
21 DefaultErrorExitCode = 1
22 )
23
24 var errorMsgForType map[reflect.Type]string
25 var statusCodeForType map[reflect.Type]int
26
27
28 func init() {
29 errorMsgForType = make(map[reflect.Type]string)
30 errorMsgForType[reflect.TypeOf(inventory.NoInventoryObjError{})] = `
31 Package uninitialized. Please run "{{.cmdNameBase}} init" command.
32
33 The package needs to be initialized to generate the template
34 which will store state for resource sets. This state is
35 necessary to perform functionality such as deleting an entire
36 package or automatically deleting omitted resources (pruning).
37 `
38
39 errorMsgForType[reflect.TypeOf(inventory.MultipleInventoryObjError{})] = `
40 Package has multiple inventory object templates.
41
42 The package should have one and only one inventory object template.
43 `
44
45 errorMsgForType[reflect.TypeOf(manifestreader.UnknownTypesError{})] = `
46 Unknown type(s) encountered. Every type must either be already installed in the cluster or the CRD must be among the applied manifests.
47
48 {{- range .err.GroupKinds}}
49 {{ printf "%s" . }}
50 {{- end}}
51 `
52
53 statusCodeForType = make(map[reflect.Type]int)
54 }
55
56
57
58
59 func CheckErr(w io.Writer, err error, cmdNameBase string) {
60 errText, found := textForError(err, cmdNameBase)
61 if found {
62 exitStatus := findErrExitCode(err)
63 if len(errText) > 0 {
64 if !strings.HasSuffix(errText, "\n") {
65 errText += "\n"
66 }
67 fmt.Fprint(w, errText)
68 }
69 os.Exit(exitStatus)
70 }
71
72 cmdutil.CheckErr(err)
73 }
74
75
76 func textForError(baseErr error, cmdNameBase string) (string, bool) {
77 errType, found := findErrType(baseErr)
78 if !found {
79 return "", false
80 }
81 tmplText, found := errorMsgForType[errType]
82 if !found {
83 return "", false
84 }
85
86 tmpl, err := template.New("errMsg").Parse(tmplText)
87 if err != nil {
88
89
90
91 return "", false
92 }
93 var b bytes.Buffer
94 err = tmpl.Execute(&b, map[string]interface{}{
95 "cmdNameBase": cmdNameBase,
96 "err": baseErr,
97 })
98 if err != nil {
99 return "", false
100 }
101 return strings.TrimSpace(b.String()), true
102 }
103
104
105
106 func findErrType(err error) (reflect.Type, bool) {
107 switch reflect.ValueOf(err).Kind() {
108 case reflect.Ptr:
109
110
111 return reflect.ValueOf(err).Elem().Type(), true
112 case reflect.Struct:
113 return reflect.TypeOf(err), true
114 default:
115 return nil, false
116 }
117 }
118
119
120
121 func findErrExitCode(err error) int {
122 errType, found := findErrType(err)
123 if !found {
124 return DefaultErrorExitCode
125 }
126 if exitStatus, found := statusCodeForType[errType]; found {
127 return exitStatus
128 }
129 return DefaultErrorExitCode
130 }
131
View as plain text