@@ -134,6 +134,72 @@ func runTests(admissionReviewVersion string) {
134
134
ExpectWithOffset (1 , w .Code ).To (Equal (http .StatusNotFound ))
135
135
})
136
136
137
+ It ("should scaffold a defaulting webhook which recovers from panics" , func () {
138
+ By ("creating a controller manager" )
139
+ m , err := manager .New (cfg , manager.Options {})
140
+ ExpectWithOffset (1 , err ).NotTo (HaveOccurred ())
141
+
142
+ By ("registering the type in the Scheme" )
143
+ builder := scheme.Builder {GroupVersion : testDefaulterGVK .GroupVersion ()}
144
+ builder .Register (& TestDefaulter {}, & TestDefaulterList {})
145
+ err = builder .AddToScheme (m .GetScheme ())
146
+ ExpectWithOffset (1 , err ).NotTo (HaveOccurred ())
147
+
148
+ err = WebhookManagedBy (m ).
149
+ For (& TestDefaulter {Panic : true }).
150
+ RecoverPanic ().
151
+ Complete ()
152
+ ExpectWithOffset (1 , err ).NotTo (HaveOccurred ())
153
+ svr := m .GetWebhookServer ()
154
+ ExpectWithOffset (1 , svr ).NotTo (BeNil ())
155
+
156
+ reader := strings .NewReader (`{
157
+ "kind":"AdmissionReview",
158
+ "apiVersion":"admission.k8s.io/` + admissionReviewVersion + `",
159
+ "request":{
160
+ "uid":"07e52e8d-4513-11e9-a716-42010a800270",
161
+ "kind":{
162
+ "group":"",
163
+ "version":"v1",
164
+ "kind":"TestDefaulter"
165
+ },
166
+ "resource":{
167
+ "group":"",
168
+ "version":"v1",
169
+ "resource":"testdefaulter"
170
+ },
171
+ "namespace":"default",
172
+ "operation":"CREATE",
173
+ "object":{
174
+ "replica":1,
175
+ "panic":true
176
+ },
177
+ "oldObject":null
178
+ }
179
+ }` )
180
+
181
+ ctx , cancel := context .WithCancel (context .Background ())
182
+ cancel ()
183
+ // TODO: we may want to improve it to make it be able to inject dependencies,
184
+ // but not always try to load certs and return not found error.
185
+ err = svr .Start (ctx )
186
+ if err != nil && ! os .IsNotExist (err ) {
187
+ ExpectWithOffset (1 , err ).NotTo (HaveOccurred ())
188
+ }
189
+
190
+ By ("sending a request to a mutating webhook path" )
191
+ path := generateMutatePath (testDefaulterGVK )
192
+ req := httptest .NewRequest ("POST" , "http://svc-name.svc-ns.svc" + path , reader )
193
+ req .Header .Add ("Content-Type" , "application/json" )
194
+ w := httptest .NewRecorder ()
195
+ svr .WebhookMux .ServeHTTP (w , req )
196
+ ExpectWithOffset (1 , w .Code ).To (Equal (http .StatusOK ))
197
+ By ("sanity checking the response contains reasonable fields" )
198
+ ExpectWithOffset (1 , w .Body ).To (ContainSubstring (`"allowed":false` ))
199
+ ExpectWithOffset (1 , w .Body ).To (ContainSubstring (`"code":500` ))
200
+ ExpectWithOffset (1 , w .Body ).To (ContainSubstring (`"message":"panic: injected panic [recovered]` ))
201
+ })
202
+
137
203
It ("should scaffold a defaulting webhook with a custom defaulter" , func () {
138
204
By ("creating a controller manager" )
139
205
m , err := manager .New (cfg , manager.Options {})
@@ -284,6 +350,73 @@ func runTests(admissionReviewVersion string) {
284
350
ExpectWithOffset (1 , w .Body ).To (ContainSubstring (`"code":403` ))
285
351
})
286
352
353
+ It ("should scaffold a validating webhook which recovers from panics" , func () {
354
+ By ("creating a controller manager" )
355
+ m , err := manager .New (cfg , manager.Options {})
356
+ ExpectWithOffset (1 , err ).NotTo (HaveOccurred ())
357
+
358
+ By ("registering the type in the Scheme" )
359
+ builder := scheme.Builder {GroupVersion : testValidatorGVK .GroupVersion ()}
360
+ builder .Register (& TestValidator {}, & TestValidatorList {})
361
+ err = builder .AddToScheme (m .GetScheme ())
362
+ ExpectWithOffset (1 , err ).NotTo (HaveOccurred ())
363
+
364
+ err = WebhookManagedBy (m ).
365
+ For (& TestValidator {Panic : true }).
366
+ RecoverPanic ().
367
+ Complete ()
368
+ ExpectWithOffset (1 , err ).NotTo (HaveOccurred ())
369
+ svr := m .GetWebhookServer ()
370
+ ExpectWithOffset (1 , svr ).NotTo (BeNil ())
371
+
372
+ reader := strings .NewReader (`{
373
+ "kind":"AdmissionReview",
374
+ "apiVersion":"admission.k8s.io/` + admissionReviewVersion + `",
375
+ "request":{
376
+ "uid":"07e52e8d-4513-11e9-a716-42010a800270",
377
+ "kind":{
378
+ "group":"",
379
+ "version":"v1",
380
+ "kind":"TestValidator"
381
+ },
382
+ "resource":{
383
+ "group":"",
384
+ "version":"v1",
385
+ "resource":"testvalidator"
386
+ },
387
+ "namespace":"default",
388
+ "operation":"CREATE",
389
+ "object":{
390
+ "replica":2,
391
+ "panic":true
392
+ }
393
+ }
394
+ }` )
395
+
396
+ ctx , cancel := context .WithCancel (context .Background ())
397
+ cancel ()
398
+ // TODO: we may want to improve it to make it be able to inject dependencies,
399
+ // but not always try to load certs and return not found error.
400
+ err = svr .Start (ctx )
401
+ if err != nil && ! os .IsNotExist (err ) {
402
+ ExpectWithOffset (1 , err ).NotTo (HaveOccurred ())
403
+ }
404
+
405
+ By ("sending a request to a validating webhook path" )
406
+ path := generateValidatePath (testValidatorGVK )
407
+ _ , err = reader .Seek (0 , 0 )
408
+ ExpectWithOffset (1 , err ).NotTo (HaveOccurred ())
409
+ req := httptest .NewRequest ("POST" , "http://svc-name.svc-ns.svc" + path , reader )
410
+ req .Header .Add ("Content-Type" , "application/json" )
411
+ w := httptest .NewRecorder ()
412
+ svr .WebhookMux .ServeHTTP (w , req )
413
+ ExpectWithOffset (1 , w .Code ).To (Equal (http .StatusOK ))
414
+ By ("sanity checking the response contains reasonable field" )
415
+ ExpectWithOffset (1 , w .Body ).To (ContainSubstring (`"allowed":false` ))
416
+ ExpectWithOffset (1 , w .Body ).To (ContainSubstring (`"code":500` ))
417
+ ExpectWithOffset (1 , w .Body ).To (ContainSubstring (`"message":"panic: injected panic [recovered]` ))
418
+ })
419
+
287
420
It ("should scaffold a validating webhook with a custom validator" , func () {
288
421
By ("creating a controller manager" )
289
422
m , err := manager .New (cfg , manager.Options {})
@@ -540,7 +673,8 @@ func runTests(admissionReviewVersion string) {
540
673
var _ runtime.Object = & TestDefaulter {}
541
674
542
675
type TestDefaulter struct {
543
- Replica int `json:"replica,omitempty"`
676
+ Replica int `json:"replica,omitempty"`
677
+ Panic bool `json:"panic,omitempty"`
544
678
}
545
679
546
680
var testDefaulterGVK = schema.GroupVersionKind {Group : "foo.test.org" , Version : "v1" , Kind : "TestDefaulter" }
@@ -566,6 +700,9 @@ func (*TestDefaulterList) GetObjectKind() schema.ObjectKind { return nil }
566
700
func (* TestDefaulterList ) DeepCopyObject () runtime.Object { return nil }
567
701
568
702
func (d * TestDefaulter ) Default () {
703
+ if d .Panic {
704
+ panic ("injected panic" )
705
+ }
569
706
if d .Replica < 2 {
570
707
d .Replica = 2
571
708
}
@@ -575,7 +712,8 @@ func (d *TestDefaulter) Default() {
575
712
var _ runtime.Object = & TestValidator {}
576
713
577
714
type TestValidator struct {
578
- Replica int `json:"replica,omitempty"`
715
+ Replica int `json:"replica,omitempty"`
716
+ Panic bool `json:"panic,omitempty"`
579
717
}
580
718
581
719
var testValidatorGVK = schema.GroupVersionKind {Group : "foo.test.org" , Version : "v1" , Kind : "TestValidator" }
@@ -603,13 +741,19 @@ func (*TestValidatorList) DeepCopyObject() runtime.Object { return nil }
603
741
var _ admission.Validator = & TestValidator {}
604
742
605
743
func (v * TestValidator ) ValidateCreate () error {
744
+ if v .Panic {
745
+ panic ("injected panic" )
746
+ }
606
747
if v .Replica < 0 {
607
748
return errors .New ("number of replica should be greater than or equal to 0" )
608
749
}
609
750
return nil
610
751
}
611
752
612
753
func (v * TestValidator ) ValidateUpdate (old runtime.Object ) error {
754
+ if v .Panic {
755
+ panic ("injected panic" )
756
+ }
613
757
if v .Replica < 0 {
614
758
return errors .New ("number of replica should be greater than or equal to 0" )
615
759
}
@@ -622,6 +766,9 @@ func (v *TestValidator) ValidateUpdate(old runtime.Object) error {
622
766
}
623
767
624
768
func (v * TestValidator ) ValidateDelete () error {
769
+ if v .Panic {
770
+ panic ("injected panic" )
771
+ }
625
772
if v .Replica > 0 {
626
773
return errors .New ("number of replica should be less than or equal to 0 to delete" )
627
774
}
0 commit comments