@@ -18,13 +18,15 @@ package volumeclaim
18
18
19
19
import (
20
20
"context"
21
+ "errors"
21
22
"fmt"
23
+ "strings"
22
24
"testing"
23
25
24
26
v1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1"
25
27
"go.uber.org/zap"
26
28
corev1 "k8s.io/api/core/v1"
27
- "k8s.io/apimachinery/pkg/api/errors"
29
+ apierrors "k8s.io/apimachinery/pkg/api/errors"
28
30
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
29
31
"k8s.io/apimachinery/pkg/runtime"
30
32
"k8s.io/apimachinery/pkg/runtime/schema"
@@ -207,7 +209,7 @@ func TestCreateExistPersistentVolumeClaims(t *testing.T) {
207
209
fn := func (action client_go_testing.Action ) (bool , runtime.Object , error ) {
208
210
switch action := action .(type ) {
209
211
case client_go_testing.GetActionImpl :
210
- return true , nil , errors .NewNotFound (schema.GroupResource {}, action .Name )
212
+ return true , nil , apierrors .NewNotFound (schema.GroupResource {}, action .Name )
211
213
default :
212
214
return false , nil , fmt .Errorf ("no reaction implemented for %s" , action )
213
215
}
@@ -295,3 +297,150 @@ func TestPurgeFinalizerAndDeletePVCForWorkspace(t *testing.T) {
295
297
t .Errorf ("pvc %s kubernetes.io/pvc-protection finalizer is not removed properly" , pvcName )
296
298
}
297
299
}
300
+
301
+ // TestCreatePVCFromVolumeClaimTemplate_GetError tests error handling when getting existing PVC fails
302
+ func TestCreatePVCFromVolumeClaimTemplate_GetError (t * testing.T ) {
303
+ ownerRef := metav1.OwnerReference {UID : types .UID ("test-owner" )}
304
+ namespace := "test-ns"
305
+
306
+ wb := v1.WorkspaceBinding {
307
+ Name : "test-workspace" ,
308
+ VolumeClaimTemplate : & corev1.PersistentVolumeClaim {
309
+ ObjectMeta : metav1.ObjectMeta {Name : "test-claim" },
310
+ Spec : corev1.PersistentVolumeClaimSpec {},
311
+ },
312
+ }
313
+
314
+ fakekubeclient := fakek8s .NewSimpleClientset ()
315
+ pvcHandler := defaultPVCHandler {fakekubeclient , zap .NewExample ().Sugar ()}
316
+
317
+ // Mock Get to return an error that's not NotFound
318
+ fakekubeclient .Fake .PrependReactor ("get" , "persistentvolumeclaims" ,
319
+ func (action client_go_testing.Action ) (bool , runtime.Object , error ) {
320
+ return true , nil , apierrors .NewInternalError (errors .New ("internal server error" ))
321
+ })
322
+
323
+ err := pvcHandler .CreatePVCFromVolumeClaimTemplate (t .Context (), wb , ownerRef , namespace )
324
+
325
+ if err == nil {
326
+ t .Fatal ("Expected error when Get fails with error" )
327
+ }
328
+
329
+ if ! strings .Contains (err .Error (), "failed to retrieve PVC" ) {
330
+ t .Errorf ("Expected error message about failed to retrieve PVC, got: %v" , err )
331
+ }
332
+ }
333
+
334
+ // TestCreatePVCFromVolumeClaimTemplate_CreateRetryableError tests retryable error handling
335
+ func TestCreatePVCFromVolumeClaimTemplate_CreateRetryableError (t * testing.T ) {
336
+ ownerRef := metav1.OwnerReference {UID : types .UID ("test-owner" )}
337
+ namespace := "test-ns"
338
+
339
+ wb := v1.WorkspaceBinding {
340
+ Name : "test-workspace" ,
341
+ VolumeClaimTemplate : & corev1.PersistentVolumeClaim {
342
+ ObjectMeta : metav1.ObjectMeta {Name : "test-claim" },
343
+ Spec : corev1.PersistentVolumeClaimSpec {},
344
+ },
345
+ }
346
+
347
+ fakekubeclient := fakek8s .NewSimpleClientset ()
348
+ pvcHandler := defaultPVCHandler {fakekubeclient , zap .NewExample ().Sugar ()}
349
+
350
+ // Mock Get to return NotFound, then Create to return quota exceeded error
351
+ fakekubeclient .Fake .PrependReactor ("get" , "persistentvolumeclaims" ,
352
+ func (action client_go_testing.Action ) (bool , runtime.Object , error ) {
353
+ return true , nil , apierrors .NewNotFound (schema.GroupResource {}, "test-claim" )
354
+ })
355
+
356
+ fakekubeclient .Fake .PrependReactor ("create" , "persistentvolumeclaims" ,
357
+ func (action client_go_testing.Action ) (bool , runtime.Object , error ) {
358
+ return true , nil , apierrors .NewForbidden (schema.GroupResource {}, "test-claim" , errors .New ("foo exceeded quota" ))
359
+ })
360
+
361
+ err := pvcHandler .CreatePVCFromVolumeClaimTemplate (t .Context (), wb , ownerRef , namespace )
362
+
363
+ if err == nil {
364
+ t .Fatal ("Expected retryable error" )
365
+ }
366
+
367
+ if ! strings .Contains (err .Error (), ErrPvcCreationFailedRetryable .Error ()) {
368
+ t .Errorf ("Expected retryable error, got: %v" , err )
369
+ }
370
+ }
371
+
372
+ // TestCreatePVCFromVolumeClaimTemplate_CreateNonRetryableError tests non-retryable error handling
373
+ func TestCreatePVCFromVolumeClaimTemplate_CreateNonRetryableError (t * testing.T ) {
374
+ ownerRef := metav1.OwnerReference {UID : types .UID ("test-owner" )}
375
+ namespace := "test-ns"
376
+
377
+ wb := v1.WorkspaceBinding {
378
+ Name : "test-workspace" ,
379
+ VolumeClaimTemplate : & corev1.PersistentVolumeClaim {
380
+ ObjectMeta : metav1.ObjectMeta {Name : "test-claim" },
381
+ Spec : corev1.PersistentVolumeClaimSpec {},
382
+ },
383
+ }
384
+
385
+ fakekubeclient := fakek8s .NewSimpleClientset ()
386
+ pvcHandler := defaultPVCHandler {fakekubeclient , zap .NewExample ().Sugar ()}
387
+
388
+ // Mock Get to return NotFound, then Create to return non-retryable error
389
+ fakekubeclient .Fake .PrependReactor ("get" , "persistentvolumeclaims" ,
390
+ func (action client_go_testing.Action ) (bool , runtime.Object , error ) {
391
+ return true , nil , apierrors .NewNotFound (schema.GroupResource {}, "test-claim" )
392
+ })
393
+
394
+ fakekubeclient .Fake .PrependReactor ("create" , "persistentvolumeclaims" ,
395
+ func (action client_go_testing.Action ) (bool , runtime.Object , error ) {
396
+ return true , nil , apierrors .NewInternalError (errors .New ("internal server error" ))
397
+ })
398
+
399
+ err := pvcHandler .CreatePVCFromVolumeClaimTemplate (t .Context (), wb , ownerRef , namespace )
400
+
401
+ if err == nil {
402
+ t .Fatal ("Expected non-retryable error" )
403
+ }
404
+
405
+ if ! strings .Contains (err .Error (), ErrPvcCreationFailed .Error ()) {
406
+ t .Errorf ("Expected non-retryable error, got: %v" , err )
407
+ }
408
+ }
409
+
410
+ // TestCreatePVCFromVolumeClaimTemplate_ConflictError tests conflict error handling (retryable)
411
+ func TestCreatePVCFromVolumeClaimTemplate_ConflictError (t * testing.T ) {
412
+ ownerRef := metav1.OwnerReference {UID : types .UID ("test-owner" )}
413
+ namespace := "test-ns"
414
+
415
+ wb := v1.WorkspaceBinding {
416
+ Name : "test-workspace" ,
417
+ VolumeClaimTemplate : & corev1.PersistentVolumeClaim {
418
+ ObjectMeta : metav1.ObjectMeta {Name : "test-claim" },
419
+ Spec : corev1.PersistentVolumeClaimSpec {},
420
+ },
421
+ }
422
+
423
+ fakekubeclient := fakek8s .NewSimpleClientset ()
424
+ pvcHandler := defaultPVCHandler {fakekubeclient , zap .NewExample ().Sugar ()}
425
+
426
+ // Mock Get to return NotFound, then Create to return conflict error
427
+ fakekubeclient .Fake .PrependReactor ("get" , "persistentvolumeclaims" ,
428
+ func (action client_go_testing.Action ) (bool , runtime.Object , error ) {
429
+ return true , nil , apierrors .NewNotFound (schema.GroupResource {}, "test-claim" )
430
+ })
431
+
432
+ fakekubeclient .Fake .PrependReactor ("create" , "persistentvolumeclaims" ,
433
+ func (action client_go_testing.Action ) (bool , runtime.Object , error ) {
434
+ return true , nil , apierrors .NewConflict (schema.GroupResource {}, "test-claim" , errors .New ("conflict" ))
435
+ })
436
+
437
+ err := pvcHandler .CreatePVCFromVolumeClaimTemplate (t .Context (), wb , ownerRef , namespace )
438
+
439
+ if err == nil {
440
+ t .Fatal ("Expected conflict error (retryable)" )
441
+ }
442
+
443
+ if ! strings .Contains (err .Error (), ErrPvcCreationFailedRetryable .Error ()) {
444
+ t .Errorf ("Expected retryable conflict error, got: %v" , err )
445
+ }
446
+ }
0 commit comments