1
16
17 package resource
18
19 import (
20 "fmt"
21 "testing"
22
23 "k8s.io/apimachinery/pkg/api/errors"
24 "k8s.io/apimachinery/pkg/runtime/schema"
25 "k8s.io/client-go/discovery"
26 "k8s.io/client-go/openapi/cached"
27 "k8s.io/client-go/openapi/openapitest"
28 "k8s.io/client-go/openapi3"
29 )
30
31 func TestFallbackQueryParamVerifier_PrimaryNoFallback(t *testing.T) {
32 tests := map[string]struct {
33 crds []schema.GroupKind
34 gvk schema.GroupVersionKind
35 queryParam VerifiableQueryParam
36 expectedSupports bool
37 }{
38 "Field validation query param is supported for batch/v1/Job, primary verifier": {
39 crds: []schema.GroupKind{},
40 gvk: schema.GroupVersionKind{
41 Group: "batch",
42 Version: "v1",
43 Kind: "Job",
44 },
45 queryParam: QueryParamFieldValidation,
46 expectedSupports: true,
47 },
48 "Field validation query param supported for core/v1/Namespace, primary verifier": {
49 crds: []schema.GroupKind{},
50 gvk: schema.GroupVersionKind{
51 Group: "",
52 Version: "v1",
53 Kind: "Namespace",
54 },
55 queryParam: QueryParamFieldValidation,
56 expectedSupports: true,
57 },
58 "Field validation unsupported for unknown GVK in primary verifier": {
59 crds: []schema.GroupKind{},
60 gvk: schema.GroupVersionKind{
61 Group: "bad",
62 Version: "v1",
63 Kind: "Uknown",
64 },
65 queryParam: QueryParamFieldValidation,
66 expectedSupports: false,
67 },
68 "Unknown query param unsupported (for all GVK's) in primary verifier": {
69 crds: []schema.GroupKind{},
70 gvk: schema.GroupVersionKind{
71 Group: "apps",
72 Version: "v1",
73 Kind: "Deployment",
74 },
75 queryParam: "UnknownQueryParam",
76 expectedSupports: false,
77 },
78 "Field validation query param supported for found CRD in primary verifier": {
79 crds: []schema.GroupKind{
80 {
81 Group: "example.com",
82 Kind: "ExampleCRD",
83 },
84 },
85
86 gvk: schema.GroupVersionKind{
87 Group: "example.com",
88 Version: "v1",
89 Kind: "ExampleCRD",
90 },
91 queryParam: QueryParamFieldValidation,
92 expectedSupports: true,
93 },
94 "Field validation query param unsupported for missing CRD in primary verifier": {
95 crds: []schema.GroupKind{
96 {
97 Group: "different.com",
98 Kind: "DifferentCRD",
99 },
100 },
101
102 gvk: schema.GroupVersionKind{
103 Group: "example.com",
104 Version: "v1",
105 Kind: "ExampleCRD",
106 },
107 queryParam: QueryParamFieldValidation,
108 expectedSupports: false,
109 },
110 "List GVK is specifically unsupported in primary verfier": {
111 crds: []schema.GroupKind{},
112 gvk: schema.GroupVersionKind{
113 Group: "",
114 Version: "v1",
115 Kind: "List",
116 },
117 queryParam: QueryParamFieldValidation,
118 expectedSupports: false,
119 },
120 }
121
122 root := openapi3.NewRoot(cached.NewClient(openapitest.NewEmbeddedFileClient()))
123 for tn, tc := range tests {
124 t.Run(tn, func(t *testing.T) {
125 primary := createFakeV3Verifier(tc.crds, root, tc.queryParam)
126
127 secondary := &failingVerifier{name: "secondary", t: t}
128 verifier := NewFallbackQueryParamVerifier(primary, secondary)
129 err := verifier.HasSupport(tc.gvk)
130 if tc.expectedSupports && err != nil {
131 t.Errorf("Expected supports, but returned err for GVK (%s)", tc.gvk)
132 } else if !tc.expectedSupports && err == nil {
133 t.Errorf("Expected not supports, but returned no err for GVK (%s)", tc.gvk)
134 }
135 })
136 }
137 }
138
139 func TestFallbackQueryParamVerifier_SecondaryFallback(t *testing.T) {
140 tests := map[string]struct {
141 crds []schema.GroupKind
142 gvk schema.GroupVersionKind
143 queryParam VerifiableQueryParam
144 primaryError error
145 expectedSupports bool
146 }{
147 "Field validation query param is supported for batch/v1/Job, secondary verifier": {
148 crds: []schema.GroupKind{},
149 gvk: schema.GroupVersionKind{
150 Group: "batch",
151 Version: "v1",
152 Kind: "Job",
153 },
154 queryParam: QueryParamFieldValidation,
155 primaryError: errors.NewNotFound(schema.GroupResource{}, "OpenAPI V3 endpoint not found"),
156 expectedSupports: true,
157 },
158 "Field validation query param is supported for batch/v1/Job, invalid v3 document error": {
159 crds: []schema.GroupKind{},
160 gvk: schema.GroupVersionKind{
161 Group: "batch",
162 Version: "v1",
163 Kind: "Job",
164 },
165 queryParam: QueryParamFieldValidation,
166 primaryError: fmt.Errorf("Invalid OpenAPI V3 document"),
167 expectedSupports: true,
168 },
169 "Field validation query param is supported for batch/v1/Job, timeout error": {
170 crds: []schema.GroupKind{},
171 gvk: schema.GroupVersionKind{
172 Group: "batch",
173 Version: "v1",
174 Kind: "Job",
175 },
176 queryParam: QueryParamFieldValidation,
177 primaryError: fmt.Errorf("timeout"),
178 expectedSupports: true,
179 },
180 "Field validation query param supported for core/v1/Namespace, secondary verifier": {
181 crds: []schema.GroupKind{},
182 gvk: schema.GroupVersionKind{
183 Group: "",
184 Version: "v1",
185 Kind: "Namespace",
186 },
187 queryParam: QueryParamFieldValidation,
188 primaryError: errors.NewNotFound(schema.GroupResource{}, "OpenAPI V3 endpoint not found"),
189 expectedSupports: true,
190 },
191 "Field validation unsupported for unknown GVK, secondary verifier": {
192 crds: []schema.GroupKind{},
193 gvk: schema.GroupVersionKind{
194 Group: "bad",
195 Version: "v1",
196 Kind: "Uknown",
197 },
198 queryParam: QueryParamFieldValidation,
199 primaryError: errors.NewNotFound(schema.GroupResource{}, "OpenAPI V3 endpoint not found"),
200 expectedSupports: false,
201 },
202 "Field validation unsupported for unknown GVK, invalid document causes secondary verifier": {
203 crds: []schema.GroupKind{},
204 gvk: schema.GroupVersionKind{
205 Group: "bad",
206 Version: "v1",
207 Kind: "Uknown",
208 },
209 queryParam: QueryParamFieldValidation,
210 primaryError: fmt.Errorf("Invalid OpenAPI V3 document"),
211 expectedSupports: false,
212 },
213 "Unknown query param unsupported (for all GVK's), secondary verifier": {
214 crds: []schema.GroupKind{},
215 gvk: schema.GroupVersionKind{
216 Group: "apps",
217 Version: "v1",
218 Kind: "Deployment",
219 },
220 queryParam: "UnknownQueryParam",
221 primaryError: errors.NewNotFound(schema.GroupResource{}, "OpenAPI V3 endpoint not found"),
222 expectedSupports: false,
223 },
224 "Field validation query param supported for found CRD, secondary verifier": {
225 crds: []schema.GroupKind{
226 {
227 Group: "example.com",
228 Kind: "ExampleCRD",
229 },
230 },
231
232 gvk: schema.GroupVersionKind{
233 Group: "example.com",
234 Version: "v1",
235 Kind: "ExampleCRD",
236 },
237 queryParam: QueryParamFieldValidation,
238 primaryError: errors.NewNotFound(schema.GroupResource{}, "OpenAPI V3 endpoint not found"),
239 expectedSupports: true,
240 },
241 "Field validation query param unsupported for missing CRD, secondary verifier": {
242 crds: []schema.GroupKind{
243 {
244 Group: "different.com",
245 Kind: "DifferentCRD",
246 },
247 },
248
249 gvk: schema.GroupVersionKind{
250 Group: "example.com",
251 Version: "v1",
252 Kind: "ExampleCRD",
253 },
254 queryParam: QueryParamFieldValidation,
255 primaryError: errors.NewNotFound(schema.GroupResource{}, "OpenAPI V3 endpoint not found"),
256 expectedSupports: false,
257 },
258 "List GVK is specifically unsupported": {
259 crds: []schema.GroupKind{},
260 gvk: schema.GroupVersionKind{
261 Group: "",
262 Version: "v1",
263 Kind: "List",
264 },
265 queryParam: QueryParamFieldValidation,
266 primaryError: errors.NewNotFound(schema.GroupResource{}, "OpenAPI V3 endpoint not found"),
267 expectedSupports: false,
268 },
269 }
270
271
272 fakeOpenAPIClient := openapitest.NewFakeClient()
273 root := openapi3.NewRoot(fakeOpenAPIClient)
274 for tn, tc := range tests {
275 t.Run(tn, func(t *testing.T) {
276 fakeOpenAPIClient.ForcedErr = tc.primaryError
277 primary := createFakeV3Verifier(tc.crds, root, tc.queryParam)
278 secondary := createFakeLegacyVerifier(tc.crds, &fakeSchema, tc.queryParam)
279 verifier := NewFallbackQueryParamVerifier(primary, secondary)
280 err := verifier.HasSupport(tc.gvk)
281 if tc.expectedSupports && err != nil {
282 t.Errorf("Expected supports, but returned err for GVK (%s)", tc.gvk)
283 } else if !tc.expectedSupports && err == nil {
284 t.Errorf("Expected not supports, but returned no err for GVK (%s)", tc.gvk)
285 }
286 })
287 }
288 }
289
290
291
292 func createFakeV3Verifier(crds []schema.GroupKind, root openapi3.Root, queryParam VerifiableQueryParam) Verifier {
293 return &queryParamVerifierV3{
294 finder: NewCRDFinder(func() ([]schema.GroupKind, error) {
295 return crds, nil
296 }),
297 root: root,
298 queryParam: queryParam,
299 }
300 }
301
302
303
304 func createFakeLegacyVerifier(crds []schema.GroupKind, fakeSchema discovery.OpenAPISchemaInterface, queryParam VerifiableQueryParam) Verifier {
305 return &QueryParamVerifier{
306 finder: NewCRDFinder(func() ([]schema.GroupKind, error) {
307 return crds, nil
308 }),
309 openAPIGetter: fakeSchema,
310 queryParam: queryParam,
311 }
312 }
313
314
315 type failingVerifier struct {
316 name string
317 t *testing.T
318 }
319
320 func (c *failingVerifier) HasSupport(gvk schema.GroupVersionKind) error {
321 c.t.Fatalf("%s verifier should not be called", c.name)
322 return nil
323 }
324
View as plain text