Skip to content

Commit 4c2a954

Browse files
authored
Merge pull request #1205 from planetscale/nick/branch-infra
Add branch infra command
2 parents 8916c19 + 5666a43 commit 4c2a954

4 files changed

Lines changed: 154 additions & 3 deletions

File tree

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ require (
2525
github.com/mattn/go-shellwords v1.0.12
2626
github.com/mitchellh/go-homedir v1.1.0
2727
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c
28-
github.com/planetscale/planetscale-go v0.151.0
28+
github.com/planetscale/planetscale-go v0.152.0
2929
github.com/planetscale/psdb v0.0.0-20250717190954-65c6661ab6e4
3030
github.com/planetscale/psdbproxy v0.0.0-20250728082226-3f4ea3a74ec7
3131
github.com/spf13/cobra v1.10.2

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -182,8 +182,8 @@ github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjL
182182
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
183183
github.com/planetscale/noglog v0.2.1-0.20210421230640-bea75fcd2e8e h1:MZ8D+Z3m2vvqGZLvoQfpaGg/j1fNDr4j03s3PRz4rVY=
184184
github.com/planetscale/noglog v0.2.1-0.20210421230640-bea75fcd2e8e/go.mod h1:hwAsSPQdvPa3WcfKfzTXxtEq/HlqwLjQasfO6QbGo4Q=
185-
github.com/planetscale/planetscale-go v0.151.0 h1:Vx1khlA76AnioSZzoY6gbJvXfMOKVWjjf4980bYgAA8=
186-
github.com/planetscale/planetscale-go v0.151.0/go.mod h1:mnADwPuBOmZaRCBbCzQna8N69vhlpEDCWGMF501qnEA=
185+
github.com/planetscale/planetscale-go v0.152.0 h1:iFuW/9Mk57Cn8fdKEsAzMAktq5ukO7Cjm0S0ISiJPDU=
186+
github.com/planetscale/planetscale-go v0.152.0/go.mod h1:mnADwPuBOmZaRCBbCzQna8N69vhlpEDCWGMF501qnEA=
187187
github.com/planetscale/psdb v0.0.0-20250717190954-65c6661ab6e4 h1:Xv5pj20Rhfty1Tv0OVcidg4ez4PvGrpKvb6rvUwQgDs=
188188
github.com/planetscale/psdb v0.0.0-20250717190954-65c6661ab6e4/go.mod h1:M52h5IWxAcbdQ1hSZrLAGQC4ZXslxEsK/Wh9nu3wdWs=
189189
github.com/planetscale/psdbproxy v0.0.0-20250728082226-3f4ea3a74ec7 h1:aRd6vdE1fyuSI4RVj7oCr8lFmgqXvpnPUmN85VbZCp8=

internal/cmd/branch/branch.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ func BranchCmd(ch *cmdutil.Helper) *cobra.Command {
3636
cmd.AddCommand(SafeMigrationsCmd(ch))
3737
cmd.AddCommand(LintCmd(ch))
3838
cmd.AddCommand(vtctld.VtctldCmd(ch))
39+
cmd.AddCommand(InfraCmd(ch))
3940

4041
return cmd
4142
}

internal/cmd/branch/infra.go

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
package branch
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"time"
7+
8+
"github.com/planetscale/cli/internal/cmdutil"
9+
"github.com/planetscale/cli/internal/printer"
10+
ps "github.com/planetscale/planetscale-go/planetscale"
11+
12+
"github.com/spf13/cobra"
13+
)
14+
15+
type InfraPod struct {
16+
Component string `header:"component" json:"component"`
17+
Size string `header:"size" json:"size"`
18+
Cell string `header:"cell" json:"cell"`
19+
TabletType string `header:"tablet type" json:"tablet_type"`
20+
KeyspaceShard string `header:"keyspace/shard" json:"keyspace_shard"`
21+
Ready string `header:"ready" json:"ready"`
22+
Restarts int `header:"restarts" json:"restarts"`
23+
Status string `header:"status" json:"status"`
24+
Age string `header:"age" json:"age"`
25+
Name string `header:"pod name" json:"name"`
26+
27+
orig *ps.BranchInfraPod
28+
}
29+
30+
func (p *InfraPod) MarshalJSON() ([]byte, error) {
31+
return json.MarshalIndent(p.orig, "", " ")
32+
}
33+
34+
func (p *InfraPod) MarshalCSVValue() interface{} {
35+
return []*InfraPod{p}
36+
}
37+
38+
func toInfraPod(pod *ps.BranchInfraPod) *InfraPod {
39+
tabletType := "-"
40+
if pod.TabletType != nil {
41+
tabletType = *pod.TabletType
42+
}
43+
44+
keyspaceShard := "-"
45+
if pod.Keyspace != nil && pod.Shard != nil {
46+
keyspaceShard = fmt.Sprintf("%s/%s", *pod.Keyspace, *pod.Shard)
47+
}
48+
49+
age := "-"
50+
if pod.CreatedAt != nil {
51+
age = humanAge(time.Since(*pod.CreatedAt))
52+
}
53+
54+
return &InfraPod{
55+
Component: pod.Component,
56+
Size: pod.Size,
57+
Cell: pod.Cell,
58+
TabletType: tabletType,
59+
KeyspaceShard: keyspaceShard,
60+
Ready: pod.Ready,
61+
Restarts: pod.RestartCount,
62+
Status: pod.Status,
63+
Age: age,
64+
Name: pod.Name,
65+
orig: pod,
66+
}
67+
}
68+
69+
func toInfraPods(pods []*ps.BranchInfraPod) []*InfraPod {
70+
result := make([]*InfraPod, 0, len(pods))
71+
for _, pod := range pods {
72+
result = append(result, toInfraPod(pod))
73+
}
74+
return result
75+
}
76+
77+
func humanAge(d time.Duration) string {
78+
if d < time.Minute {
79+
return fmt.Sprintf("%ds", int(d.Seconds()))
80+
}
81+
if d < time.Hour {
82+
return fmt.Sprintf("%dm", int(d.Minutes()))
83+
}
84+
if d < 24*time.Hour {
85+
h := int(d.Hours())
86+
m := int(d.Minutes()) % 60
87+
if m == 0 {
88+
return fmt.Sprintf("%dh", h)
89+
}
90+
return fmt.Sprintf("%dh%dm", h, m)
91+
}
92+
days := int(d.Hours()) / 24
93+
h := int(d.Hours()) % 24
94+
if h == 0 {
95+
return fmt.Sprintf("%dd", days)
96+
}
97+
return fmt.Sprintf("%dd%dh", days, h)
98+
}
99+
100+
// InfraCmd shows infrastructure (pods) for a branch.
101+
func InfraCmd(ch *cmdutil.Helper) *cobra.Command {
102+
cmd := &cobra.Command{
103+
Use: "infra <database> <branch>",
104+
Short: "Show infrastructure (pods) for a branch",
105+
Hidden: true,
106+
Args: cmdutil.RequiredArgs("database", "branch"),
107+
RunE: func(cmd *cobra.Command, args []string) error {
108+
ctx := cmd.Context()
109+
database := args[0]
110+
branch := args[1]
111+
112+
client, err := ch.Client()
113+
if err != nil {
114+
return err
115+
}
116+
117+
end := ch.Printer.PrintProgress(fmt.Sprintf("Fetching infrastructure for %s/%s",
118+
printer.BoldBlue(database), printer.BoldBlue(branch)))
119+
defer end()
120+
121+
infra, err := client.BranchInfrastructure.Get(ctx, &ps.GetBranchInfrastructureRequest{
122+
Organization: ch.Config.Organization,
123+
Database: database,
124+
Branch: branch,
125+
})
126+
if err != nil {
127+
switch cmdutil.ErrCode(err) {
128+
case ps.ErrNotFound:
129+
return cmdutil.HandleNotFoundWithServiceTokenCheck(
130+
ctx, cmd, ch.Config, ch.Client, err, "read_branch",
131+
"branch %s does not exist in database %s (organization: %s)",
132+
printer.BoldBlue(branch), printer.BoldBlue(database), printer.BoldBlue(ch.Config.Organization))
133+
default:
134+
return cmdutil.HandleError(err)
135+
}
136+
}
137+
138+
end()
139+
140+
if len(infra.Pods) == 0 && ch.Printer.Format() == printer.Human {
141+
ch.Printer.Printf("No pods found for branch %s.\n", printer.BoldBlue(branch))
142+
return nil
143+
}
144+
145+
return ch.Printer.PrintResource(toInfraPods(infra.Pods))
146+
},
147+
}
148+
149+
return cmd
150+
}

0 commit comments

Comments
 (0)