@@ -77,6 +77,69 @@ func runTests(admissionReviewVersion string) {
77
77
close (stop )
78
78
})
79
79
80
+ It ("should scaffold a custom defaulter webhook which recovers from panics" , func () {
81
+ By ("creating a controller manager" )
82
+ m , err := manager .New (cfg , manager.Options {})
83
+ ExpectWithOffset (1 , err ).NotTo (HaveOccurred ())
84
+
85
+ By ("registering the type in the Scheme" )
86
+ builder := scheme.Builder {GroupVersion : testDefaulterGVK .GroupVersion ()}
87
+ builder .Register (& TestDefaulter {}, & TestDefaulterList {})
88
+ err = builder .AddToScheme (m .GetScheme ())
89
+ ExpectWithOffset (1 , err ).NotTo (HaveOccurred ())
90
+
91
+ err = WebhookManagedBy (m ).
92
+ For (& TestDefaulter {}).
93
+ WithDefaulter (& TestCustomDefaulter {}).
94
+ RecoverPanic (true ).
95
+ // RecoverPanic defaults to true.
96
+ Complete ()
97
+ ExpectWithOffset (1 , err ).NotTo (HaveOccurred ())
98
+ svr := m .GetWebhookServer ()
99
+ ExpectWithOffset (1 , svr ).NotTo (BeNil ())
100
+
101
+ reader := strings .NewReader (admissionReviewGV + admissionReviewVersion + `",
102
+ "request":{
103
+ "uid":"07e52e8d-4513-11e9-a716-42010a800270",
104
+ "kind":{
105
+ "group":"",
106
+ "version":"v1",
107
+ "kind":"TestDefaulter"
108
+ },
109
+ "resource":{
110
+ "group":"",
111
+ "version":"v1",
112
+ "resource":"testdefaulter"
113
+ },
114
+ "namespace":"default",
115
+ "operation":"CREATE",
116
+ "object":{
117
+ "panic":true
118
+ },
119
+ "oldObject":null
120
+ }
121
+ }` )
122
+
123
+ ctx , cancel := context .WithCancel (context .Background ())
124
+ cancel ()
125
+ err = svr .Start (ctx )
126
+ if err != nil && ! os .IsNotExist (err ) {
127
+ ExpectWithOffset (1 , err ).NotTo (HaveOccurred ())
128
+ }
129
+
130
+ By ("sending a request to a mutating webhook path" )
131
+ path := generateMutatePath (testDefaulterGVK )
132
+ req := httptest .NewRequest ("POST" , svcBaseAddr + path , reader )
133
+ req .Header .Add ("Content-Type" , "application/json" )
134
+ w := httptest .NewRecorder ()
135
+ svr .WebhookMux ().ServeHTTP (w , req )
136
+ ExpectWithOffset (1 , w .Code ).To (Equal (http .StatusOK ))
137
+ By ("sanity checking the response contains reasonable fields" )
138
+ ExpectWithOffset (1 , w .Body ).To (ContainSubstring (`"allowed":false` ))
139
+ ExpectWithOffset (1 , w .Body ).To (ContainSubstring (`"code":500` ))
140
+ ExpectWithOffset (1 , w .Body ).To (ContainSubstring (`"message":"panic: fake panic test [recovered]` ))
141
+ })
142
+
80
143
It ("should scaffold a defaulting webhook with a custom defaulter" , func () {
81
144
By ("creating a controller manager" )
82
145
m , err := manager .New (cfg , manager.Options {})
@@ -230,6 +293,74 @@ func runTests(admissionReviewVersion string) {
230
293
EventuallyWithOffset (1 , logBuffer ).Should (gbytes .Say (`"msg":"Validating object","object":{"name":"foo","namespace":"default"},"namespace":"default","name":"foo","resource":{"group":"foo.test.org","version":"v1","resource":"testvalidator"},"user":"","requestID":"07e52e8d-4513-11e9-a716-42010a800270"` ))
231
294
})
232
295
296
+ It ("should scaffold a customValidator webhook which recovers from panics" , func () {
297
+ By ("creating a controller manager" )
298
+ m , err := manager .New (cfg , manager.Options {})
299
+
300
+ ExpectWithOffset (1 , err ).NotTo (HaveOccurred ())
301
+
302
+ By ("registering the type in the Scheme" )
303
+ builder := scheme.Builder {GroupVersion : testValidatorGVK .GroupVersion ()}
304
+ builder .Register (& TestValidator {}, & TestValidatorList {})
305
+ err = builder .AddToScheme (m .GetScheme ())
306
+ ExpectWithOffset (1 , err ).NotTo (HaveOccurred ())
307
+
308
+ err = WebhookManagedBy (m ).
309
+ For (& TestValidator {Panic : true }).
310
+ WithValidator (& TestCustomValidator {}).
311
+ RecoverPanic (true ).
312
+ Complete ()
313
+ ExpectWithOffset (1 , err ).NotTo (HaveOccurred ())
314
+ svr := m .GetWebhookServer ()
315
+ ExpectWithOffset (1 , svr ).NotTo (BeNil ())
316
+
317
+ reader := strings .NewReader (admissionReviewGV + admissionReviewVersion + `",
318
+ "request":{
319
+ "uid":"07e52e8d-4513-11e9-a716-42010a800270",
320
+ "kind":{
321
+ "group":"",
322
+ "version":"v1",
323
+ "kind":"TestValidator"
324
+ },
325
+
326
+ "resource":{
327
+ "group":"",
328
+
329
+ "version":"v1",
330
+ "resource":"testvalidator"
331
+ },
332
+ "namespace":"default",
333
+ "operation":"CREATE",
334
+
335
+ "object":{
336
+ "replica":2,
337
+ "panic":true
338
+ }
339
+ }
340
+ }` )
341
+
342
+ ctx , cancel := context .WithCancel (context .Background ())
343
+ cancel ()
344
+ err = svr .Start (ctx )
345
+ if err != nil && ! os .IsNotExist (err ) {
346
+ ExpectWithOffset (1 , err ).NotTo (HaveOccurred ())
347
+ }
348
+
349
+ By ("sending a request to a validating webhook path" )
350
+ path := generateValidatePath (testValidatorGVK )
351
+ _ , err = reader .Seek (0 , 0 )
352
+ ExpectWithOffset (1 , err ).NotTo (HaveOccurred ())
353
+ req := httptest .NewRequest ("POST" , svcBaseAddr + path , reader )
354
+ req .Header .Add ("Content-Type" , "application/json" )
355
+ w := httptest .NewRecorder ()
356
+ svr .WebhookMux ().ServeHTTP (w , req )
357
+ ExpectWithOffset (1 , w .Code ).To (Equal (http .StatusOK ))
358
+ By ("sanity checking the response contains reasonable field" )
359
+ ExpectWithOffset (1 , w .Body ).To (ContainSubstring (`"allowed":false` ))
360
+ ExpectWithOffset (1 , w .Body ).To (ContainSubstring (`"code":500` ))
361
+ ExpectWithOffset (1 , w .Body ).To (ContainSubstring (`"message":"panic: fake panic test [recovered]` ))
362
+ })
363
+
233
364
It ("should send an error when trying to register a webhook with more than one For" , func () {
234
365
By ("creating a controller manager" )
235
366
m , err := manager .New (cfg , manager.Options {})
@@ -247,6 +378,102 @@ func runTests(admissionReviewVersion string) {
247
378
Complete ()
248
379
Expect (err ).To (HaveOccurred ())
249
380
})
381
+
382
+ It ("should scaffold a custom validator webhook if the type implements the CustomValidator interface to validate deletes" , func () {
383
+ By ("creating a controller manager" )
384
+ ctx , cancel := context .WithCancel (context .Background ())
385
+
386
+ m , err := manager .New (cfg , manager.Options {})
387
+ ExpectWithOffset (1 , err ).NotTo (HaveOccurred ())
388
+
389
+ By ("registering the type in the Scheme" )
390
+ builder := scheme.Builder {GroupVersion : testValidatorGVK .GroupVersion ()}
391
+ builder .Register (& TestValidator {}, & TestValidatorList {})
392
+ err = builder .AddToScheme (m .GetScheme ())
393
+ ExpectWithOffset (1 , err ).NotTo (HaveOccurred ())
394
+
395
+ err = WebhookManagedBy (m ).
396
+ For (& TestValidator {}).
397
+ WithValidator (& TestCustomValidator {}).
398
+ Complete ()
399
+ ExpectWithOffset (1 , err ).NotTo (HaveOccurred ())
400
+ svr := m .GetWebhookServer ()
401
+ ExpectWithOffset (1 , svr ).NotTo (BeNil ())
402
+
403
+ reader := strings .NewReader (admissionReviewGV + admissionReviewVersion + `",
404
+ "request":{
405
+ "uid":"07e52e8d-4513-11e9-a716-42010a800270",
406
+ "kind":{
407
+ "group":"",
408
+ "version":"v1",
409
+ "kind":"TestValidator"
410
+
411
+ },
412
+ "resource":{
413
+ "group":"",
414
+ "version":"v1",
415
+ "resource":"testvalidator"
416
+ },
417
+ "namespace":"default",
418
+ "operation":"DELETE",
419
+ "object":null,
420
+ "oldObject":{
421
+ "replica":1
422
+ }
423
+ }
424
+ }` )
425
+
426
+ cancel ()
427
+ err = svr .Start (ctx )
428
+ if err != nil && ! os .IsNotExist (err ) {
429
+ ExpectWithOffset (1 , err ).NotTo (HaveOccurred ())
430
+ }
431
+
432
+ By ("sending a request to a validating webhook path to check for failed delete" )
433
+ path := generateValidatePath (testValidatorGVK )
434
+ req := httptest .NewRequest ("POST" , svcBaseAddr + path , reader )
435
+ req .Header .Add ("Content-Type" , "application/json" )
436
+ w := httptest .NewRecorder ()
437
+ svr .WebhookMux ().ServeHTTP (w , req )
438
+ ExpectWithOffset (1 , w .Code ).To (Equal (http .StatusOK ))
439
+ By ("sanity checking the response contains reasonable field" )
440
+ ExpectWithOffset (1 , w .Body ).To (ContainSubstring (`"allowed":false` ))
441
+ ExpectWithOffset (1 , w .Body ).To (ContainSubstring (`"code":403` ))
442
+
443
+ reader = strings .NewReader (admissionReviewGV + admissionReviewVersion + `",
444
+ "request":{
445
+ "uid":"07e52e8d-4513-11e9-a716-42010a800270",
446
+
447
+ "kind":{
448
+ "group":"",
449
+ "version":"v1",
450
+ "kind":"TestValidator"
451
+ },
452
+ "resource":{
453
+
454
+ "group":"",
455
+ "version":"v1",
456
+ "resource":"testvalidator"
457
+ },
458
+ "namespace":"default",
459
+ "operation":"DELETE",
460
+ "object":null,
461
+ "oldObject":{
462
+ "replica":0
463
+ }
464
+ }
465
+ }` )
466
+ By ("sending a request to a validating webhook path with correct request" )
467
+ path = generateValidatePath (testValidatorGVK )
468
+ req = httptest .NewRequest ("POST" , svcBaseAddr + path , reader )
469
+ req .Header .Add ("Content-Type" , "application/json" )
470
+ w = httptest .NewRecorder ()
471
+ svr .WebhookMux ().ServeHTTP (w , req )
472
+ ExpectWithOffset (1 , w .Code ).To (Equal (http .StatusOK ))
473
+ By ("sanity checking the response contains reasonable field" )
474
+ ExpectWithOffset (1 , w .Body ).To (ContainSubstring (`"allowed":true` ))
475
+ ExpectWithOffset (1 , w .Body ).To (ContainSubstring (`"code":200` ))
476
+ })
250
477
}
251
478
252
479
// TestDefaulter.
@@ -431,9 +658,13 @@ func (*TestCustomDefaulter) Default(ctx context.Context, obj runtime.Object) err
431
658
}
432
659
433
660
d := obj .(* TestDefaulter ) //nolint:ifshort
661
+
434
662
if d .Replica < 2 {
435
663
d .Replica = 2
436
664
}
665
+ if d .Panic {
666
+ panic ("fake panic test" )
667
+ }
437
668
return nil
438
669
}
439
670
@@ -454,6 +685,9 @@ func (*TestCustomValidator) ValidateCreate(ctx context.Context, obj runtime.Obje
454
685
}
455
686
456
687
v := obj .(* TestValidator ) //nolint:ifshort
688
+ if v .Panic {
689
+ panic ("fake panic test" )
690
+ }
457
691
if v .Replica < 0 {
458
692
return nil , errors .New ("number of replica should be greater than or equal to 0" )
459
693
}
0 commit comments