1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package validate
16
17 import (
18 "reflect"
19
20 "k8s.io/kube-openapi/pkg/validation/errors"
21 "k8s.io/kube-openapi/pkg/validation/spec"
22 )
23
24
25 type ValueValidator interface {
26
27
28
29 SetPath(path string)
30
31
32 Applies(source interface{}, valueKind reflect.Kind) bool
33
34 Validate(value interface{}) *Result
35 }
36
37 type basicCommonValidator struct {
38 Path string
39 In string
40 Default interface{}
41 Enum []interface{}
42 }
43
44 func (b *basicCommonValidator) SetPath(path string) {
45 b.Path = path
46 }
47
48 func (b *basicCommonValidator) Applies(source interface{}, kind reflect.Kind) bool {
49 switch source.(type) {
50 case *spec.Schema:
51 return true
52 }
53 return false
54 }
55
56 func (b *basicCommonValidator) Validate(data interface{}) (res *Result) {
57 if len(b.Enum) > 0 {
58 for _, enumValue := range b.Enum {
59 actualType := reflect.TypeOf(enumValue)
60 if actualType != nil {
61 expectedValue := reflect.ValueOf(data)
62 if expectedValue.IsValid() && expectedValue.Type().ConvertibleTo(actualType) {
63 if reflect.DeepEqual(expectedValue.Convert(actualType).Interface(), enumValue) {
64 return nil
65 }
66 }
67 }
68 }
69 return errorHelp.sErr(errors.EnumFail(b.Path, b.In, data, b.Enum))
70 }
71 return nil
72 }
73
74 type numberValidator struct {
75 Path string
76 In string
77 Default interface{}
78 MultipleOf *float64
79 Maximum *float64
80 ExclusiveMaximum bool
81 Minimum *float64
82 ExclusiveMinimum bool
83
84 Type string
85 Format string
86 }
87
88 func (n *numberValidator) SetPath(path string) {
89 n.Path = path
90 }
91
92 func (n *numberValidator) Applies(source interface{}, kind reflect.Kind) bool {
93 switch source.(type) {
94 case *spec.Schema:
95 isInt := kind >= reflect.Int && kind <= reflect.Uint64
96 isFloat := kind == reflect.Float32 || kind == reflect.Float64
97 r := isInt || isFloat
98 debugLog("schema props validator for %q applies %t for %T (kind: %v) isInt=%t, isFloat=%t\n", n.Path, r, source, kind, isInt, isFloat)
99 return r
100 }
101 debugLog("schema props validator for %q applies %t for %T (kind: %v)\n", n.Path, false, source, kind)
102 return false
103 }
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126 func (n *numberValidator) Validate(val interface{}) *Result {
127 res := new(Result)
128
129 resMultiple := new(Result)
130 resMinimum := new(Result)
131 resMaximum := new(Result)
132
133
134
135 data := valueHelp.asFloat64(val)
136
137
138 res.AddErrors(IsValueValidAgainstRange(val, n.Type, n.Format, "Checked", n.Path))
139
140
141 if n.MultipleOf != nil {
142
143 resMultiple.AddErrors(IsValueValidAgainstRange(*n.MultipleOf, n.Type, n.Format, "MultipleOf", n.Path))
144 if resMultiple.IsValid() {
145
146 if err := MultipleOfNativeType(n.Path, n.In, val, *n.MultipleOf); err != nil {
147 resMultiple.Merge(errorHelp.sErr(err))
148 }
149 } else {
150
151 if err := MultipleOf(n.Path, n.In, data, *n.MultipleOf); err != nil {
152 resMultiple.Merge(errorHelp.sErr(err))
153 }
154 }
155 }
156
157
158 if n.Maximum != nil {
159
160 resMaximum.AddErrors(IsValueValidAgainstRange(*n.Maximum, n.Type, n.Format, "Maximum boundary", n.Path))
161 if resMaximum.IsValid() {
162
163 if err := MaximumNativeType(n.Path, n.In, val, *n.Maximum, n.ExclusiveMaximum); err != nil {
164 resMaximum.Merge(errorHelp.sErr(err))
165 }
166 } else {
167
168 if err := Maximum(n.Path, n.In, data, *n.Maximum, n.ExclusiveMaximum); err != nil {
169 resMaximum.Merge(errorHelp.sErr(err))
170 }
171 }
172 }
173
174
175 if n.Minimum != nil {
176
177 resMinimum.AddErrors(IsValueValidAgainstRange(*n.Minimum, n.Type, n.Format, "Minimum boundary", n.Path))
178 if resMinimum.IsValid() {
179
180 if err := MinimumNativeType(n.Path, n.In, val, *n.Minimum, n.ExclusiveMinimum); err != nil {
181 resMinimum.Merge(errorHelp.sErr(err))
182 }
183 } else {
184
185 if err := Minimum(n.Path, n.In, data, *n.Minimum, n.ExclusiveMinimum); err != nil {
186 resMinimum.Merge(errorHelp.sErr(err))
187 }
188 }
189 }
190 res.Merge(resMultiple, resMinimum, resMaximum)
191 res.Inc()
192 return res
193 }
194
195 type stringValidator struct {
196 MaxLength *int64
197 MinLength *int64
198 Pattern string
199 Path string
200 In string
201 }
202
203 func (s *stringValidator) SetPath(path string) {
204 s.Path = path
205 }
206
207 func (s *stringValidator) Applies(source interface{}, kind reflect.Kind) bool {
208 switch source.(type) {
209 case *spec.Schema:
210 r := kind == reflect.String
211 debugLog("string validator for %q applies %t for %T (kind: %v)\n", s.Path, r, source, kind)
212 return r
213 }
214 debugLog("string validator for %q applies %t for %T (kind: %v)\n", s.Path, false, source, kind)
215 return false
216 }
217
218 func (s *stringValidator) Validate(val interface{}) *Result {
219 data, ok := val.(string)
220 if !ok {
221 return errorHelp.sErr(errors.InvalidType(s.Path, s.In, stringType, val))
222 }
223
224 if s.MaxLength != nil {
225 if err := MaxLength(s.Path, s.In, data, *s.MaxLength); err != nil {
226 return errorHelp.sErr(err)
227 }
228 }
229
230 if s.MinLength != nil {
231 if err := MinLength(s.Path, s.In, data, *s.MinLength); err != nil {
232 return errorHelp.sErr(err)
233 }
234 }
235
236 if s.Pattern != "" {
237 if err := Pattern(s.Path, s.In, data, s.Pattern); err != nil {
238 return errorHelp.sErr(err)
239 }
240 }
241 return nil
242 }
243
View as plain text