Look for pods in ownerReferences of PVC (#120427)

* Look for pods in ownerReferences of PVC

* Implement for loop instead of using slices package

* Add tests for getPodsForPVC function

* Make PVC names consistent

* Remove volumes part of the pvc owner pod

* Do not store result of append in another variable

* Fix lint error
This commit is contained in:
Majid Garoosi 2023-09-13 20:26:12 +03:30 committed by GitHub
parent a08ee80807
commit 710dceded5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 148 additions and 3 deletions

View File

@ -1645,7 +1645,7 @@ func (d *PersistentVolumeClaimDescriber) Describe(namespace, name string, descri
pc := d.CoreV1().Pods(namespace)
pods, err := getPodsForPVC(pc, pvc.Name, describerSettings)
pods, err := getPodsForPVC(pc, pvc, describerSettings)
if err != nil {
return "", err
}
@ -1655,7 +1655,7 @@ func (d *PersistentVolumeClaimDescriber) Describe(namespace, name string, descri
return describePersistentVolumeClaim(pvc, events, pods)
}
func getPodsForPVC(c corev1client.PodInterface, pvcName string, settings DescriberSettings) ([]corev1.Pod, error) {
func getPodsForPVC(c corev1client.PodInterface, pvc *corev1.PersistentVolumeClaim, settings DescriberSettings) ([]corev1.Pod, error) {
nsPods, err := getPodsInChunks(c, metav1.ListOptions{Limit: settings.ChunkSize})
if err != nil {
return []corev1.Pod{}, err
@ -1665,12 +1665,40 @@ func getPodsForPVC(c corev1client.PodInterface, pvcName string, settings Describ
for _, pod := range nsPods.Items {
for _, volume := range pod.Spec.Volumes {
if volume.VolumeSource.PersistentVolumeClaim != nil && volume.VolumeSource.PersistentVolumeClaim.ClaimName == pvcName {
if volume.VolumeSource.PersistentVolumeClaim != nil && volume.VolumeSource.PersistentVolumeClaim.ClaimName == pvc.Name {
pods = append(pods, pod)
}
}
}
ownersLoop:
for _, ownerRef := range pvc.ObjectMeta.OwnerReferences {
if ownerRef.Kind != "Pod" {
continue
}
podIndex := -1
for i, pod := range nsPods.Items {
if pod.UID == ownerRef.UID {
podIndex = i
break
}
}
if podIndex == -1 {
// Maybe the pod has been deleted
continue
}
for _, pod := range pods {
if pod.UID == nsPods.Items[podIndex].UID {
// This owner pod is already recorded, look for pods between other owners
continue ownersLoop
}
}
pods = append(pods, nsPods.Items[podIndex])
}
return pods, nil
}

View File

@ -1994,6 +1994,123 @@ func TestPersistentVolumeClaimDescriber(t *testing.T) {
}
}
func TestGetPodsForPVC(t *testing.T) {
goldClassName := "gold"
testCases := []struct {
name string
pvc *corev1.PersistentVolumeClaim
requiredObjects []runtime.Object
expectedPods []string
}{
{
name: "pvc-unused",
pvc: &corev1.PersistentVolumeClaim{
ObjectMeta: metav1.ObjectMeta{Namespace: "ns", Name: "pvc-name"},
Spec: corev1.PersistentVolumeClaimSpec{
VolumeName: "volume1",
StorageClassName: &goldClassName,
},
Status: corev1.PersistentVolumeClaimStatus{
Phase: corev1.ClaimBound,
},
},
expectedPods: []string{},
},
{
name: "pvc-in-pods-volumes-list",
pvc: &corev1.PersistentVolumeClaim{
ObjectMeta: metav1.ObjectMeta{Namespace: "ns", Name: "pvc-name"},
Spec: corev1.PersistentVolumeClaimSpec{
VolumeName: "volume1",
StorageClassName: &goldClassName,
},
Status: corev1.PersistentVolumeClaimStatus{
Phase: corev1.ClaimBound,
},
},
requiredObjects: []runtime.Object{
&corev1.Pod{
ObjectMeta: metav1.ObjectMeta{Namespace: "ns", Name: "pod-name"},
Spec: corev1.PodSpec{
Volumes: []corev1.Volume{
{
Name: "volume",
VolumeSource: corev1.VolumeSource{
PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{
ClaimName: "pvc-name",
},
},
},
},
},
},
},
expectedPods: []string{"pod-name"},
},
{
name: "pvc-owned-by-pod",
pvc: &corev1.PersistentVolumeClaim{
ObjectMeta: metav1.ObjectMeta{
Namespace: "ns",
Name: "pvc-name",
OwnerReferences: []metav1.OwnerReference{
{
Kind: "Pod",
Name: "pod-name",
UID: "pod-uid",
},
},
},
Spec: corev1.PersistentVolumeClaimSpec{
VolumeName: "volume1",
StorageClassName: &goldClassName,
},
Status: corev1.PersistentVolumeClaimStatus{
Phase: corev1.ClaimBound,
},
},
requiredObjects: []runtime.Object{
&corev1.Pod{
ObjectMeta: metav1.ObjectMeta{Namespace: "ns", Name: "pod-name", UID: "pod-uid"},
},
},
expectedPods: []string{"pod-name"},
},
}
for _, test := range testCases {
t.Run(test.name, func(t *testing.T) {
var objects []runtime.Object
objects = append(objects, test.requiredObjects...)
objects = append(objects, test.pvc)
fake := fake.NewSimpleClientset(objects...)
pods, err := getPodsForPVC(fake.CoreV1().Pods(test.pvc.ObjectMeta.Namespace), test.pvc, DescriberSettings{})
if err != nil {
t.Errorf("Unexpected error for test %s: %v", test.name, err)
}
for _, expectedPod := range test.expectedPods {
foundPod := false
for _, pod := range pods {
if pod.Name == expectedPod {
foundPod = true
break
}
}
if !foundPod {
t.Errorf("Expected pod %s, but it was not returned: %v", expectedPod, pods)
}
}
if len(test.expectedPods) != len(pods) {
t.Errorf("Expected %d pods, but got %d pods", len(test.expectedPods), len(pods))
}
})
}
}
func TestDescribeDeployment(t *testing.T) {
labels := map[string]string{"k8s-app": "bar"}
testCases := []struct {