Skip to content

Commit b4c2853

Browse files
committed
chore: remove org context switcher in the cli
1 parent 30c4b4d commit b4c2853

File tree

8 files changed

+98
-172
lines changed

8 files changed

+98
-172
lines changed

cli/create.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ func (r *RootCmd) create() *serpent.Command {
2929
parameterFlags workspaceParameterFlags
3030
autoUpdates string
3131
copyParametersFrom string
32+
orgContext = NewOrganizationContext()
3233
)
3334
client := new(codersdk.Client)
3435
cmd := &serpent.Command{
@@ -43,7 +44,7 @@ func (r *RootCmd) create() *serpent.Command {
4344
),
4445
Middleware: serpent.Chain(r.InitClient(client)),
4546
Handler: func(inv *serpent.Invocation) error {
46-
organization, err := CurrentOrganization(r, inv, client)
47+
organization, err := orgContext.Selected(inv, client)
4748
if err != nil {
4849
return err
4950
}
@@ -269,6 +270,7 @@ func (r *RootCmd) create() *serpent.Command {
269270
)
270271
cmd.Options = append(cmd.Options, parameterFlags.cliParameters()...)
271272
cmd.Options = append(cmd.Options, parameterFlags.cliParameterDefaults()...)
273+
orgContext.AttachOptions(cmd)
272274
return cmd
273275
}
274276

cli/login.go

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -358,13 +358,6 @@ func (r *RootCmd) login() *serpent.Command {
358358
return xerrors.Errorf("write server url: %w", err)
359359
}
360360

361-
// If the current organization cannot be fetched, then reset the organization context.
362-
// Otherwise, organization cli commands will fail.
363-
_, err = CurrentOrganization(r, inv, client)
364-
if err != nil {
365-
_ = config.Organization().Delete()
366-
}
367-
368361
_, _ = fmt.Fprintf(inv.Stdout, Caret+"Welcome to Coder, %s! You're authenticated.\n", pretty.Sprint(cliui.DefaultStyles.Keyword, resp.Username))
369362
return nil
370363
},

cli/organization.go

Lines changed: 33 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
package cli
22

