@@ -28,6 +28,7 @@ import (
28
28
apps "k8s.io/api/apps/v1"
29
29
batch "k8s.io/api/batch/v1"
30
30
v1 "k8s.io/api/core/v1"
31
+ storage "k8s.io/api/storage/v1"
31
32
storagev1beta1 "k8s.io/api/storage/v1beta1"
32
33
apiequality "k8s.io/apimachinery/pkg/api/equality"
33
34
apierrors "k8s.io/apimachinery/pkg/api/errors"
@@ -1349,35 +1350,50 @@ func CreatePod(client clientset.Interface, namespace string, podCount int, podTe
1349
1350
return createError
1350
1351
}
1351
1352
1352
- func CreatePodWithPersistentVolume (client clientset.Interface , namespace string , claimTemplate * v1.PersistentVolumeClaim , factory volumeFactory , podTemplate * v1.Pod , count int ) error {
1353
+ func CreatePodWithPersistentVolume (client clientset.Interface , namespace string , claimTemplate * v1.PersistentVolumeClaim , factory volumeFactory , podTemplate * v1.Pod , count int , bindVolume bool ) error {
1353
1354
var createError error
1354
1355
lock := sync.Mutex {}
1355
1356
createPodFunc := func (i int ) {
1356
1357
pvcName := fmt .Sprintf ("pvc-%d" , i )
1357
-
1358
+ // pvc
1359
+ pvc := claimTemplate .DeepCopy ()
1360
+ pvc .Name = pvcName
1358
1361
// pv
1359
1362
pv := factory (i )
1360
- // bind to "pvc-$i"
1361
- pv .Spec .ClaimRef = & v1.ObjectReference {
1362
- Kind : "PersistentVolumeClaim" ,
1363
- Namespace : namespace ,
1364
- Name : pvcName ,
1365
- APIVersion : "v1" ,
1363
+ // PVs are cluster-wide resources.
1364
+ // Prepend a namespace to make the name globally unique.
1365
+ pv .Name = fmt .Sprintf ("%s-%s" , namespace , pv .Name )
1366
+ if bindVolume {
1367
+ // bind pv to "pvc-$i"
1368
+ pv .Spec .ClaimRef = & v1.ObjectReference {
1369
+ Kind : "PersistentVolumeClaim" ,
1370
+ Namespace : namespace ,
1371
+ Name : pvcName ,
1372
+ APIVersion : "v1" ,
1373
+ }
1374
+ pv .Status .Phase = v1 .VolumeBound
1375
+
1376
+ // bind pvc to "pv-$i"
1377
+ // pvc.Spec.VolumeName = pv.Name
1378
+ pvc .Status .Phase = v1 .ClaimBound
1379
+ } else {
1380
+ pv .Status .Phase = v1 .VolumeAvailable
1366
1381
}
1367
- pv .Status .Phase = v1 .VolumeBound
1368
1382
if err := CreatePersistentVolumeWithRetries (client , pv ); err != nil {
1369
1383
lock .Lock ()
1370
1384
defer lock .Unlock ()
1371
1385
createError = fmt .Errorf ("error creating PV: %s" , err )
1372
1386
return
1373
1387
}
1388
+ // We need to update status separately, as creating persistentvolumes resets status to the default one
1389
+ // (so with Status.Phase will be equal to PersistentVolumePhase).
1390
+ if _ , err := client .CoreV1 ().PersistentVolumes ().UpdateStatus (context .TODO (), pv , metav1.UpdateOptions {}); err != nil {
1391
+ lock .Lock ()
1392
+ defer lock .Unlock ()
1393
+ createError = fmt .Errorf ("error creating PV: %s" , err )
1394
+ return
1395
+ }
1374
1396
1375
- // pvc
1376
- pvc := claimTemplate .DeepCopy ()
1377
- pvc .Name = pvcName
1378
- // bind to "pv-$i"
1379
- pvc .Spec .VolumeName = pv .Name
1380
- pvc .Status .Phase = v1 .ClaimBound
1381
1397
if err := CreatePersistentVolumeClaimWithRetries (client , namespace , pvc ); err != nil {
1382
1398
lock .Lock ()
1383
1399
defer lock .Unlock ()
@@ -1446,9 +1462,50 @@ type volumeFactory func(uniqueID int) *v1.PersistentVolume
1446
1462
1447
1463
func NewCreatePodWithPersistentVolumeStrategy (claimTemplate * v1.PersistentVolumeClaim , factory volumeFactory , podTemplate * v1.Pod ) TestPodCreateStrategy {
1448
1464
return func (client clientset.Interface , namespace string , podCount int ) error {
1449
- return CreatePodWithPersistentVolume (client , namespace , claimTemplate , factory , podTemplate , podCount )
1465
+ return CreatePodWithPersistentVolume (client , namespace , claimTemplate , factory , podTemplate , podCount , true /* bindVolume */ )
1466
+ }
1467
+ }
1468
+
1469
+ func makeUnboundPersistentVolumeClaim (storageClass string ) * v1.PersistentVolumeClaim {
1470
+ return & v1.PersistentVolumeClaim {
1471
+ Spec : v1.PersistentVolumeClaimSpec {
1472
+ AccessModes : []v1.PersistentVolumeAccessMode {v1 .ReadOnlyMany },
1473
+ StorageClassName : & storageClass ,
1474
+ Resources : v1.ResourceRequirements {
1475
+ Requests : v1.ResourceList {
1476
+ v1 .ResourceName (v1 .ResourceStorage ): resource .MustParse ("1Gi" ),
1477
+ },
1478
+ },
1479
+ },
1480
+ }
1481
+ }
1482
+
1483
+ func NewCreatePodWithPersistentVolumeWithFirstConsumerStrategy (factory volumeFactory , podTemplate * v1.Pod ) TestPodCreateStrategy {
1484
+ return func (client clientset.Interface , namespace string , podCount int ) error {
1485
+ volumeBindingMode := storage .VolumeBindingWaitForFirstConsumer
1486
+ storageClass := & storage.StorageClass {
1487
+ ObjectMeta : metav1.ObjectMeta {
1488
+ Name : "storage-class-1" ,
1489
+ },
1490
+ Provisioner : "kubernetes.io/gce-pd" ,
1491
+ VolumeBindingMode : & volumeBindingMode ,
1492
+ }
1493
+ claimTemplate := makeUnboundPersistentVolumeClaim (storageClass .Name )
1494
+
1495
+ if err := CreateStorageClassWithRetries (client , storageClass ); err != nil {
1496
+ return fmt .Errorf ("failed to create storage class: %v" , err )
1497
+ }
1498
+
1499
+ factoryWithStorageClass := func (i int ) * v1.PersistentVolume {
1500
+ pv := factory (i )
1501
+ pv .Spec .StorageClassName = storageClass .Name
1502
+ return pv
1503
+ }
1504
+
1505
+ return CreatePodWithPersistentVolume (client , namespace , claimTemplate , factoryWithStorageClass , podTemplate , podCount , false /* bindVolume */ )
1450
1506
}
1451
1507
}
1508
+
1452
1509
func NewSimpleCreatePodStrategy () TestPodCreateStrategy {
1453
1510
basePod := & v1.Pod {
1454
1511
ObjectMeta : metav1.ObjectMeta {
0 commit comments