1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package validate
16
17 import (
18 "reflect"
19 "strings"
20
21 "github.com/go-openapi/swag"
22 "k8s.io/kube-openapi/pkg/validation/errors"
23 "k8s.io/kube-openapi/pkg/validation/spec"
24 "k8s.io/kube-openapi/pkg/validation/strfmt"
25 )
26
27 type typeValidator struct {
28 Type spec.StringOrArray
29 Nullable bool
30 Format string
31 In string
32 Path string
33 }
34
35 func (t *typeValidator) schemaInfoForType(data interface{}) (string, string) {
36
37
38
39 switch data.(type) {
40 case []byte, strfmt.Base64, *strfmt.Base64:
41 return stringType, stringFormatByte
42 case strfmt.CreditCard, *strfmt.CreditCard:
43 return stringType, stringFormatCreditCard
44 case strfmt.Date, *strfmt.Date:
45 return stringType, stringFormatDate
46 case strfmt.DateTime, *strfmt.DateTime:
47 return stringType, stringFormatDateTime
48 case strfmt.Duration, *strfmt.Duration:
49 return stringType, stringFormatDuration
50 case strfmt.Email, *strfmt.Email:
51 return stringType, stringFormatEmail
52 case strfmt.HexColor, *strfmt.HexColor:
53 return stringType, stringFormatHexColor
54 case strfmt.Hostname, *strfmt.Hostname:
55 return stringType, stringFormatHostname
56 case strfmt.IPv4, *strfmt.IPv4:
57 return stringType, stringFormatIPv4
58 case strfmt.IPv6, *strfmt.IPv6:
59 return stringType, stringFormatIPv6
60 case strfmt.ISBN, *strfmt.ISBN:
61 return stringType, stringFormatISBN
62 case strfmt.ISBN10, *strfmt.ISBN10:
63 return stringType, stringFormatISBN10
64 case strfmt.ISBN13, *strfmt.ISBN13:
65 return stringType, stringFormatISBN13
66 case strfmt.MAC, *strfmt.MAC:
67 return stringType, stringFormatMAC
68 case strfmt.Password, *strfmt.Password:
69 return stringType, stringFormatPassword
70 case strfmt.RGBColor, *strfmt.RGBColor:
71 return stringType, stringFormatRGBColor
72 case strfmt.SSN, *strfmt.SSN:
73 return stringType, stringFormatSSN
74 case strfmt.URI, *strfmt.URI:
75 return stringType, stringFormatURI
76 case strfmt.UUID, *strfmt.UUID:
77 return stringType, stringFormatUUID
78 case strfmt.UUID3, *strfmt.UUID3:
79 return stringType, stringFormatUUID3
80 case strfmt.UUID4, *strfmt.UUID4:
81 return stringType, stringFormatUUID4
82 case strfmt.UUID5, *strfmt.UUID5:
83 return stringType, stringFormatUUID5
84
85
86 default:
87 val := reflect.ValueOf(data)
88 tpe := val.Type()
89 switch tpe.Kind() {
90 case reflect.Bool:
91 return booleanType, ""
92 case reflect.String:
93 return stringType, ""
94 case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Uint8, reflect.Uint16, reflect.Uint32:
95
96 return integerType, integerFormatInt32
97 case reflect.Int, reflect.Int64, reflect.Uint, reflect.Uint64:
98 return integerType, integerFormatInt64
99 case reflect.Float32:
100
101 return numberType, numberFormatFloat32
102 case reflect.Float64:
103
104 return numberType, numberFormatFloat64
105
106 case reflect.Slice:
107 return arrayType, ""
108 case reflect.Map, reflect.Struct:
109 return objectType, ""
110 case reflect.Interface:
111
112 panic("dunno what to do here")
113 case reflect.Ptr:
114 return t.schemaInfoForType(reflect.Indirect(val).Interface())
115 }
116 }
117 return "", ""
118 }
119
120 func (t *typeValidator) SetPath(path string) {
121 t.Path = path
122 }
123
124 func (t *typeValidator) Applies(source interface{}, kind reflect.Kind) bool {
125
126 stpe := reflect.TypeOf(source)
127 r := (len(t.Type) > 0 || t.Format != "") && stpe == specSchemaType
128 debugLog("type validator for %q applies %t for %T (kind: %v)\n", t.Path, r, source, kind)
129 return r
130 }
131
132 func (t *typeValidator) Validate(data interface{}) *Result {
133 result := new(Result)
134 result.Inc()
135 if data == nil {
136
137 if len(t.Type) > 0 && !t.Type.Contains(nullType) && !t.Nullable {
138 return errorHelp.sErr(errors.InvalidType(t.Path, t.In, strings.Join(t.Type, ","), nullType))
139 }
140 return result
141 }
142
143
144 val := reflect.Indirect(reflect.ValueOf(data))
145 kind := val.Kind()
146
147
148 schType, format := t.schemaInfoForType(data)
149
150 debugLog("path: %s, schType: %s, format: %s, expType: %s, expFmt: %s, kind: %s", t.Path, schType, format, t.Type, t.Format, val.Kind().String())
151
152
153
154
155 isLowerInt := t.Format == integerFormatInt64 && format == integerFormatInt32
156 isLowerFloat := t.Format == numberFormatFloat64 && format == numberFormatFloat32
157 isFloatInt := schType == numberType && swag.IsFloat64AJSONInteger(val.Float()) && t.Type.Contains(integerType)
158 isIntFloat := schType == integerType && t.Type.Contains(numberType)
159
160 if kind != reflect.String && kind != reflect.Slice && t.Format != "" && !(t.Type.Contains(schType) || format == t.Format || isFloatInt || isIntFloat || isLowerInt || isLowerFloat) {
161
162 return errorHelp.sErr(errors.InvalidType(t.Path, t.In, t.Format, format))
163 }
164
165 if !(t.Type.Contains(numberType) || t.Type.Contains(integerType)) && t.Format != "" && (kind == reflect.String || kind == reflect.Slice) {
166 return result
167 }
168
169 if !(t.Type.Contains(schType) || isFloatInt || isIntFloat) {
170 return errorHelp.sErr(errors.InvalidType(t.Path, t.In, strings.Join(t.Type, ","), schType))
171 }
172 return result
173 }
174
View as plain text