33
import (
4-
"errors"
54
"fmt"
6-
"os"
75
"slices"
86
"strings"
97

@@ -17,6 +15,8 @@ import (
1715
)
1816

1917
func (r *RootCmd) organizations() *serpent.Command {
18+
orgContext := NewOrganizationContext()
19+
2020
cmd := &serpent.Command{
2121
Use: "organizations [subcommand]",
2222
Short: "Organization related commands",
@@ -26,114 +26,14 @@ func (r *RootCmd) organizations() *serpent.Command {
2626
return inv.Command.HelpHandler(inv)
2727
},
2828
Children: []*serpent.Command{
29-
r.currentOrganization(),
30-
r.switchOrganization(),
29+
r.showOrganization(orgContext),
3130
r.createOrganization(),
32-
r.organizationMembers(),
33-
r.organizationRoles(),
34-
},
35-
}
36-
37-
cmd.Options = serpent.OptionSet{}
38-
return cmd
39-
}
40-
41-
func (r *RootCmd) switchOrganization() *serpent.Command {
42-
client := new(codersdk.Client)
43-
44-
cmd := &serpent.Command{
45-
Use: "set <organization name | ID>",
46-
Short: "set the organization used by the CLI. Pass an empty string to reset to the default organization.",
47-
Long: "set the organization used by the CLI. Pass an empty string to reset to the default organization.\n" + FormatExamples(
48-
Example{
49-
Description: "Remove the current organization and defer to the default.",
50-
Command: "coder organizations set ''",
51-
},
52-
Example{
53-
Description: "Switch to a custom organization.",
54-
Command: "coder organizations set my-org",
55-
},
56-
),
57-
Middleware: serpent.Chain(
58-
r.InitClient(client),
59-
serpent.RequireRangeArgs(0, 1),
60-
),
61-
Options: serpent.OptionSet{},
62-
Handler: func(inv *serpent.Invocation) error {
63-
conf := r.createConfig()
64-
orgs, err := client.OrganizationsByUser(inv.Context(), codersdk.Me)
65-
if err != nil {
66-
return xerrors.Errorf("failed to get organizations: %w", err)
67-
}
68-
// Keep the list of orgs sorted
69-
slices.SortFunc(orgs, func(a, b codersdk.Organization) int {
70-
return strings.Compare(a.Name, b.Name)
71-
})
72-
73-
var switchToOrg string
74-
if len(inv.Args) == 0 {
75-
// Pull switchToOrg from a prompt selector, rather than command line
76-
// args.
77-
switchToOrg, err = promptUserSelectOrg(inv, conf, orgs)
78-
if err != nil {
79-
return err
80-
}
81-
} else {
82-
switchToOrg = inv.Args[0]
83-
}
84-
85-
// If the user passes an empty string, we want to remove the organization
86-
// from the config file. This will defer to default behavior.
87-
if switchToOrg == "" {
88-
err := conf.Organization().Delete()
89-
if err != nil && !errors.Is(err, os.ErrNotExist) {
90-
return xerrors.Errorf("failed to unset organization: %w", err)
91-
}
92-
_, _ = fmt.Fprintf(inv.Stdout, "Organization unset\n")
93-
} else {
94-
// Find the selected org in our list.
95-
index := slices.IndexFunc(orgs, func(org codersdk.Organization) bool {
96-
return org.Name == switchToOrg || org.ID.String() == switchToOrg
97-
})
98-
if index < 0 {
99-
// Using this error for better error message formatting
100-
err := &codersdk.Error{
101-
Response: codersdk.Response{
102-
Message: fmt.Sprintf("Organization %q not found. Is the name correct, and are you a member of it?", switchToOrg),
103-
Detail: "Ensure the organization argument is correct and you are a member of it.",
104-
},
105-
Helper: fmt.Sprintf("Valid organizations you can switch to: %s", strings.Join(orgNames(orgs), ", ")),
106-
}
107-
return err
108-
}
109-
110-
// Always write the uuid to the config file. Names can change.
111-
err := conf.Organization().Write(orgs[index].ID.String())
112-
if err != nil {
113-
return xerrors.Errorf("failed to write organization to config file: %w", err)
114-
}
115-
}
116-
117-
// Verify it worked.
118-
current, err := CurrentOrganization(r, inv, client)
119-
if err != nil {
120-
// An SDK error could be a permission error. So offer the advice to unset the org
121-
// and reset the context.
122-
var sdkError *codersdk.Error
123-
if errors.As(err, &sdkError) {
124-
if sdkError.Helper == "" && sdkError.StatusCode() != 500 {
125-
sdkError.Helper = `If this error persists, try unsetting your org with 'coder organizations set ""'`
126-
}
127-
return sdkError
128-
}
129-
return xerrors.Errorf("failed to get current organization: %w", err)
130-
}
131-
132-
_, _ = fmt.Fprintf(inv.Stdout, "Current organization context set to %s (%s)\n", current.Name, current.ID.String())
133-
return nil
31+
r.organizationMembers(orgContext),
32+
r.organizationRoles(orgContext),
13433
},
13534
}
13635

36+
orgContext.AttachOptions(cmd)
13737
return cmd
13838
}
13939

@@ -207,7 +107,7 @@ func orgNames(orgs []codersdk.Organization) []string {
207107
return names
208108
}
209109

210-
func (r *RootCmd) currentOrganization() *serpent.Command {
110+
func (r *RootCmd) showOrganization(orgContext *OrganizationContext) *serpent.Command {
211111
var (
212112
stringFormat func(orgs []codersdk.Organization) (string, error)
213113
client = new(codersdk.Client)
@@ -226,8 +126,29 @@ func (r *RootCmd) currentOrganization() *serpent.Command {
226126
onlyID = false
227127
)
228128
cmd := &serpent.Command{
229-
Use: "show [current|me|uuid]",
230-
Short: "Show the organization, if no argument is given, the organization currently in use will be shown.",
129+
Use: "show [\"selected\"|\"me\"|uuid|org_name]",
130+
Short: "Show the organization. " +
131+
"Using \"selected\" will show the selected organization from the \"--org\" flag. " +
132+
"Using \"me\" will show all organizations you are a member of.",
133+
Long: FormatExamples(
134+
Example{
135+
Description: "coder org show selected",
136+
Command: "Shows the organizations selected with '--org=<org_name>'. " +
137+
"This organization is the organization used by the cli.",
138+
},
139+
Example{
140+
Description: "coder org show me",
141+
Command: "List of all organizations you are a member of.",
142+
},
143+
Example{
144+
Description: "coder org show developers",
145+
Command: "Show organization with name 'developers'",
146+
},
147+
Example{
148+
Description: "coder org show 90ee1875-3db5-43b3-828e-af3687522e43",
149+
Command: "Show organization with the given ID.",
150+
},
151+
),
231152
Middleware: serpent.Chain(
232153
r.InitClient(client),
233154
serpent.RequireRangeArgs(0, 1),
@@ -242,22 +163,22 @@ func (r *RootCmd) currentOrganization() *serpent.Command {
242163
},
243164
},
244165
Handler: func(inv *serpent.Invocation) error {
245-
orgArg := "current"
166+
orgArg := "selected"
246167
if len(inv.Args) >= 1 {
247168
orgArg = inv.Args[0]
248169
}
249170

250171
var orgs []codersdk.Organization
251172
var err error
252173
switch strings.ToLower(orgArg) {
253-
case "current":
174+
case "selected":
254175
stringFormat = func(orgs []codersdk.Organization) (string, error) {
255176
if len(orgs) != 1 {
256177
return "", xerrors.Errorf("expected 1 organization, got %d", len(orgs))
257178
}
258179
return fmt.Sprintf("Current CLI Organization: %s (%s)\n", orgs[0].Name, orgs[0].ID.String()), nil
259180
}
260-
org, err := CurrentOrganization(r, inv, client)
181+
org, err := orgContext.Selected(inv, client)
261182
if err != nil {
262183
return err
263184
}

cli/organizationmembers.go

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,16 @@ import (
1111
"github.com/coder/serpent"
1212
)
1313

14-
func (r *RootCmd) organizationMembers() *serpent.Command {
14+
func (r *RootCmd) organizationMembers(orgContext *OrganizationContext) *serpent.Command {
1515
cmd := &serpent.Command{
1616
Use: "members",
1717
Aliases: []string{"member"},
1818
Short: "Manage organization members",
1919
Children: []*serpent.Command{
20-
r.listOrganizationMembers(),
21-
r.assignOrganizationRoles(),
22-
r.addOrganizationMember(),
23-
r.removeOrganizationMember(),
20+
r.listOrganizationMembers(orgContext),
21+
r.assignOrganizationRoles(orgContext),
22+
r.addOrganizationMember(orgContext),
23+
r.removeOrganizationMember(orgContext),
2424
},
2525
Handler: func(inv *serpent.Invocation) error {
2626
return inv.Command.HelpHandler(inv)
@@ -30,7 +30,7 @@ func (r *RootCmd) organizationMembers() *serpent.Command {
3030
return cmd
3131
}
3232

33-
func (r *RootCmd) removeOrganizationMember() *serpent.Command {
33+
func (r *RootCmd) removeOrganizationMember(orgContext *OrganizationContext) *serpent.Command {
3434
client := new(codersdk.Client)
3535

3636
cmd := &serpent.Command{
@@ -42,7 +42,7 @@ func (r *RootCmd) removeOrganizationMember() *serpent.Command {
4242
),
4343
Handler: func(inv *serpent.Invocation) error {
4444
ctx := inv.Context()
45-
organization, err := CurrentOrganization(r, inv, client)
45+
organization, err := orgContext.Selected(inv, client)
4646
if err != nil {
4747
return err
4848
}
@@ -61,7 +61,7 @@ func (r *RootCmd) removeOrganizationMember() *serpent.Command {
6161
return cmd
6262
}
6363

64-
func (r *RootCmd) addOrganizationMember() *serpent.Command {
64+
func (r *RootCmd) addOrganizationMember(orgContext *OrganizationContext) *serpent.Command {
6565
client := new(codersdk.Client)
6666

6767
cmd := &serpent.Command{
@@ -73,7 +73,7 @@ func (r *RootCmd) addOrganizationMember() *serpent.Command {
7373
),
7474
Handler: func(inv *serpent.Invocation) error {
7575
ctx := inv.Context()
76-
organization, err := CurrentOrganization(r, inv, client)
76+
organization, err := orgContext.Selected(inv, client)
7777
if err != nil {
7878
return err
7979
}
@@ -92,7 +92,7 @@ func (r *RootCmd) addOrganizationMember() *serpent.Command {
9292
return cmd
9393
}
9494

95-
func (r *RootCmd) assignOrganizationRoles() *serpent.Command {
95+
func (r *RootCmd) assignOrganizationRoles(orgContext *OrganizationContext) *serpent.Command {
9696
client := new(codersdk.Client)
9797

9898
cmd := &serpent.Command{
@@ -104,7 +104,7 @@ func (r *RootCmd) assignOrganizationRoles() *serpent.Command {
104104
),
105105
Handler: func(inv *serpent.Invocation) error {
106106
ctx := inv.Context()
107-
organization, err := CurrentOrganization(r, inv, client)
107+
organization, err := orgContext.Selected(inv, client)
108108
if err != nil {
109109
return err
110110
}
@@ -135,7 +135,7 @@ func (r *RootCmd) assignOrganizationRoles() *serpent.Command {
135135
return cmd
136136
}
137137

138-
func (r *RootCmd) listOrganizationMembers() *serpent.Command {
138+
func (r *RootCmd) listOrganizationMembers(orgContext *OrganizationContext) *serpent.Command {
139139
formatter := cliui.NewOutputFormatter(
140140
cliui.TableFormat([]codersdk.OrganizationMemberWithName{}, []string{"username", "organization_roles"}),
141141
cliui.JSONFormat(),
@@ -151,7 +151,7 @@ func (r *RootCmd) listOrganizationMembers() *serpent.Command {
151151
),
152152
Handler: func(inv *serpent.Invocation) error {
153153
ctx := inv.Context()
154-
organization, err := CurrentOrganization(r, inv, client)
154+
organization, err := orgContext.Selected(inv, client)
155155
if err != nil {
156156
return err
157157
}

cli/organizationroles.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import (
1616
"github.com/coder/serpent"
1717
)
1818

19-
func (r *RootCmd) organizationRoles() *serpent.Command {
19+
func (r *RootCmd) organizationRoles(orgContext *OrganizationContext) *serpent.Command {
2020
cmd := &serpent.Command{
2121
Use: "roles",
2222
Short: "Manage organization roles.",
@@ -26,14 +26,14 @@ func (r *RootCmd) organizationRoles() *serpent.Command {
2626
},
2727
Hidden: true,
2828
Children: []*serpent.Command{
29-
r.showOrganizationRoles(),
30-
r.editOrganizationRole(),
29+
r.showOrganizationRoles(orgContext),
30+
r.editOrganizationRole(orgContext),
3131
},
3232
}
3333
return cmd
3434
}
3535

36-
func (r *RootCmd) showOrganizationRoles() *serpent.Command {
36+
func (r *RootCmd) showOrganizationRoles(orgContext *OrganizationContext) *serpent.Command {
3737
formatter := cliui.NewOutputFormatter(
3838
cliui.ChangeFormatterData(
3939
cliui.TableFormat([]roleTableRow{}, []string{"name", "display_name", "site_permissions", "organization_permissions", "user_permissions"}),
@@ -63,7 +63,7 @@ func (r *RootCmd) showOrganizationRoles() *serpent.Command {
6363
),
6464
Handler: func(inv *serpent.Invocation) error {
6565
ctx := inv.Context()
66-
org, err := CurrentOrganization(r, inv, client)
66+
org, err := orgContext.Selected(inv, client)
6767
if err != nil {
6868
return err
6969
}
@@ -100,7 +100,7 @@ func (r *RootCmd) showOrganizationRoles() *serpent.Command {
100100
return cmd
101101
}
102102

103-
func (r *RootCmd) editOrganizationRole() *serpent.Command {
103+
func (r *RootCmd) editOrganizationRole(orgContext *OrganizationContext) *serpent.Command {
104104
formatter := cliui.NewOutputFormatter(
105105
cliui.ChangeFormatterData(
106106
cliui.TableFormat([]roleTableRow{}, []string{"name", "display_name", "site_permissions", "organization_permissions", "user_permissions"}),
@@ -148,7 +148,7 @@ func (r *RootCmd) editOrganizationRole() *serpent.Command {
148148
),
149149
Handler: func(inv *serpent.Invocation) error {
150150
ctx := inv.Context()
151-
org, err := CurrentOrganization(r, inv, client)
151+
org, err := orgContext.Selected(inv, client)
152152
if err != nil {
153153
return err
154154
}

0 commit comments

Comments
 (0)