...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package genericwebhook
17
18 import (
19 "reflect"
20 "strings"
21
22 "github.com/pkg/errors"
23 "k8s.io/apimachinery/pkg/util/validation/field"
24 )
25
26 type FieldValidator interface {
27 Validate(root interface{}, path *field.Path) field.ErrorList
28 }
29
30
31
32
33
34
35 func Validate(obj interface{}) field.ErrorList {
36
37 errorList := field.ErrorList{}
38
39 root := obj
40 walker := NewFieldWalker(obj, func(path *field.Path, obj interface{}, field *reflect.StructField) bool {
41 webhookAttr := ""
42 if field != nil {
43 webhookAttr = field.Tag.Get("webhook")
44 }
45 attributes := strings.Split(webhookAttr, ",")
46
47 webhook := ""
48 nilable := false
49 if len(attributes) > 0 {
50 webhook = attributes[0]
51 }
52 if len(attributes) > 1 {
53 nilable = attributes[1] == "nilable"
54 }
55
56 validator := getValidator(obj, webhook, nilable)
57 if validator != nil {
58 if err := validator.Validate(root, path); err != nil {
59 errorList = append(errorList, err...)
60 }
61 }
62
63 return true
64 })
65 walker.Walk()
66
67 return errorList
68 }
69
70 func Aggregate(errs field.ErrorList) error {
71 if errs == nil || len(errs) == 0 {
72 return nil
73 }
74 return errors.New(errs.ToAggregate().Error())
75 }
76
77 func getValidator(obj interface{}, webhook string, nilable bool) FieldValidator {
78
79
80
81
82 val := reflect.ValueOf(obj)
83
84 if validator, ok := obj.(FieldValidator); ok {
85 if nilable || !val.IsZero() {
86 return validator
87 }
88 }
89
90 if webhook != "" {
91 webhookImpl := webhooks[webhook]
92
93 v := val.Convert(webhookImpl).Interface()
94 if validator, ok := v.(FieldValidator); ok {
95 if nilable || !val.IsZero() {
96 return validator
97 }
98 }
99 }
100
101 return nil
102 }
103