From 87752492d0dc7df3cf78011d5ce315a3eb0cad51 Mon Sep 17 00:00:00 2001 From: bndw Date: Fri, 23 Jan 2026 21:52:50 -0800 Subject: Restructure CLI with Cobra Replace custom switch-based routing with Cobra for cleaner command hierarchy. Reorganize commands into logical groups: - Root command handles deployment (--binary, --static, --domain, etc.) - App management at top level: list, logs, status, restart, remove - env subcommand group: list, set, unset - host subcommand group: init, status, update, ssh - Standalone: ui (renamed from webui), version Add version command with ldflags support for build info. --- cmd/deploy/host/status.go | 108 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 cmd/deploy/host/status.go (limited to 'cmd/deploy/host/status.go') diff --git a/cmd/deploy/host/status.go b/cmd/deploy/host/status.go new file mode 100644 index 0000000..bdd9c31 --- /dev/null +++ b/cmd/deploy/host/status.go @@ -0,0 +1,108 @@ +package host + +import ( + "fmt" + + "github.com/bdw/deploy/internal/ssh" + "github.com/bdw/deploy/internal/state" + "github.com/spf13/cobra" +) + +var statusCmd = &cobra.Command{ + Use: "status", + Short: "Show VPS health (uptime, disk, memory)", + RunE: runStatus, +} + +func runStatus(cmd *cobra.Command, args []string) error { + st, err := state.Load() + if err != nil { + return fmt.Errorf("error loading state: %w", err) + } + + host, _ := cmd.Flags().GetString("host") + if host == "" { + host = st.GetDefaultHost() + } + + if host == "" { + return fmt.Errorf("--host is required (no default host set)") + } + + fmt.Printf("Connecting to %s...\n\n", host) + + client, err := ssh.Connect(host) + if err != nil { + return fmt.Errorf("error connecting to VPS: %w", err) + } + defer client.Close() + + fmt.Println("UPTIME") + if output, err := client.Run("uptime -p"); err == nil { + fmt.Printf(" %s", output) + } + if output, err := client.Run("uptime -s"); err == nil { + fmt.Printf(" Since: %s", output) + } + fmt.Println() + + fmt.Println("LOAD") + if output, err := client.Run("cat /proc/loadavg | awk '{print $1, $2, $3}'"); err == nil { + fmt.Printf(" 1m, 5m, 15m: %s", output) + } + fmt.Println() + + fmt.Println("MEMORY") + if output, err := client.Run("free -h | awk 'NR==2 {print \" Used: \" $3 \" / \" $2}'"); err == nil { + fmt.Print(output) + } + if output, err := client.Run("free -h | awk 'NR==2 {printf \" Available: %s\\n\", $7}'"); err == nil { + fmt.Print(output) + } + fmt.Println() + + fmt.Println("DISK") + if output, err := client.Run("df -h / | awk 'NR==2 {print \" Used: \" $3 \" / \" $2 \" (\" $5 \")\"}'"); err == nil { + fmt.Print(output) + } + if output, err := client.Run("df -h / | awk 'NR==2 {print \" Available: \" $4}'"); err == nil { + fmt.Print(output) + } + fmt.Println() + + fmt.Println("UPDATES") + if output, err := client.Run("[ -f /var/lib/update-notifier/updates-available ] && cat /var/lib/update-notifier/updates-available | head -2 || echo ' (update info not available)'"); err == nil { + fmt.Print(output) + } + fmt.Println() + + fmt.Println("SERVICES") + if output, err := client.Run("systemctl is-active caddy 2>/dev/null && echo ' Caddy: active' || echo ' Caddy: inactive'"); err == nil { + if output == "active\n" { + fmt.Println(" Caddy: active") + } else { + fmt.Println(" Caddy: inactive") + } + } + + hostState := st.GetHost(host) + if hostState != nil && len(hostState.Apps) > 0 { + activeCount := 0 + for name, app := range hostState.Apps { + if app.Type == "app" { + if output, err := client.Run(fmt.Sprintf("systemctl is-active %s 2>/dev/null", name)); err == nil && output == "active\n" { + activeCount++ + } + } + } + appCount := 0 + for _, app := range hostState.Apps { + if app.Type == "app" { + appCount++ + } + } + fmt.Printf(" Deployed apps: %d/%d active\n", activeCount, appCount) + } + + return nil +} -- cgit v1.2.3