diff --git a/go.mod b/go.mod index 80b2ed2f..ebc04f15 100644 --- a/go.mod +++ b/go.mod @@ -14,6 +14,7 @@ require ( github.com/charmbracelet/huh v1.0.0 github.com/charmbracelet/lipgloss v1.1.0 github.com/charmbracelet/x/ansi v0.11.2 + github.com/dustin/go-humanize v1.0.1 github.com/fatih/color v1.19.0 github.com/frankban/quicktest v1.14.6 github.com/go-sql-driver/mysql v1.9.3 @@ -31,7 +32,7 @@ require ( github.com/mitchellh/go-homedir v1.1.0 github.com/muesli/termenv v0.16.0 github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c - github.com/planetscale/planetscale-go v0.176.0 + github.com/planetscale/planetscale-go v0.177.0 github.com/planetscale/psdb v0.0.0-20250717190954-65c6661ab6e4 github.com/planetscale/psdbproxy v0.0.0-20250728082226-3f4ea3a74ec7 github.com/spf13/cobra v1.10.2 @@ -68,7 +69,6 @@ require ( github.com/clipperhouse/uax29/v2 v2.3.0 // indirect github.com/danieljoos/wincred v1.2.3 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/dustin/go-humanize v1.0.1 // indirect github.com/dvsekhvalnov/jose2go v1.8.0 // indirect github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect github.com/fsnotify/fsnotify v1.9.0 // indirect diff --git a/go.sum b/go.sum index 3f26b92c..c3147c64 100644 --- a/go.sum +++ b/go.sum @@ -183,8 +183,8 @@ github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjL github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/planetscale/noglog v0.2.1-0.20210421230640-bea75fcd2e8e h1:MZ8D+Z3m2vvqGZLvoQfpaGg/j1fNDr4j03s3PRz4rVY= github.com/planetscale/noglog v0.2.1-0.20210421230640-bea75fcd2e8e/go.mod h1:hwAsSPQdvPa3WcfKfzTXxtEq/HlqwLjQasfO6QbGo4Q= -github.com/planetscale/planetscale-go v0.176.0 h1:EkwiSM0+GbRVZ7/sCMP+AXD7VK1cO/gPBdMziY2JEMA= -github.com/planetscale/planetscale-go v0.176.0/go.mod h1:paQCI5SgquuoewvMQM7R+r1XJO868bdP6/ihGidYRM0= +github.com/planetscale/planetscale-go v0.177.0 h1:jVE8uInjGayJ7RLaqwBK7VPgu96U/99dwV2MbbuRywA= +github.com/planetscale/planetscale-go v0.177.0/go.mod h1:paQCI5SgquuoewvMQM7R+r1XJO868bdP6/ihGidYRM0= github.com/planetscale/psdb v0.0.0-20250717190954-65c6661ab6e4 h1:Xv5pj20Rhfty1Tv0OVcidg4ez4PvGrpKvb6rvUwQgDs= github.com/planetscale/psdb v0.0.0-20250717190954-65c6661ab6e4/go.mod h1:M52h5IWxAcbdQ1hSZrLAGQC4ZXslxEsK/Wh9nu3wdWs= github.com/planetscale/psdbproxy v0.0.0-20250728082226-3f4ea3a74ec7 h1:aRd6vdE1fyuSI4RVj7oCr8lFmgqXvpnPUmN85VbZCp8= diff --git a/internal/cmd/branch/infra.go b/internal/cmd/branch/infra.go index d26f9386..b1331a6c 100644 --- a/internal/cmd/branch/infra.go +++ b/internal/cmd/branch/infra.go @@ -5,6 +5,7 @@ import ( "fmt" "time" + "github.com/dustin/go-humanize" "github.com/planetscale/cli/internal/cmdutil" "github.com/planetscale/cli/internal/printer" ps "github.com/planetscale/planetscale-go/planetscale" @@ -74,6 +75,67 @@ func toInfraPods(pods []*ps.BranchInfraPod) []*InfraPod { return result } +type PostgresInfraRow struct { + Component string `header:"component" json:"component"` + Role string `header:"role" json:"role"` + Size string `header:"size" json:"size"` + AZ string `header:"az" json:"az"` + Storage string `header:"storage" json:"storage"` + Name string `header:"name" json:"name"` + + orig any +} + +func (r *PostgresInfraRow) MarshalJSON() ([]byte, error) { + return json.MarshalIndent(r.orig, "", " ") +} + +func (r *PostgresInfraRow) MarshalCSVValue() interface{} { + return []*PostgresInfraRow{r} +} + +func toPostgresInfraRows(pg *ps.PostgresBranchInfrastructure) []*PostgresInfraRow { + rows := make([]*PostgresInfraRow, 0, len(pg.Nodes)+len(pg.Bouncers)) + + for _, node := range pg.Nodes { + storage := "-" + if node.VolumeUsageBytes != nil && node.VolumeCapacityBytes != nil { + storage = fmt.Sprintf("%s / %s", + humanize.IBytes(uint64(*node.VolumeUsageBytes)), + humanize.IBytes(uint64(*node.VolumeCapacityBytes))) + } + + rows = append(rows, &PostgresInfraRow{ + Component: "postgres", + Role: node.Role, + Size: node.ClusterDisplayName, + AZ: node.AvailabilityZone, + Storage: storage, + Name: node.Name, + orig: node, + }) + } + + for _, bouncer := range pg.Bouncers { + size := "-" + if bouncer.SKU != nil { + size = bouncer.SKU.DisplayName + } + + rows = append(rows, &PostgresInfraRow{ + Component: "pgbouncer", + Role: bouncer.Target, + Size: size, + AZ: "-", + Storage: "-", + Name: bouncer.Name, + orig: bouncer, + }) + } + + return rows +} + func humanAge(d time.Duration) string { if d < time.Minute { return fmt.Sprintf("%ds", int(d.Seconds())) @@ -137,12 +199,25 @@ func InfraCmd(ch *cmdutil.Helper) *cobra.Command { end() - if len(infra.Pods) == 0 && ch.Printer.Format() == printer.Human { - ch.Printer.Printf("No pods found for branch %s.\n", printer.BoldBlue(branch)) - return nil - } + switch { + case infra.Postgres != nil: + rows := toPostgresInfraRows(infra.Postgres) + if len(rows) == 0 && ch.Printer.Format() == printer.Human { + ch.Printer.Printf("No nodes found for branch %s.\n", printer.BoldBlue(branch)) + return nil + } - return ch.Printer.PrintResource(toInfraPods(infra.Pods)) + return ch.Printer.PrintResource(rows) + case infra.Vitess != nil: + if len(infra.Vitess.Pods) == 0 && ch.Printer.Format() == printer.Human { + ch.Printer.Printf("No pods found for branch %s.\n", printer.BoldBlue(branch)) + return nil + } + + return ch.Printer.PrintResource(toInfraPods(infra.Vitess.Pods)) + default: + return fmt.Errorf("unexpected infrastructure response for branch %s", branch) + } }, }