Merge pull request #65837 from clandry94/pvc_describe_claimed_by

Automatic merge from submit-queue (batch tested with PRs 65838, 65837). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.

output which pods are a pvc in use when kubectl describe pvc is run

**What this PR does / why we need it**:
This PR implements a feature request to display the pods mounted to a PVC when `kubectl describe pvc` is ran. We need it since the only way to see which pods are bound to a PVC is by checking the volume mounts of each individual pod in the namespace. 

Example Output:
```
$ kubectl get pods,pvc
NAME     READY  STATUS    RESTARTS   AGE
test-pod   1/1       Running       0                2h

NAME      STATUS    VOLUME                                   CAPACITY  ACCESS MODES   STORAGECLASS        AGE
test-pvc  Bound     pvc-718681dd-70cc-11e7-aa14-42010af00029   100Gi      RWO            us-east1-b          345d
```

```
$ kubectl describe pvc
Name:          elasticsearch-data-elasticsearch-data-us-east1-b-0
Namespace:     partners-production
StorageClass:  us-east1-b
Status:        Bound
Volume:      pvc-718681dd-70cc-11e7-aa14-42010af00029
Labels:       <none>
Annotations:   <none>
Finalizers:    [kubernetes.io/pvc-protection]
Capacity:      1Gi
Access Modes:  RWO
Events:        <none>
Mounted By:     test-pod
```

Pods using the PVC are shown with the `Mounted By` field

**Which issue(s) this PR fixes**:
Closes #65233 

**Special notes for your reviewer**:

**Release note**:
```release-note
Running `kubectl describe pvc` now shows which pods are mounted to the pvc being described with the `Mounted By` field
```
pull/8/head
Kubernetes Submit Queue 2018-07-06 11:03:05 -07:00 committed by GitHub
commit 54db2273eb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 75 additions and 2 deletions

View File

@ -1291,12 +1291,52 @@ func (d *PersistentVolumeClaimDescriber) Describe(namespace, name string, descri
return "", err
}
pc := d.Core().Pods(namespace)
mountPods, err := getMountPods(pc, pvc.Name)
if err != nil {
return "", err
}
events, _ := d.Core().Events(namespace).Search(legacyscheme.Scheme, pvc)
return describePersistentVolumeClaim(pvc, events)
return describePersistentVolumeClaim(pvc, events, mountPods)
}
func describePersistentVolumeClaim(pvc *api.PersistentVolumeClaim, events *api.EventList) (string, error) {
func getMountPods(c coreclient.PodInterface, pvcName string) ([]api.Pod, error) {
nsPods, err := c.List(metav1.ListOptions{})
if err != nil {
return []api.Pod{}, err
}
var pods []api.Pod
for _, pod := range nsPods.Items {
pvcs := getPvcs(pod.Spec.Volumes)
for _, pvc := range pvcs {
if pvc.PersistentVolumeClaim.ClaimName == pvcName {
pods = append(pods, pod)
}
}
}
return pods, nil
}
func getPvcs(volumes []api.Volume) []api.Volume {
var pvcs []api.Volume
for _, volume := range volumes {
if volume.VolumeSource.PersistentVolumeClaim != nil {
pvcs = append(pvcs, volume)
}
}
return pvcs
}
func describePersistentVolumeClaim(pvc *api.PersistentVolumeClaim, events *api.EventList, mountPods []api.Pod) (string, error) {
return tabbedString(func(out io.Writer) error {
w := NewPrefixWriter(out)
w.Write(LEVEL_0, "Name:\t%s\n", pvc.Name)
@ -1342,6 +1382,8 @@ func describePersistentVolumeClaim(pvc *api.PersistentVolumeClaim, events *api.E
DescribeEvents(events, w)
}
printPodsMultiline(w, "Mounted By", mountPods)
return nil
})
}
@ -3867,6 +3909,37 @@ func printTaintsMultilineWithIndent(w PrefixWriter, initialIndent, title, innerI
}
}
// printPodsMultiline prints multiple pods with a proper alignment.
func printPodsMultiline(w PrefixWriter, title string, pods []api.Pod) {
printPodsMultilineWithIndent(w, "", title, "\t", pods)
}
// printPodsMultilineWithIndent prints multiple pods with a user-defined alignment.
func printPodsMultilineWithIndent(w PrefixWriter, initialIndent, title, innerIndent string, pods []api.Pod) {
w.Write(LEVEL_0, "%s%s:%s", initialIndent, title, innerIndent)
if pods == nil || len(pods) == 0 {
w.WriteLine("<none>")
return
}
// to print pods in the sorted order
sort.Slice(pods, func(i, j int) bool {
cmpKey := func(pod api.Pod) string {
return pod.Name
}
return cmpKey(pods[i]) < cmpKey(pods[j])
})
for i, pod := range pods {
if i != 0 {
w.Write(LEVEL_0, "%s", initialIndent)
w.Write(LEVEL_0, "%s", innerIndent)
}
w.Write(LEVEL_0, "%s\n", pod.Name)
}
}
// printPodTolerationsMultiline prints multiple tolerations with a proper alignment.
func printPodTolerationsMultiline(w PrefixWriter, title string, tolerations []api.Toleration) {
printTolerationsMultilineWithIndent(w, "", title, "\t", tolerations)