...
1
2
3
4
19
20 package errors
21
22 import (
23 "errors"
24 "fmt"
25
26 "sigs.k8s.io/kustomize/kyaml/yaml/internal/k8sgen/pkg/util/sets"
27 )
28
29
30 type MessageCountMap map[string]int
31
32
33
34
35
36
37
38 type Aggregate interface {
39 error
40 Errors() []error
41 Is(error) bool
42 }
43
44
45
46
47
48
49 func NewAggregate(errlist []error) Aggregate {
50 if len(errlist) == 0 {
51 return nil
52 }
53
54 var errs []error
55 for _, e := range errlist {
56 if e != nil {
57 errs = append(errs, e)
58 }
59 }
60 if len(errs) == 0 {
61 return nil
62 }
63 return aggregate(errs)
64 }
65
66
67
68
69 type aggregate []error
70
71
72 func (agg aggregate) Error() string {
73 if len(agg) == 0 {
74
75 return ""
76 }
77 if len(agg) == 1 {
78 return agg[0].Error()
79 }
80 seenerrs := sets.NewString()
81 result := ""
82 agg.visit(func(err error) bool {
83 msg := err.Error()
84 if seenerrs.Has(msg) {
85 return false
86 }
87 seenerrs.Insert(msg)
88 if len(seenerrs) > 1 {
89 result += ", "
90 }
91 result += msg
92 return false
93 })
94 if len(seenerrs) == 1 {
95 return result
96 }
97 return "[" + result + "]"
98 }
99
100 func (agg aggregate) Is(target error) bool {
101 return agg.visit(func(err error) bool {
102 return errors.Is(err, target)
103 })
104 }
105
106 func (agg aggregate) visit(f func(err error) bool) bool {
107 for _, err := range agg {
108 switch err := err.(type) {
109 case aggregate:
110 if match := err.visit(f); match {
111 return match
112 }
113 case Aggregate:
114 for _, nestedErr := range err.Errors() {
115 if match := f(nestedErr); match {
116 return match
117 }
118 }
119 default:
120 if match := f(err); match {
121 return match
122 }
123 }
124 }
125
126 return false
127 }
128
129
130 func (agg aggregate) Errors() []error {
131 return []error(agg)
132 }
133
134
135 type Matcher func(error) bool
136
137
138
139
140
141
142
143
144 func FilterOut(err error, fns ...Matcher) error {
145 if err == nil {
146 return nil
147 }
148 if agg, ok := err.(Aggregate); ok {
149 return NewAggregate(filterErrors(agg.Errors(), fns...))
150 }
151 if !matchesError(err, fns...) {
152 return err
153 }
154 return nil
155 }
156
157
158 func matchesError(err error, fns ...Matcher) bool {
159 for _, fn := range fns {
160 if fn(err) {
161 return true
162 }
163 }
164 return false
165 }
166
167
168
169
170
171 func filterErrors(list []error, fns ...Matcher) []error {
172 result := []error{}
173 for _, err := range list {
174 r := FilterOut(err, fns...)
175 if r != nil {
176 result = append(result, r)
177 }
178 }
179 return result
180 }
181
182
183
184 func Flatten(agg Aggregate) Aggregate {
185 result := []error{}
186 if agg == nil {
187 return nil
188 }
189 for _, err := range agg.Errors() {
190 if a, ok := err.(Aggregate); ok {
191 r := Flatten(a)
192 if r != nil {
193 result = append(result, r.Errors()...)
194 }
195 } else {
196 if err != nil {
197 result = append(result, err)
198 }
199 }
200 }
201 return NewAggregate(result)
202 }
203
204
205 func CreateAggregateFromMessageCountMap(m MessageCountMap) Aggregate {
206 if m == nil {
207 return nil
208 }
209 result := make([]error, 0, len(m))
210 for errStr, count := range m {
211 var countStr string
212 if count > 1 {
213 countStr = fmt.Sprintf(" (repeated %v times)", count)
214 }
215 result = append(result, fmt.Errorf("%v%v", errStr, countStr))
216 }
217 return NewAggregate(result)
218 }
219
220
221
222 func Reduce(err error) error {
223 if agg, ok := err.(Aggregate); ok && err != nil {
224 switch len(agg.Errors()) {
225 case 1:
226 return agg.Errors()[0]
227 case 0:
228 return nil
229 }
230 }
231 return err
232 }
233
234
235
236
237 func AggregateGoroutines(funcs ...func() error) Aggregate {
238 errChan := make(chan error, len(funcs))
239 for _, f := range funcs {
240 go func(f func() error) { errChan <- f() }(f)
241 }
242 errs := make([]error, 0)
243 for i := 0; i < cap(errChan); i++ {
244 if err := <-errChan; err != nil {
245 errs = append(errs, err)
246 }
247 }
248 return NewAggregate(errs)
249 }
250
251
252 var ErrPreconditionViolated = errors.New("precondition is violated")
253
View as plain text