@@ -25,9 +25,11 @@ import (
25
25
apierrors "k8s.io/apimachinery/pkg/api/errors"
26
26
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
27
27
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
28
+ "k8s.io/apimachinery/pkg/runtime/schema"
28
29
"k8s.io/apimachinery/pkg/util/wait"
29
30
"k8s.io/apimachinery/pkg/util/yaml"
30
31
32
+ apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
31
33
apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
32
34
clientschema "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/scheme"
33
35
"k8s.io/apiextensions-apiserver/test/integration/fixtures"
@@ -251,6 +253,180 @@ func TestCustomResourceValidation(t *testing.T) {
251
253
}
252
254
}
253
255
256
+ func TestCustomResourceItemsValidation (t * testing.T ) {
257
+ tearDown , apiExtensionClient , client , err := fixtures .StartDefaultServerWithClients (t )
258
+ if err != nil {
259
+ t .Fatal (err )
260
+ }
261
+ defer tearDown ()
262
+
263
+ // decode CRD manifest
264
+ obj , _ , err := clientschema .Codecs .UniversalDeserializer ().Decode ([]byte (fixtureItemsAndType ), nil , nil )
265
+ if err != nil {
266
+ t .Fatalf ("failed decoding of: %v\n \n %s" , err , fixtureItemsAndType )
267
+ }
268
+ crd := obj .(* apiextensionsv1.CustomResourceDefinition )
269
+
270
+ // create CRDs
271
+ t .Logf ("Creating CRD %s" , crd .Name )
272
+ if _ , err = fixtures .CreateNewV1CustomResourceDefinition (crd , apiExtensionClient , client ); err != nil {
273
+ t .Fatalf ("unexpected create error: %v" , err )
274
+ }
275
+
276
+ // create CR
277
+ gvr := schema.GroupVersionResource {
278
+ Group : crd .Spec .Group ,
279
+ Version : crd .Spec .Versions [0 ].Name ,
280
+ Resource : crd .Spec .Names .Plural ,
281
+ }
282
+ u := unstructured.Unstructured {Object : map [string ]interface {}{
283
+ "apiVersion" : gvr .GroupVersion ().String (),
284
+ "kind" : crd .Spec .Names .Kind ,
285
+ "metadata" : map [string ]interface {}{
286
+ "name" : "foo" ,
287
+ },
288
+ "items-no-type" : map [string ]interface {}{
289
+ "items" : []interface {}{
290
+ map [string ]interface {}{},
291
+ },
292
+ },
293
+ "items-items-no-type" : map [string ]interface {}{
294
+ "items" : []interface {}{
295
+ []interface {}{map [string ]interface {}{}},
296
+ },
297
+ },
298
+ "items-properties-items-no-type" : map [string ]interface {}{
299
+ "items" : []interface {}{
300
+ map [string ]interface {}{
301
+ "items" : []interface {}{
302
+ map [string ]interface {}{},
303
+ },
304
+ },
305
+ },
306
+ },
307
+ "type-array-no-items" : map [string ]interface {}{
308
+ "type" : "array" ,
309
+ },
310
+ "items-and-type" : map [string ]interface {}{
311
+ "items" : []interface {}{map [string ]interface {}{}},
312
+ "type" : "array" ,
313
+ },
314
+ "issue-84880" : map [string ]interface {}{
315
+ "volumes" : []interface {}{
316
+ map [string ]interface {}{
317
+ "downwardAPI" : map [string ]interface {}{
318
+ "items" : []interface {}{
319
+ map [string ]interface {}{
320
+ "path" : "annotations" ,
321
+ },
322
+ },
323
+ },
324
+ },
325
+ },
326
+ },
327
+ }}
328
+ _ , err = client .Resource (gvr ).Create (& u , metav1.CreateOptions {})
329
+ if err != nil {
330
+ t .Fatalf ("unexpected error: %v" , err )
331
+ }
332
+ }
333
+
334
+ const fixtureItemsAndType = `
335
+ apiVersion: apiextensions.k8s.io/v1
336
+ kind: CustomResourceDefinition
337
+ metadata:
338
+ name: foos.tests.example.com
339
+ spec:
340
+ group: tests.example.com
341
+ version: v1beta1
342
+ names:
343
+ plural: foos
344
+ singular: foo
345
+ kind: Foo
346
+ listKind: Foolist
347
+ scope: Cluster
348
+ versions:
349
+ - name: v1beta1
350
+ served: true
351
+ storage: true
352
+ schema:
353
+ openAPIV3Schema:
354
+ type: object
355
+ properties:
356
+ items-no-type:
357
+ type: object
358
+ properties:
359
+ items:
360
+ type: array
361
+ items:
362
+ type: object
363
+ items-items-no-type:
364
+ type: object
365
+ properties:
366
+ items:
367
+ type: array
368
+ items:
369
+ type: array
370
+ items:
371
+ type: object
372
+ items-properties-items-no-type:
373
+ type: object
374
+ properties:
375
+ items:
376
+ type: array
377
+ items:
378
+ type: object
379
+ properties:
380
+ items:
381
+ type: array
382
+ items:
383
+ type: object
384
+ type-array-no-items:
385
+ type: object
386
+ properties:
387
+ type:
388
+ type: string
389
+ items-and-type:
390
+ type: object
391
+ properties:
392
+ type:
393
+ type: string
394
+ items:
395
+ type: array
396
+ items:
397
+ type: object
398
+ default-with-items-and-no-type:
399
+ type: object
400
+ properties:
401
+ type:
402
+ type: string
403
+ items:
404
+ type: array
405
+ items:
406
+ type: object
407
+ default: {"items": []}
408
+ issue-84880:
409
+ type: object
410
+ properties:
411
+ volumes:
412
+ type: array
413
+ items:
414
+ type: object
415
+ properties:
416
+ downwardAPI:
417
+ type: object
418
+ properties:
419
+ items:
420
+ items:
421
+ properties:
422
+ path:
423
+ type: string
424
+ required:
425
+ - path
426
+ type: object
427
+ type: array
428
+ `
429
+
254
430
func TestCustomResourceUpdateValidation (t * testing.T ) {
255
431
tearDown , apiExtensionClient , dynamicClient , err := fixtures .StartDefaultServerWithClients (t )
256
432
if err != nil {
0 commit comments