diff --git a/go.mod b/go.mod index c2d02f3b..26f2d701 100644 --- a/go.mod +++ b/go.mod @@ -25,7 +25,7 @@ require ( github.com/mattn/go-shellwords v1.0.12 github.com/mitchellh/go-homedir v1.1.0 github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c - github.com/planetscale/planetscale-go v0.151.0 + github.com/planetscale/planetscale-go v0.152.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 diff --git a/go.sum b/go.sum index 52500b6a..bddcdd53 100644 --- a/go.sum +++ b/go.sum @@ -182,8 +182,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.151.0 h1:Vx1khlA76AnioSZzoY6gbJvXfMOKVWjjf4980bYgAA8= -github.com/planetscale/planetscale-go v0.151.0/go.mod h1:mnADwPuBOmZaRCBbCzQna8N69vhlpEDCWGMF501qnEA= +github.com/planetscale/planetscale-go v0.152.0 h1:iFuW/9Mk57Cn8fdKEsAzMAktq5ukO7Cjm0S0ISiJPDU= +github.com/planetscale/planetscale-go v0.152.0/go.mod h1:mnADwPuBOmZaRCBbCzQna8N69vhlpEDCWGMF501qnEA= 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/branch.go b/internal/cmd/branch/branch.go index f36df908..5ecc9390 100644 --- a/internal/cmd/branch/branch.go +++ b/internal/cmd/branch/branch.go @@ -36,6 +36,7 @@ func BranchCmd(ch *cmdutil.Helper) *cobra.Command { cmd.AddCommand(SafeMigrationsCmd(ch)) cmd.AddCommand(LintCmd(ch)) cmd.AddCommand(vtctld.VtctldCmd(ch)) + cmd.AddCommand(InfraCmd(ch)) return cmd } diff --git a/internal/cmd/branch/infra.go b/internal/cmd/branch/infra.go new file mode 100644 index 00000000..d26f9386 --- /dev/null +++ b/internal/cmd/branch/infra.go @@ -0,0 +1,150 @@ +package branch + +import ( + "encoding/json" + "fmt" + "time" + + "github.com/planetscale/cli/internal/cmdutil" + "github.com/planetscale/cli/internal/printer" + ps "github.com/planetscale/planetscale-go/planetscale" + + "github.com/spf13/cobra" +) + +type InfraPod struct { + Component string `header:"component" json:"component"` + Size string `header:"size" json:"size"` + Cell string `header:"cell" json:"cell"` + TabletType string `header:"tablet type" json:"tablet_type"` + KeyspaceShard string `header:"keyspace/shard" json:"keyspace_shard"` + Ready string `header:"ready" json:"ready"` + Restarts int `header:"restarts" json:"restarts"` + Status string `header:"status" json:"status"` + Age string `header:"age" json:"age"` + Name string `header:"pod name" json:"name"` + + orig *ps.BranchInfraPod +} + +func (p *InfraPod) MarshalJSON() ([]byte, error) { + return json.MarshalIndent(p.orig, "", " ") +} + +func (p *InfraPod) MarshalCSVValue() interface{} { + return []*InfraPod{p} +} + +func toInfraPod(pod *ps.BranchInfraPod) *InfraPod { + tabletType := "-" + if pod.TabletType != nil { + tabletType = *pod.TabletType + } + + keyspaceShard := "-" + if pod.Keyspace != nil && pod.Shard != nil { + keyspaceShard = fmt.Sprintf("%s/%s", *pod.Keyspace, *pod.Shard) + } + + age := "-" + if pod.CreatedAt != nil { + age = humanAge(time.Since(*pod.CreatedAt)) + } + + return &InfraPod{ + Component: pod.Component, + Size: pod.Size, + Cell: pod.Cell, + TabletType: tabletType, + KeyspaceShard: keyspaceShard, + Ready: pod.Ready, + Restarts: pod.RestartCount, + Status: pod.Status, + Age: age, + Name: pod.Name, + orig: pod, + } +} + +func toInfraPods(pods []*ps.BranchInfraPod) []*InfraPod { + result := make([]*InfraPod, 0, len(pods)) + for _, pod := range pods { + result = append(result, toInfraPod(pod)) + } + return result +} + +func humanAge(d time.Duration) string { + if d < time.Minute { + return fmt.Sprintf("%ds", int(d.Seconds())) + } + if d < time.Hour { + return fmt.Sprintf("%dm", int(d.Minutes())) + } + if d < 24*time.Hour { + h := int(d.Hours()) + m := int(d.Minutes()) % 60 + if m == 0 { + return fmt.Sprintf("%dh", h) + } + return fmt.Sprintf("%dh%dm", h, m) + } + days := int(d.Hours()) / 24 + h := int(d.Hours()) % 24 + if h == 0 { + return fmt.Sprintf("%dd", days) + } + return fmt.Sprintf("%dd%dh", days, h) +} + +// InfraCmd shows infrastructure (pods) for a branch. +func InfraCmd(ch *cmdutil.Helper) *cobra.Command { + cmd := &cobra.Command{ + Use: "infra ", + Short: "Show infrastructure (pods) for a branch", + Hidden: true, + Args: cmdutil.RequiredArgs("database", "branch"), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := cmd.Context() + database := args[0] + branch := args[1] + + client, err := ch.Client() + if err != nil { + return err + } + + end := ch.Printer.PrintProgress(fmt.Sprintf("Fetching infrastructure for %s/%s", + printer.BoldBlue(database), printer.BoldBlue(branch))) + defer end() + + infra, err := client.BranchInfrastructure.Get(ctx, &ps.GetBranchInfrastructureRequest{ + Organization: ch.Config.Organization, + Database: database, + Branch: branch, + }) + if err != nil { + switch cmdutil.ErrCode(err) { + case ps.ErrNotFound: + return cmdutil.HandleNotFoundWithServiceTokenCheck( + ctx, cmd, ch.Config, ch.Client, err, "read_branch", + "branch %s does not exist in database %s (organization: %s)", + printer.BoldBlue(branch), printer.BoldBlue(database), printer.BoldBlue(ch.Config.Organization)) + default: + return cmdutil.HandleError(err) + } + } + + 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 + } + + return ch.Printer.PrintResource(toInfraPods(infra.Pods)) + }, + } + + return cmd +}