Skip to content

Commit 5179a75

Browse files
Merge pull request #1162 from planetscale/current-org
Add `current` to `org list` output
2 parents 9c00057 + 13f4129 commit 5179a75

File tree

3 files changed

+200
-7
lines changed

3 files changed

+200
-7
lines changed

internal/cmd/org/list.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@ func ListCmd(ch *cmdutil.Helper) *cobra.Command {
3030
return nil
3131
}
3232

33-
return ch.Printer.PrintResource(toOrgs(orgs))
33+
currentOrgName := getCurrentOrganization(ch)
34+
35+
return ch.Printer.PrintResource(toOrgs(orgs, currentOrgName, ch.Printer.Format()))
3436
},
3537
}
3638

internal/cmd/org/list_test.go

Lines changed: 159 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"bytes"
55
"context"
66
"testing"
7+
"testing/fstest"
78

89
"github.com/planetscale/cli/internal/cmdutil"
910
"github.com/planetscale/cli/internal/config"
@@ -33,11 +34,167 @@ func TestOrganization_ListCmd(t *testing.T) {
3334
},
3435
}
3536

37+
fs := fstest.MapFS{
38+
".pscale.yml": &fstest.MapFile{
39+
Data: []byte("org: " + org + "\n"),
40+
},
41+
}
42+
3643
ch := &cmdutil.Helper{
3744
Printer: p,
3845
Config: &config.Config{
3946
Organization: org,
4047
},
48+
ConfigFS: config.NewConfigFS(fs),
49+
Client: func() (*ps.Client, error) {
50+
return &ps.Client{
51+
Organizations: svc,
52+
}, nil
53+
},
54+
}
55+
56+
cmd := ListCmd(ch)
57+
err := cmd.Execute()
58+
59+
c.Assert(err, qt.IsNil)
60+
c.Assert(svc.ListFnInvoked, qt.IsTrue)
61+
62+
orgs := []*organization{
63+
{Name: "foo", Current: false},
64+
{Name: "bar", Current: false},
65+
}
66+
c.Assert(buf.String(), qt.JSONEquals, orgs)
67+
}
68+
69+
func TestOrganization_ListCmd_WithCurrentOrg(t *testing.T) {
70+
c := qt.New(t)
71+
72+
var buf bytes.Buffer
73+
format := printer.JSON
74+
p := printer.NewPrinter(&format)
75+
p.SetResourceOutput(&buf)
76+
77+
currentOrg := "foo"
78+
79+
svc := &mock.OrganizationsService{
80+
ListFn: func(ctx context.Context) ([]*ps.Organization, error) {
81+
return []*ps.Organization{
82+
{Name: "foo"},
83+
{Name: "bar"},
84+
}, nil
85+
},
86+
}
87+
88+
fs := fstest.MapFS{
89+
".pscale.yml": &fstest.MapFile{
90+
Data: []byte("org: " + currentOrg + "\n"),
91+
},
92+
}
93+
94+
ch := &cmdutil.Helper{
95+
Printer: p,
96+
Config: &config.Config{
97+
Organization: currentOrg,
98+
},
99+
ConfigFS: config.NewConfigFS(fs),
100+
Client: func() (*ps.Client, error) {
101+
return &ps.Client{
102+
Organizations: svc,
103+
}, nil
104+
},
105+
}
106+
107+
cmd := ListCmd(ch)
108+
err := cmd.Execute()
109+
110+
c.Assert(err, qt.IsNil)
111+
c.Assert(svc.ListFnInvoked, qt.IsTrue)
112+
113+
orgs := []*organization{
114+
{Name: "foo", Current: true},
115+
{Name: "bar", Current: false},
116+
}
117+
c.Assert(buf.String(), qt.JSONEquals, orgs)
118+
}
119+
120+
func TestOrganization_ListCmd_HumanFormat(t *testing.T) {
121+
c := qt.New(t)
122+
123+
var buf bytes.Buffer
124+
format := printer.Human
125+
p := printer.NewPrinter(&format)
126+
p.SetResourceOutput(&buf)
127+
128+
currentOrg := "foo"
129+
130+
svc := &mock.OrganizationsService{
131+
ListFn: func(ctx context.Context) ([]*ps.Organization, error) {
132+
return []*ps.Organization{
133+
{Name: "foo"},
134+
{Name: "bar"},
135+
}, nil
136+
},
137+
}
138+
139+
fs := fstest.MapFS{
140+
".pscale.yml": &fstest.MapFile{
141+
Data: []byte("org: " + currentOrg + "\n"),
142+
},
143+
}
144+
145+
ch := &cmdutil.Helper{
146+
Printer: p,
147+
Config: &config.Config{
148+
Organization: currentOrg,
149+
},
150+
ConfigFS: config.NewConfigFS(fs),
151+
Client: func() (*ps.Client, error) {
152+
return &ps.Client{
153+
Organizations: svc,
154+
}, nil
155+
},
156+
}
157+
158+
cmd := ListCmd(ch)
159+
err := cmd.Execute()
160+
161+
c.Assert(err, qt.IsNil)
162+
c.Assert(svc.ListFnInvoked, qt.IsTrue)
163+
164+
// For human format, the current org should have an asterisk prefix
165+
output := buf.String()
166+
c.Assert(output, qt.Contains, "* foo")
167+
c.Assert(output, qt.Contains, "bar")
168+
169+
c.Assert(output, qt.Not(qt.Contains), "* bar")
170+
}
171+
172+
func TestOrganization_ListCmd_NoConfig(t *testing.T) {
173+
c := qt.New(t)
174+
175+
var buf bytes.Buffer
176+
format := printer.JSON
177+
p := printer.NewPrinter(&format)
178+
p.SetResourceOutput(&buf)
179+
180+
svc := &mock.OrganizationsService{
181+
ListFn: func(ctx context.Context) ([]*ps.Organization, error) {
182+
return []*ps.Organization{
183+
{Name: "foo"},
184+
{Name: "bar"},
185+
}, nil
186+
},
187+
}
188+
189+
// Create an empty filesystem (no config file)
190+
fs := fstest.MapFS{}
191+
192+
ch := &cmdutil.Helper{
193+
Printer: p,
194+
Config: &config.Config{
195+
Organization: "",
196+
},
197+
ConfigFS: config.NewConfigFS(fs),
41198
Client: func() (*ps.Client, error) {
42199
return &ps.Client{
43200
Organizations: svc,
@@ -52,8 +209,8 @@ func TestOrganization_ListCmd(t *testing.T) {
52209
c.Assert(svc.ListFnInvoked, qt.IsTrue)
53210

54211
orgs := []*organization{
55-
{Name: "foo"},
56-
{Name: "bar"},
212+
{Name: "foo", Current: false},
213+
{Name: "bar", Current: false},
57214
}
58215
c.Assert(buf.String(), qt.JSONEquals, orgs)
59216
}

internal/cmd/org/org.go

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package org
22

33
import (
44
"github.com/planetscale/cli/internal/cmdutil"
5+
"github.com/planetscale/cli/internal/config"
56
"github.com/planetscale/cli/internal/printer"
67
ps "github.com/planetscale/planetscale-go/planetscale"
78
"github.com/spf13/cobra"
@@ -26,23 +27,56 @@ type organization struct {
2627
Name string `header:"name" json:"name"`
2728
CreatedAt int64 `header:"created_at,timestamp(ms|utc|human)" json:"created_at"`
2829
UpdatedAt int64 `header:"updated_at,timestamp(ms|utc|human)" json:"updated_at"`
30+
Current bool `header:"current" json:"current"`
2931
}
3032

3133
// toOrgs returns a slice of printable orgs.
32-
func toOrgs(organizations []*ps.Organization) []*organization {
34+
func toOrgs(organizations []*ps.Organization, currentOrgName string, format printer.Format) []*organization {
3335
orgs := make([]*organization, 0, len(organizations))
3436

3537
for _, org := range organizations {
36-
orgs = append(orgs, toOrg(org))
38+
orgs = append(orgs, toOrg(org, currentOrgName, format))
3739
}
3840

3941
return orgs
4042
}
4143

42-
func toOrg(org *ps.Organization) *organization {
44+
func toOrg(org *ps.Organization, currentOrgName string, format printer.Format) *organization {
45+
isCurrent := org.Name == currentOrgName
46+
name := org.Name
47+
48+
if isCurrent && format == printer.Human {
49+
name = "* " + org.Name
50+
}
51+
4352
return &organization{
44-
Name: org.Name,
53+
Name: name,
4554
CreatedAt: printer.GetMilliseconds(org.CreatedAt),
4655
UpdatedAt: printer.GetMilliseconds(org.UpdatedAt),
56+
Current: isCurrent,
57+
}
58+
}
59+
60+
func getCurrentOrganization(ch *cmdutil.Helper) string {
61+
if ch.Config.Organization != "" {
62+
return ch.Config.Organization
4763
}
64+
65+
configPath, err := config.ProjectConfigPath()
66+
if err == nil {
67+
cfg, err := ch.ConfigFS.NewFileConfig(configPath)
68+
if err == nil && cfg.Organization != "" {
69+
return cfg.Organization
70+
}
71+
}
72+
73+
configPath, err = config.DefaultConfigPath()
74+
if err == nil {
75+
cfg, err := ch.ConfigFS.NewFileConfig(configPath)
76+
if err == nil && cfg.Organization != "" {
77+
return cfg.Organization
78+
}
79+
}
80+
81+
return ""
4882
}

0 commit comments

Comments
 (0)