Skip to content

Commit 6ae04c3

Browse files
committed
add persistent volume name; add volume mount name
1 parent 2d73c89 commit 6ae04c3

File tree

2 files changed

+70
-37
lines changed

2 files changed

+70
-37
lines changed

README.md

+21-7
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ kubectl df-pv
5656

5757
### Flags
5858

59-
```shell
59+
```shell script
6060
> kubectl df-pv --help
6161

6262
df-pv emulates Unix style df for persistent volumes w/ ability to filter by namespace
@@ -74,6 +74,14 @@ Flags:
7474
-v, --verbosity string log level; one of [info, debug, trace, warn, error, fatal, panic] (default "info")
7575
```
7676
77+
### Other useful commands
78+
79+
#### enable trace logging, but output to a file
80+
81+
```shell script
82+
df-pv -v trace 2> trace.log
83+
```
84+
7785
## Tested
7886
7987
### Works on
@@ -96,19 +104,25 @@ Flags:
96104
97105
## TODO Features
98106
107+
### Yet to be completed
108+
109+
☒ sort-by flag
110+
111+
☒ exclude namespaces
112+
113+
☒ only show a specific colored result ("red", "yellow", "green")
114+
115+
### Completed
116+
99117
☑ `df` for all Persistent Volumes in the cluster
100118
101119
☑ human readable output as default (using IEC format)
102120
103121
&#9745; color based on usage [red: > 75% (too high); yellow: < 25% (too low); green: >= 25 and <= 75 (OK)]
104122
105-
&#9746; sort-by flag
123+
&#9745; print PV name
106124
107-
&#9746; print PV name (right now, it prints the PVC name)
108-
109-
&#9746; exclude namespaces
110-
111-
&#9746; only show a specific colored result ("red", "yellow", "green")
125+
&#9745; print volume mount name
112126
113127
## Motivation
114128

pkg/df-pv/root.go

+49-30
Original file line numberDiff line numberDiff line change
@@ -89,15 +89,17 @@ func PrintUsingGoPretty(sliceOfOutputRowPVC []*OutputRowPVC) {
8989
// https://github.com/jedib0t/go-pretty/tree/v6.0.4/table
9090
t := table.NewWriter()
9191

92-
t.AppendHeader(table.Row{"PVC", "Namespace", "Pod", "Size", "Used", "Available", "%Used", "iused", "ifree", "%iused"})
92+
t.AppendHeader(table.Row{"Namespace", "PVC Name", "PV Name", "Pod Name", "Volume Mount Name", "Size", "Used", "Available", "%Used", "iused", "ifree", "%iused"})
9393
hiWhiteColor := text.FgHiWhite
9494
for _, pvcRow := range sliceOfOutputRowPVC {
9595
percentageUsedColor := GetColorFromPercentageUsed(pvcRow.PercentageUsed)
9696
percentageIUsedColor := GetColorFromPercentageUsed(pvcRow.PercentageIUsed)
9797
t.AppendRow([]interface{}{
98-
hiWhiteColor.Sprintf("%s", pvcRow.PVCName),
9998
hiWhiteColor.Sprintf("%s", pvcRow.Namespace),
99+
hiWhiteColor.Sprintf("%s", pvcRow.PVCName),
100+
hiWhiteColor.Sprintf("%s", pvcRow.PVName),
100101
hiWhiteColor.Sprintf("%s", pvcRow.PodName),
102+
hiWhiteColor.Sprintf("%s", pvcRow.VolumeMountName),
101103
percentageUsedColor.Sprintf("%s", ConvertQuantityValueToHumanReadableIECString(pvcRow.CapacityBytes)),
102104
percentageUsedColor.Sprintf("%s", ConvertQuantityValueToHumanReadableIECString(pvcRow.UsedBytes)),
103105
percentageUsedColor.Sprintf("%s", ConvertQuantityValueToHumanReadableIECString(pvcRow.AvailableBytes)),
@@ -321,22 +323,19 @@ func ConvertQuantityValueToHumanReadableDecimalString(quantity *resource.Quantit
321323
// }
322324

323325
type OutputRowPVC struct {
324-
PodName string `json:"podName"`
325-
Namespace string `json:"namespace"`
326-
327-
PVCName string `json:"pvcName"`
328-
329-
AvailableBytes *resource.Quantity `json:"availableBytes"`
330-
CapacityBytes *resource.Quantity `json:"capacityBytes"`
331-
UsedBytes *resource.Quantity `json:"usedBytes"`
332-
PercentageUsed float64
333-
326+
Namespace string `json:"namespace"`
327+
PVCName string `json:"pvcName"`
328+
PVName string `json:"pvName"`
329+
PodName string `json:"podName"`
330+
VolumeMountName string `json:"volumeMountName"`
331+
AvailableBytes *resource.Quantity `json:"availableBytes"`
332+
CapacityBytes *resource.Quantity `json:"capacityBytes"`
333+
UsedBytes *resource.Quantity `json:"usedBytes"`
334+
PercentageUsed float64
334335
InodesFree int64 `json:"inodesFree"`
335336
Inodes int64 `json:"inodes"`
336337
InodesUsed int64 `json:"inodesUsed"`
337338
PercentageIUsed float64
338-
339-
VolumeMountName string `json:"volumeMountName"`
340339
}
341340

342341
type ServerResponseStruct struct {
@@ -506,13 +505,17 @@ func GetOutputRowPVCFromNodeChan(ctx context.Context, clientset *kubernetes.Clie
506505

507506
// for trace logging only
508507
var nodeRespBody interface{}
509-
_ = json.Unmarshal(responseRawArrayOfBytes, &nodeRespBody)
508+
err = json.Unmarshal(responseRawArrayOfBytes, &nodeRespBody)
509+
if err != nil {
510+
return errors.Wrapf(err, "unable to unmarshal json into an interface (this really shouldn't happen)")
511+
}
510512
// log.Tracef("response from node: %+v\n", nodeRespBody)
511-
jsonText, err := json.MarshalIndent(nodeRespBody, "", " ")
513+
jsonText, err := json.Marshal(nodeRespBody)
514+
// jsonText, err := json.MarshalIndent(nodeRespBody, "", " ")
512515
if err != nil {
513516
return errors.Wrapf(err, "unable to marshal json (this really shouldn't happen)")
514517
}
515-
log.Tracef("response from node: %s\n", jsonText)
518+
log.Tracef("response from node: %s", jsonText)
516519

517520
var jsonConvertedIntoStruct ServerResponseStruct
518521
err = json.Unmarshal(responseRawArrayOfBytes, &jsonConvertedIntoStruct)
@@ -522,7 +525,7 @@ func GetOutputRowPVCFromNodeChan(ctx context.Context, clientset *kubernetes.Clie
522525

523526
for _, pod := range jsonConvertedIntoStruct.Pods {
524527
for _, vol := range pod.ListOfVolumes {
525-
outputRowPVC := GetOutputRowPVCFromPodAndVolume(pod, vol, desiredNamespace)
528+
outputRowPVC := GetOutputRowPVCFromPodAndVolume(ctx, clientset, pod, vol, desiredNamespace)
526529
if nil == outputRowPVC {
527530
log.Tracef("no pvc found for pod: '%s', vol: '%s', desiredNamespace: '%s'; continuing...", pod.PodRef.Name, vol.PvcRef.PvcName, desiredNamespace)
528531
continue
@@ -539,7 +542,7 @@ func GetOutputRowPVCFromNodeChan(ctx context.Context, clientset *kubernetes.Clie
539542
return nil
540543
}
541544

542-
func GetOutputRowPVCFromPodAndVolume(pod *Pod, vol *Volume, desiredNamespace string) *OutputRowPVC {
545+
func GetOutputRowPVCFromPodAndVolume(ctx context.Context, clientset *kubernetes.Clientset, pod *Pod, vol *Volume, desiredNamespace string) *OutputRowPVC {
543546
var outputRowPVC *OutputRowPVC
544547

545548
if 0 < len(desiredNamespace) {
@@ -551,22 +554,28 @@ func GetOutputRowPVCFromPodAndVolume(pod *Pod, vol *Volume, desiredNamespace str
551554
}
552555

553556
if 0 < len(vol.PvcRef.PvcName) {
554-
outputRowPVC = &OutputRowPVC{
555-
PodName: pod.PodRef.Name,
556-
Namespace: pod.PodRef.Namespace,
557-
558-
PVCName: vol.PvcRef.PvcName,
559-
AvailableBytes: resource.NewQuantity(vol.AvailableBytes, resource.BinarySI),
560-
CapacityBytes: resource.NewQuantity(vol.CapacityBytes, resource.BinarySI),
561-
UsedBytes: resource.NewQuantity(vol.UsedBytes, resource.BinarySI),
562-
PercentageUsed: (float64(vol.UsedBytes) / float64(vol.CapacityBytes)) * 100.0,
557+
namespace := pod.PodRef.Namespace
558+
pvcName := vol.PvcRef.PvcName
559+
pvName, _ := GetPVNameFromPVCName(ctx, clientset, namespace, pvcName)
560+
// if err != nil {
561+
// ctx.Err()
562+
// return errors.Wrapf(err, "unable to get PV name from the PVC name")
563+
// }
563564

565+
outputRowPVC = &OutputRowPVC{
566+
Namespace: namespace,
567+
PVCName: pvcName,
568+
PVName: pvName,
569+
PodName: pod.PodRef.Name,
570+
VolumeMountName: vol.Name,
571+
AvailableBytes: resource.NewQuantity(vol.AvailableBytes, resource.BinarySI),
572+
CapacityBytes: resource.NewQuantity(vol.CapacityBytes, resource.BinarySI),
573+
UsedBytes: resource.NewQuantity(vol.UsedBytes, resource.BinarySI),
574+
PercentageUsed: (float64(vol.UsedBytes) / float64(vol.CapacityBytes)) * 100.0,
564575
Inodes: vol.Inodes,
565576
InodesFree: vol.InodesFree,
566577
InodesUsed: vol.InodesUsed,
567578
PercentageIUsed: (float64(vol.InodesUsed) / float64(vol.Inodes)) * 100.0,
568-
569-
VolumeMountName: vol.Name,
570579
}
571580
}
572581
return outputRowPVC
@@ -582,6 +591,16 @@ func ListNodes(ctx context.Context, clientset *kubernetes.Clientset) (*corev1.No
582591
return clientset.CoreV1().Nodes().List(ctx, metav1.ListOptions{})
583592
}
584593

594+
func GetPVNameFromPVCName(ctx context.Context, clientset *kubernetes.Clientset, namespace string, pvcName string) (string, error) {
595+
var pvName string
596+
pvc, err := clientset.CoreV1().PersistentVolumeClaims(namespace).Get(ctx, pvcName, metav1.GetOptions{})
597+
if err != nil {
598+
return pvName, err
599+
}
600+
pvName = pvc.Spec.VolumeName
601+
return pvName, err
602+
}
603+
585604
func KubeConfigPath() (string, error) {
586605
log.Debugf("getting kubeconfig path based on user's home dir")
587606
home, err := os.UserHomeDir()

0 commit comments

Comments
 (0)