diff --git a/README.md b/README.md index 85047d3..ca16c49 100644 --- a/README.md +++ b/README.md @@ -195,6 +195,7 @@ services: glance: container_name: glance image: glanceapp/glance + restart: unless-stopped volumes: - ./config:/app/config ports: diff --git a/internal/glance/cli.go b/internal/glance/cli.go index 7527750..8e0fc32 100644 --- a/internal/glance/cli.go +++ b/internal/glance/cli.go @@ -6,6 +6,7 @@ import ( "os" "strings" + "github.com/shirou/gopsutil/v4/disk" "github.com/shirou/gopsutil/v4/sensors" ) @@ -18,11 +19,13 @@ const ( cliIntentConfigPrint cliIntentDiagnose cliIntentSensorsPrint + cliIntentMountpointInfo ) type cliOptions struct { intent cliIntent configPath string + args []string } func parseCliOptions() (*cliOptions, error) { @@ -46,6 +49,7 @@ func parseCliOptions() (*cliOptions, error) { fmt.Println(" config:validate Validate the config file") fmt.Println(" config:print Print the parsed config file with embedded includes") fmt.Println(" sensors:print List all sensors") + fmt.Println(" mountpoint:info Print information about a given mountpoint path") fmt.Println(" diagnose Run diagnostic checks") } configPath := flags.String("config", "glance.yml", "Set config path") @@ -72,6 +76,12 @@ func parseCliOptions() (*cliOptions, error) { } else { return nil, unknownCommandErr } + } else if len(args) == 2 { + if args[0] == "mountpoint:info" { + intent = cliIntentMountpointInfo + } else { + return nil, unknownCommandErr + } } else { return nil, unknownCommandErr } @@ -79,6 +89,7 @@ func parseCliOptions() (*cliOptions, error) { return &cliOptions{ intent: intent, configPath: *configPath, + args: args, }, nil } @@ -105,3 +116,23 @@ func cliSensorsPrint() int { return 0 } + +func cliMountpointInfo(requestedPath string) int { + usage, err := disk.Usage(requestedPath) + if err != nil { + fmt.Printf("Failed to retrieve info for path %s: %v\n", requestedPath, err) + if warns, ok := err.(*disk.Warnings); ok { + for _, w := range warns.List { + fmt.Printf(" - %v\n", w) + } + } + + return 1 + } + + fmt.Println("Path:", usage.Path) + fmt.Println("FS type:", ternary(usage.Fstype == "", "unknown", usage.Fstype)) + fmt.Printf("Used percent: %.1f%%", usage.UsedPercent) + + return 0 +} diff --git a/internal/glance/main.go b/internal/glance/main.go index 3dd43dc..67a980c 100644 --- a/internal/glance/main.go +++ b/internal/glance/main.go @@ -51,6 +51,8 @@ func Main() int { fmt.Println(string(contents)) case cliIntentSensorsPrint: return cliSensorsPrint() + case cliIntentMountpointInfo: + return cliMountpointInfo(options.args[1]) case cliIntentDiagnose: runDiagnostic() } diff --git a/pkg/sysinfo/sysinfo.go b/pkg/sysinfo/sysinfo.go index 673b9d2..1ed8c75 100644 --- a/pkg/sysinfo/sysinfo.go +++ b/pkg/sysinfo/sysinfo.go @@ -227,35 +227,50 @@ func Collect(req *SystemInfoRequest) (*SystemInfo, []error) { } } - filesystems, err := disk.Partitions(false) - if err == nil { - for _, fs := range filesystems { - mpReq, ok := req.Mountpoints[fs.Mountpoint] - isHidden := req.HideMountpointsByDefault - if ok && mpReq.Hide != nil { - isHidden = *mpReq.Hide - } - if isHidden { - continue - } - - usage, err := disk.Usage(fs.Mountpoint) - if err == nil { - mpInfo := MountpointInfo{ - Path: fs.Mountpoint, - Name: mpReq.Name, - TotalMB: usage.Total / 1024 / 1024, - UsedMB: usage.Used / 1024 / 1024, - UsedPercent: uint8(math.Min(usage.UsedPercent, 100)), - } - - info.Mountpoints = append(info.Mountpoints, mpInfo) - } else { - addErr(fmt.Errorf("getting filesystem usage for %s: %v", fs.Mountpoint, err)) - } + addedMountpoints := map[string]struct{}{} + addMountpointInfo := func(requestedPath string, mpReq MointpointRequest) { + if _, exists := addedMountpoints[requestedPath]; exists { + return } - } else { - addErr(fmt.Errorf("getting filesystems: %v", err)) + + isHidden := req.HideMountpointsByDefault + if mpReq.Hide != nil { + isHidden = *mpReq.Hide + } + if isHidden { + return + } + + usage, err := disk.Usage(requestedPath) + if err == nil { + mpInfo := MountpointInfo{ + Path: requestedPath, + Name: mpReq.Name, + TotalMB: usage.Total / 1024 / 1024, + UsedMB: usage.Used / 1024 / 1024, + UsedPercent: uint8(math.Min(usage.UsedPercent, 100)), + } + + info.Mountpoints = append(info.Mountpoints, mpInfo) + addedMountpoints[requestedPath] = struct{}{} + } else { + addErr(fmt.Errorf("getting filesystem usage for %s: %v", requestedPath, err)) + } + } + + if !req.HideMountpointsByDefault { + filesystems, err := disk.Partitions(false) + if err == nil { + for _, fs := range filesystems { + addMountpointInfo(fs.Mountpoint, req.Mountpoints[fs.Mountpoint]) + } + } else { + addErr(fmt.Errorf("getting filesystems: %v", err)) + } + } + + for mountpoint, mpReq := range req.Mountpoints { + addMountpointInfo(mountpoint, mpReq) } sort.Slice(info.Mountpoints, func(a, b int) bool {