mirror of
https://github.com/psviderski/uncloud.git
synced 2026-08-26 11:03:34 +00:00
refactor: replace tabwriter with a Table for consistent table rendering across commands
This commit is contained in:
@@ -3,11 +3,10 @@ package context
|
||||
import (
|
||||
"fmt"
|
||||
"maps"
|
||||
"os"
|
||||
"slices"
|
||||
"text/tabwriter"
|
||||
|
||||
"github.com/psviderski/uncloud/internal/cli"
|
||||
"github.com/psviderski/uncloud/internal/cli/tui"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
@@ -38,8 +37,8 @@ func list(uncli *cli.CLI) error {
|
||||
contextNames := slices.Sorted(maps.Keys(uncli.Config.Contexts))
|
||||
currentContext := uncli.Config.CurrentContext
|
||||
|
||||
tw := tabwriter.NewWriter(os.Stdout, 0, 0, 3, ' ', 0)
|
||||
fmt.Fprintln(tw, "NAME\tCURRENT\tCONNECTIONS")
|
||||
t := tui.NewTable()
|
||||
t.Headers("NAME", "CURRENT", "CONNECTIONS")
|
||||
|
||||
for _, name := range contextNames {
|
||||
current := ""
|
||||
@@ -47,8 +46,9 @@ func list(uncli *cli.CLI) error {
|
||||
current = "✓"
|
||||
}
|
||||
connCount := len(uncli.Config.Contexts[name].Connections)
|
||||
fmt.Fprintf(tw, "%s\t%s\t%d\n", name, current, connCount)
|
||||
t.Row(name, current, fmt.Sprintf("%d", connCount))
|
||||
}
|
||||
|
||||
return tw.Flush()
|
||||
fmt.Println(t)
|
||||
return nil
|
||||
}
|
||||
|
||||
+15
-15
@@ -4,11 +4,10 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/netip"
|
||||
"os"
|
||||
"strings"
|
||||
"text/tabwriter"
|
||||
|
||||
"github.com/psviderski/uncloud/internal/cli"
|
||||
"github.com/psviderski/uncloud/internal/cli/tui"
|
||||
"github.com/psviderski/uncloud/internal/machine/network"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
@@ -39,12 +38,9 @@ func list(ctx context.Context, uncli *cli.CLI) error {
|
||||
}
|
||||
|
||||
// Print the list of machines in a table format.
|
||||
tw := tabwriter.NewWriter(os.Stdout, 0, 0, 3, ' ', 0)
|
||||
// Print header.
|
||||
if _, err = fmt.Fprintln(tw, "NAME\tSTATE\tADDRESS\tPUBLIC IP\tWIREGUARD ENDPOINTS\tMACHINE ID"); err != nil {
|
||||
return fmt.Errorf("write header: %w", err)
|
||||
}
|
||||
// Print rows.
|
||||
t := tui.NewTable()
|
||||
t.Headers("NAME", "STATE", "ADDRESS", "PUBLIC IP", "WIREGUARD ENDPOINTS", "MACHINE ID")
|
||||
|
||||
for _, member := range machines {
|
||||
m := member.Machine
|
||||
subnet, _ := m.Network.Subnet.ToPrefix()
|
||||
@@ -62,14 +58,18 @@ func list(ctx context.Context, uncli *cli.CLI) error {
|
||||
endpoints[i] = addrPort.String()
|
||||
}
|
||||
|
||||
if _, err = fmt.Fprintf(
|
||||
tw, "%s\t%s\t%s\t%s\t%s\t%s\n", m.Name, capitalise(member.State.String()), subnet, publicIP,
|
||||
strings.Join(endpoints, ", "), member.Machine.Id,
|
||||
); err != nil {
|
||||
return fmt.Errorf("write row: %w", err)
|
||||
}
|
||||
t.Row(
|
||||
m.Name,
|
||||
capitalise(member.State.String()),
|
||||
subnet.String(),
|
||||
publicIP,
|
||||
strings.Join(endpoints, tui.Faint.Render(", ")),
|
||||
member.Machine.Id,
|
||||
)
|
||||
}
|
||||
return tw.Flush()
|
||||
|
||||
fmt.Println(t)
|
||||
return nil
|
||||
}
|
||||
|
||||
// capitalise returns a string where the first character is upper case, and the rest is lower case.
|
||||
|
||||
@@ -206,7 +206,7 @@ func formatContainerTree(containers []api.ServiceContainer) string {
|
||||
// Add containers as children.
|
||||
for _, ctr := range ctrs {
|
||||
state, _ := ctr.HumanState()
|
||||
info := fmt.Sprintf("%s • %s • %s", ctr.Name, ctr.Config.Image, state)
|
||||
info := fmt.Sprintf("%s • %s • %s", ctr.Name, tui.FormatImage(ctr.Config.Image, tui.NoStyle), state)
|
||||
t.Child(info)
|
||||
}
|
||||
|
||||
|
||||
@@ -3,14 +3,13 @@ package service
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"slices"
|
||||
"text/tabwriter"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/pkg/stringid"
|
||||
"github.com/docker/go-units"
|
||||
"github.com/psviderski/uncloud/internal/cli"
|
||||
"github.com/psviderski/uncloud/internal/cli/tui"
|
||||
"github.com/psviderski/uncloud/pkg/api"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
@@ -73,10 +72,8 @@ func inspect(ctx context.Context, uncli *cli.CLI, opts inspectOptions) error {
|
||||
})
|
||||
|
||||
// Print the list of containers in a table format.
|
||||
tw := tabwriter.NewWriter(os.Stdout, 0, 0, 3, ' ', 0)
|
||||
if _, err = fmt.Fprintln(tw, "CONTAINER ID\tIMAGE\tCREATED\tSTATUS\tIP ADDRESS\tMACHINE"); err != nil {
|
||||
return fmt.Errorf("write header: %w", err)
|
||||
}
|
||||
t := tui.NewTable()
|
||||
t.Headers("CONTAINER ID", "IMAGE", "CREATED", "STATUS", "IP ADDRESS", "MACHINE")
|
||||
|
||||
now := time.Now().UTC()
|
||||
for _, ctr := range svc.Containers {
|
||||
@@ -98,19 +95,16 @@ func inspect(ctx context.Context, uncli *cli.CLI, opts inspectOptions) error {
|
||||
ipStr = ip.String()
|
||||
}
|
||||
|
||||
_, err = fmt.Fprintf(
|
||||
tw,
|
||||
"%s\t%s\t%s\t%s\t%s\t%s\n",
|
||||
t.Row(
|
||||
stringid.TruncateID(ctr.Container.ID),
|
||||
ctr.Container.Config.Image,
|
||||
tui.FormatImage(ctr.Container.Config.Image, tui.NoStyle),
|
||||
created,
|
||||
state,
|
||||
ipStr,
|
||||
machine,
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("write row: %w", err)
|
||||
}
|
||||
}
|
||||
return tw.Flush()
|
||||
|
||||
fmt.Println(t)
|
||||
return nil
|
||||
}
|
||||
|
||||
+18
-19
@@ -3,12 +3,11 @@ package service
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"slices"
|
||||
"strings"
|
||||
"text/tabwriter"
|
||||
|
||||
"github.com/psviderski/uncloud/internal/cli"
|
||||
"github.com/psviderski/uncloud/internal/cli/tui"
|
||||
"github.com/psviderski/uncloud/pkg/api"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
@@ -50,20 +49,22 @@ func list(ctx context.Context, uncli *cli.CLI) error {
|
||||
})
|
||||
|
||||
// Print the list of services in a table format.
|
||||
tw := tabwriter.NewWriter(os.Stdout, 0, 0, 3, ' ', 0)
|
||||
t := tui.NewTable()
|
||||
|
||||
// Include the ID column if there are duplicate service names to differentiate them.
|
||||
headers := []string{"NAME", "MODE", "REPLICAS", "IMAGE", "ENDPOINTS"}
|
||||
if haveDuplicateNames {
|
||||
if _, err = fmt.Fprintf(tw, "ID\t"); err != nil {
|
||||
return fmt.Errorf("write header: %w", err)
|
||||
}
|
||||
}
|
||||
if _, err = fmt.Fprintln(tw, "NAME\tMODE\tREPLICAS\tIMAGE\tENDPOINTS"); err != nil {
|
||||
return fmt.Errorf("write header: %w", err)
|
||||
headers = append([]string{"ID"}, headers...)
|
||||
}
|
||||
t.Headers(headers...)
|
||||
|
||||
for _, s := range services {
|
||||
images := strings.Join(s.Images(), ", ")
|
||||
endpoints := strings.Join(s.Endpoints(), ", ")
|
||||
images := s.Images()
|
||||
for i, img := range images {
|
||||
images[i] = tui.FormatImage(img, tui.NoStyle)
|
||||
}
|
||||
formattedImages := strings.Join(images, tui.Faint.Render(", "))
|
||||
endpoints := strings.Join(s.Endpoints(), tui.Faint.Render(", "))
|
||||
|
||||
// If no endpoints from ports, check if the service uses custom Caddy config.
|
||||
if endpoints == "" {
|
||||
@@ -74,15 +75,13 @@ func list(ctx context.Context, uncli *cli.CLI) error {
|
||||
}
|
||||
}
|
||||
|
||||
row := []string{s.Name, s.Mode, fmt.Sprintf("%d", len(s.Containers)), formattedImages, endpoints}
|
||||
if haveDuplicateNames {
|
||||
if _, err = fmt.Fprintf(tw, "%s\t", s.ID); err != nil {
|
||||
return fmt.Errorf("write row: %w", err)
|
||||
}
|
||||
}
|
||||
if _, err = fmt.Fprintf(tw, "%s\t%s\t%d\t%s\t%s\n",
|
||||
s.Name, s.Mode, len(s.Containers), images, endpoints); err != nil {
|
||||
return fmt.Errorf("write row: %w", err)
|
||||
row = append([]string{s.ID}, row...)
|
||||
}
|
||||
t.Row(row...)
|
||||
}
|
||||
return tw.Flush()
|
||||
|
||||
fmt.Println(t)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -3,12 +3,11 @@ package volume
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"slices"
|
||||
"strings"
|
||||
"text/tabwriter"
|
||||
|
||||
"github.com/psviderski/uncloud/internal/cli"
|
||||
"github.com/psviderski/uncloud/internal/cli/tui"
|
||||
"github.com/psviderski/uncloud/pkg/api"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
@@ -86,16 +85,13 @@ func list(ctx context.Context, uncli *cli.CLI, opts listOptions) error {
|
||||
}
|
||||
|
||||
// Print the volumes in a table format.
|
||||
tw := tabwriter.NewWriter(os.Stdout, 0, 0, 3, ' ', 0)
|
||||
fmt.Fprintln(tw, "NAME\tDRIVER\tMACHINE")
|
||||
t := tui.NewTable()
|
||||
t.Headers("NAME", "DRIVER", "MACHINE")
|
||||
|
||||
for _, v := range volumes {
|
||||
fmt.Fprintf(tw, "%s\t%s\t%s\n",
|
||||
v.Volume.Name,
|
||||
v.Volume.Driver,
|
||||
v.MachineName,
|
||||
)
|
||||
t.Row(v.Volume.Name, v.Volume.Driver, v.MachineName)
|
||||
}
|
||||
|
||||
return tw.Flush()
|
||||
fmt.Println(t)
|
||||
return nil
|
||||
}
|
||||
|
||||
+8
-14
@@ -3,13 +3,12 @@ package wg
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"text/tabwriter"
|
||||
"time"
|
||||
|
||||
"github.com/docker/go-units"
|
||||
"github.com/psviderski/uncloud/internal/cli"
|
||||
"github.com/psviderski/uncloud/internal/cli/tui"
|
||||
"github.com/spf13/cobra"
|
||||
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
||||
"google.golang.org/grpc/codes"
|
||||
@@ -97,10 +96,8 @@ func runShow(ctx context.Context, uncli *cli.CLI, opts showOptions) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
tw := tabwriter.NewWriter(os.Stdout, 0, 0, 3, ' ', 0)
|
||||
if _, err = fmt.Fprintln(tw, "PEER\tPUBLIC KEY\tENDPOINT\tHANDSHAKE\tRECEIVED\tSENT\tALLOWED IPS"); err != nil {
|
||||
return fmt.Errorf("write header: %w", err)
|
||||
}
|
||||
t := tui.NewTable()
|
||||
t.Headers("PEER", "PUBLIC KEY", "ENDPOINT", "HANDSHAKE", "RECEIVED", "SENT", "ALLOWED IPS")
|
||||
|
||||
for _, peer := range resp.Peers {
|
||||
machineName, ok := machinesNamesByPublicKey[wgtypes.Key(peer.PublicKey).String()]
|
||||
@@ -113,20 +110,17 @@ func runShow(ctx context.Context, uncli *cli.CLI, opts showOptions) error {
|
||||
lastHandshake = time.Since(peer.LastHandshakeTime.AsTime()).Round(time.Second).String() + " ago"
|
||||
}
|
||||
|
||||
_, err = fmt.Fprintf(
|
||||
tw,
|
||||
"%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
|
||||
t.Row(
|
||||
machineName,
|
||||
wgtypes.Key(peer.PublicKey).String(),
|
||||
peer.Endpoint,
|
||||
lastHandshake,
|
||||
units.HumanSize(float64(peer.ReceiveBytes)),
|
||||
units.HumanSize(float64(peer.TransmitBytes)),
|
||||
strings.Join(peer.AllowedIps, ", "),
|
||||
strings.Join(peer.AllowedIps, tui.Faint.Render(", ")),
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("write row: %w", err)
|
||||
}
|
||||
}
|
||||
return tw.Flush()
|
||||
|
||||
fmt.Println(t)
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user