@@ -34,6 +34,7 @@ const (
34
34
csiStorageClassName = "hostpath-csi"
35
35
legacyStorageClassName = "hostpath-provisioner"
36
36
legacyStorageClassNameImmediate = "hostpath-provisioner-immediate"
37
+ testMountName = "testmount"
37
38
)
38
39
func TestCreatePVCOnNode1 (t * testing.T ) {
39
40
RegisterTestingT (t )
@@ -210,6 +211,55 @@ func TestPVCSize(t *testing.T) {
210
211
211
212
}
212
213
214
+ func TestFsGroup (t * testing.T ) {
215
+ RegisterTestingT (t )
216
+ tearDown , ns , k8sClient := setupTestCaseNs (t )
217
+ defer tearDown (t )
218
+ annotations := make (map [string ]string )
219
+
220
+ pvc := createPVCDef (ns .Name , legacyStorageClassName , annotations )
221
+ defer func () {
222
+ // Cleanup
223
+ if pvc != nil {
224
+ t .Logf ("Removing PVC: %s" , pvc .Name )
225
+ err := k8sClient .CoreV1 ().PersistentVolumeClaims (ns .Name ).Delete (context .TODO (), pvc .Name , metav1.DeleteOptions {})
226
+ Expect (err ).ToNot (HaveOccurred ())
227
+ }
228
+ }()
229
+ t .Logf ("Creating PVC: %s" , pvc .Name )
230
+ pvc , err := k8sClient .CoreV1 ().PersistentVolumeClaims (ns .Name ).Create (context .TODO (), pvc , metav1.CreateOptions {})
231
+ Expect (err ).ToNot (HaveOccurred ())
232
+
233
+ Eventually (func () corev1.PersistentVolumeClaimPhase {
234
+ pvc , err = k8sClient .CoreV1 ().PersistentVolumeClaims (ns .Name ).Get (context .TODO (), pvc .Name , metav1.GetOptions {})
235
+ Expect (err ).ToNot (HaveOccurred ())
236
+ return pvc .Status .Phase
237
+ }, 90 * time .Second , 1 * time .Second ).Should (BeEquivalentTo (corev1 .ClaimPending ))
238
+
239
+ Expect (pvc .Spec .VolumeName ).To (BeEmpty ())
240
+
241
+ touchPod := createPodUsingPVCWithFsGroup (ns .Name , "touch-pod" , pvc , "touch /data/test.txt" , 2000 , annotations )
242
+ touchPod , err = k8sClient .CoreV1 ().Pods (ns .Name ).Create (context .TODO (), touchPod , metav1.CreateOptions {})
243
+ Expect (err ).ToNot (HaveOccurred ())
244
+ Eventually (func () bool {
245
+ touchPod , err = k8sClient .CoreV1 ().Pods (ns .Name ).Get (context .TODO (), touchPod .Name , metav1.GetOptions {})
246
+ Expect (err ).ToNot (HaveOccurred ())
247
+ return touchPod .Status .Phase == corev1 .PodRunning || touchPod .Status .Phase == corev1 .PodSucceeded
248
+ }, 90 * time .Second , 1 * time .Second ).Should (BeTrue ())
249
+ getPod := createPodUsingPVCWithFsGroup (ns .Name , "get-pod" , pvc , "ls -al /data/test.txt" , 2000 , annotations )
250
+ getPod , err = k8sClient .CoreV1 ().Pods (ns .Name ).Create (context .TODO (), getPod , metav1.CreateOptions {})
251
+ Expect (err ).ToNot (HaveOccurred ())
252
+ Eventually (func () string {
253
+ getPod , err = k8sClient .CoreV1 ().Pods (ns .Name ).Get (context .TODO (), getPod .Name , metav1.GetOptions {})
254
+ Expect (err ).ToNot (HaveOccurred ())
255
+ out ,err := RunKubeCtlCommand ("logs" , getPod .GetName (), "-n" , ns .Name )
256
+ if err != nil {
257
+ return ""
258
+ }
259
+ return out
260
+ }, 90 * time .Second , 1 * time .Second ).Should (ContainSubstring ("-rw-r--r--. 1 1000 2000" ))
261
+ }
262
+
213
263
func createPVCDef (namespace , storageClassName string , annotations map [string ]string ) * corev1.PersistentVolumeClaim {
214
264
return & corev1.PersistentVolumeClaim {
215
265
ObjectMeta : metav1.ObjectMeta {
@@ -232,9 +282,13 @@ func createPVCDef(namespace, storageClassName string, annotations map[string]str
232
282
}
233
283
234
284
func createPodUsingPVC (namespace string , pvc * corev1.PersistentVolumeClaim , annotations map [string ]string ) * corev1.Pod {
285
+ return createPodUsingPVCWithCommand (namespace , "test-pod" , pvc , "sleep 1" , annotations )
286
+ }
287
+
288
+ func createPodUsingPVCWithCommand (namespace , name string , pvc * corev1.PersistentVolumeClaim , command string , annotations map [string ]string ) * corev1.Pod {
235
289
return & corev1.Pod {
236
290
ObjectMeta : metav1.ObjectMeta {
237
- Name : "test-pod" ,
291
+ Name : name ,
238
292
Namespace : namespace ,
239
293
Annotations : annotations ,
240
294
},
@@ -243,13 +297,19 @@ func createPodUsingPVC(namespace string, pvc *corev1.PersistentVolumeClaim, anno
243
297
Containers : []corev1.Container {
244
298
{
245
299
Name : "runner" ,
246
- Image : "kubevirt/cdi-importer:latest" ,
247
- Command : []string {"/bin/sh" , "-c" , "sleep 1" },
300
+ Image : "quay.io/kubevirt/cdi-importer:latest" ,
301
+ Command : []string {"/bin/sh" , "-c" , command },
302
+ VolumeMounts : []v1.VolumeMount {
303
+ {
304
+ Name : testMountName ,
305
+ MountPath : "/data" ,
306
+ },
307
+ },
248
308
},
249
309
},
250
310
Volumes : []corev1.Volume {
251
311
{
252
- Name : pvc . GetName () ,
312
+ Name : testMountName ,
253
313
VolumeSource : corev1.VolumeSource {
254
314
PersistentVolumeClaim : & corev1.PersistentVolumeClaimVolumeSource {
255
315
ClaimName : pvc .GetName (),
@@ -261,6 +321,17 @@ func createPodUsingPVC(namespace string, pvc *corev1.PersistentVolumeClaim, anno
261
321
}
262
322
}
263
323
324
+ func createPodUsingPVCWithFsGroup (namespace , name string , pvc * corev1.PersistentVolumeClaim , command string , groupId int64 , annotations map [string ]string ) * corev1.Pod {
325
+ userId := int64 (1000 )
326
+ pod := createPodUsingPVCWithCommand (namespace , name , pvc , command , annotations )
327
+ pod .Spec .SecurityContext = & corev1.PodSecurityContext {
328
+ RunAsUser : & userId ,
329
+ RunAsGroup : & groupId ,
330
+ FSGroup : & groupId ,
331
+ }
332
+ return pod
333
+ }
334
+
264
335
func getHostpathPVs (allPvs []corev1.PersistentVolume ) []corev1.PersistentVolume {
265
336
result := make ([]corev1.PersistentVolume , 0 )
266
337
for _ , pv := range allPvs {
0 commit comments