master
 1package get
 2
 3import (
 4	"fmt"
 5	"math"
 6	"os"
 7	"strings"
 8
 9	human "github.com/dustin/go-humanize"
10	"github.com/jedib0t/go-pretty/v6/table"
11	"github.com/kahnwong/swissknife/configs/color"
12	"github.com/shirou/gopsutil/v4/disk"
13)
14
15func Volumes() error {
16	// ref: <https://stackoverflow.com/a/64141403>
17	// layout inspired by `duf`
18
19	// init table
20	t := table.NewWriter()
21	t.SetOutputMirror(os.Stdout)
22	t.AppendHeader(table.Row{"Mounted on", "Size", "Used", "Avail", "Use%", "Type", "Filesystem"})
23
24	// get volumes info
25	partitions, err := disk.Partitions(false)
26	if err != nil {
27		return fmt.Errorf("error getting partitions info: %w", err)
28	}
29
30	for _, partition := range partitions {
31		// linux
32		isSquashFs := partition.Fstype == "squashfs"
33		isSnap := strings.Contains(partition.Mountpoint, "snap")
34		isKubernetes := strings.Contains(partition.Mountpoint, "kubelet")
35		// osx
36		isOsx := strings.Contains(partition.Mountpoint, "System/Volumes")
37		isDevFs := partition.Fstype == "devfs"
38		isOsxNix := strings.Contains(partition.Mountpoint, "/nix")
39		if !isSquashFs && !isSnap && !isKubernetes && !isOsx && !isDevFs && !isOsxNix {
40			device := partition.Mountpoint
41			stats, err := disk.Usage(device)
42			if err != nil {
43				return fmt.Errorf("error getting disk info: %w", err)
44			}
45
46			if stats.Total == 0 {
47				continue
48			}
49
50			// disk available
51			diskAvail := stats.Free
52			diskAvailStr := ""
53			if diskAvail < 50*1024*1024*1024 { // if free space less than 50 GB
54				diskAvailStr = color.Red(human.Bytes(diskAvail))
55			} else if diskAvail < 100*1024*1024*1024 { // if free space less than 100 GB
56				diskAvailStr = color.Yellow(human.Bytes(diskAvail))
57			} else {
58				diskAvailStr = color.Green(human.Bytes(diskAvail))
59			}
60
61			// disk use percent
62			percentRaw := stats.UsedPercent
63			diskUseTicks := int(math.Round(stats.UsedPercent)) / 10
64			diskUseBar := fmt.Sprintf(
65				"[%s%s] %2.f%%",
66				strings.Repeat("#", diskUseTicks),
67				strings.Repeat(".", 10-diskUseTicks),
68				stats.UsedPercent,
69			)
70			diskUseStr := ""
71			if percentRaw > 80 {
72				diskUseStr = color.Red(diskUseBar)
73			} else if percentRaw > 70 {
74				diskUseStr = color.Yellow(diskUseBar)
75			} else {
76				diskUseStr = color.Green(diskUseBar)
77			}
78
79			// append info to table
80			t.AppendRows([]table.Row{
81				{
82					color.Blue(partition.Mountpoint),
83					human.Bytes(stats.Total),
84					human.Bytes(stats.Used),
85					diskAvailStr,
86					diskUseStr,
87					color.Magenta(partition.Fstype),
88					color.Magenta(partition.Device),
89				},
90			})
91		}
92	}
93
94	// render
95	t.Render()
96	return nil
97}