@@ -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 {})
@@ -542,7 +675,8 @@ var _ runtime.Object = &TestDefaulter{}
542
675
const testDefaulterKind = "TestDefaulter"
543
676
544
677
type TestDefaulter struct {
545
- Replica int `json:"replica,omitempty"`
678
+ Replica int `json:"replica,omitempty"`
679
+ Panic bool `json:"panic,omitempty"`
546
680
}
547
681
548
682
var testDefaulterGVK = schema.GroupVersionKind {Group : "foo.test.org" , Version : "v1" , Kind : testDefaulterKind }
@@ -568,6 +702,9 @@ func (*TestDefaulterList) GetObjectKind() schema.ObjectKind { return nil }
568
702
func (* TestDefaulterList ) DeepCopyObject () runtime.Object { return nil }
569
703
570
704
func (d * TestDefaulter ) Default () {
705
+ if d .Panic {
706
+ panic ("injected panic" )
707
+ }
571
708
if d .Replica < 2 {
572
709
d .Replica = 2
573
710
}
@@ -579,7 +716,8 @@ var _ runtime.Object = &TestValidator{}
579
716
const testValidatorKind = "TestValidator"
580
717
581
718
type TestValidator struct {
582
- Replica int `json:"replica,omitempty"`
719
+ Replica int `json:"replica,omitempty"`
720
+ Panic bool `json:"panic,omitempty"`
583
721
}
584
722
585
723
var testValidatorGVK = schema.GroupVersionKind {Group : "foo.test.org" , Version : "v1" , Kind : testValidatorKind }
@@ -607,13 +745,19 @@ func (*TestValidatorList) DeepCopyObject() runtime.Object { return nil }
607
745
var _ admission.Validator = & TestValidator {}
608
746
609
747
func (v * TestValidator ) ValidateCreate () error {
748
+ if v .Panic {
749
+ panic ("injected panic" )
750
+ }
610
751
if v .Replica < 0 {
611
752
return errors .New ("number of replica should be greater than or equal to 0" )
612
753
}
613
754
return nil
614
755
}
615
756
616
757
func (v * TestValidator ) ValidateUpdate (old runtime.Object ) error {
758
+ if v .Panic {
759
+ panic ("injected panic" )
760
+ }
617
761
if v .Replica < 0 {
618
762
return errors .New ("number of replica should be greater than or equal to 0" )
619
763
}
@@ -626,6 +770,9 @@ func (v *TestValidator) ValidateUpdate(old runtime.Object) error {
626
770
}
627
771
628
772
func (v * TestValidator ) ValidateDelete () error {
773
+ if v .Panic {
774
+ panic ("injected panic" )
775
+ }
629
776
if v .Replica > 0 {
630
777
return errors .New ("number of replica should be less than or equal to 0 to delete" )
631
778
}
0 commit comments