Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit5bf46f3

Browse files
authored
chore: remove org context switcher in the cli (#13674)
* chore: remove org context switcher in the cli
1 parent4a0fd74 commit5bf46f3

File tree

52 files changed

+353
-362
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+353
-362
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
parameterFlagsworkspaceParameterFlags
3030
autoUpdatesstring
3131
copyParametersFromstring
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
iferr!=nil {
4849
returnerr
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
returncmd
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
returnxerrors.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-
iferr!=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
returnnil
370363
},

‎cli/login_test.go

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,9 @@ import (
55
"fmt"
66
"net/http"
77
"net/http/httptest"
8-
"os"
98
"runtime"
109
"testing"
1110

12-
"github.com/google/uuid"
1311
"github.com/stretchr/testify/assert"
1412
"github.com/stretchr/testify/require"
1513

@@ -424,29 +422,6 @@ func TestLogin(t *testing.T) {
424422
require.NotEqual(t,client.SessionToken(),sessionFile)
425423
})
426424

427-
// Login should reset the configured organization if the user is not a member
428-
t.Run("ResetOrganization",func(t*testing.T) {
429-
t.Parallel()
430-
client:=coderdtest.New(t,nil)
431-
coderdtest.CreateFirstUser(t,client)
432-
root,cfg:=clitest.New(t,"login",client.URL.String(),"--token",client.SessionToken())
433-
434-
notRealOrg:=uuid.NewString()
435-
err:=cfg.Organization().Write(notRealOrg)
436-
require.NoError(t,err,"write bad org to config")
437-
438-
err=root.Run()
439-
require.NoError(t,err)
440-
sessionFile,err:=cfg.Session().Read()
441-
require.NoError(t,err)
442-
require.NotEqual(t,client.SessionToken(),sessionFile)
443-
444-
// Organization config should be deleted since the org does not exist
445-
selected,err:=cfg.Organization().Read()
446-
require.ErrorIs(t,err,os.ErrNotExist)
447-
require.NotEqual(t,selected,notRealOrg)
448-
})
449-
450425
t.Run("KeepOrganizationContext",func(t*testing.T) {
451426
t.Parallel()
452427
client:=coderdtest.New(t,nil)

‎cli/organization.go

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

33
import (
4-
"errors"
54
"fmt"
6-
"os"
7-
"slices"
85
"strings"
96

107
"golang.org/x/xerrors"
118

129
"github.com/coder/coder/v2/cli/cliui"
13-
"github.com/coder/coder/v2/cli/config"
1410
"github.com/coder/coder/v2/codersdk"
15-
"github.com/coder/pretty"
1611
"github.com/coder/serpent"
1712
)
1813

1914
func (r*RootCmd)organizations()*serpent.Command {
15+
orgContext:=NewOrganizationContext()
16+
2017
cmd:=&serpent.Command{
2118
Use:"organizations [subcommand]",
2219
Short:"Organization related commands",
@@ -26,188 +23,18 @@ func (r *RootCmd) organizations() *serpent.Command {
2623
returninv.Command.HelpHandler(inv)
2724
},
2825
Children: []*serpent.Command{
29-
r.currentOrganization(),
30-
r.switchOrganization(),
26+
r.showOrganization(orgContext),
3127
r.createOrganization(),
32-
r.organizationMembers(),
33-
r.organizationRoles(),
28+
r.organizationMembers(orgContext),
29+
r.organizationRoles(orgContext),
3430
},
3531
}
3632

37-
cmd.Options= serpent.OptionSet{}
33+
orgContext.AttachOptions(cmd)
3834
returncmd
3935
}
4036

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-
iferr!=nil {
66-
returnxerrors.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-
returnstrings.Compare(a.Name,b.Name)
71-
})
72-
73-
varswitchToOrgstring
74-
iflen(inv.Args)==0 {
75-
// Pull switchToOrg from a prompt selector, rather than command line
76-
// args.
77-
switchToOrg,err=promptUserSelectOrg(inv,conf,orgs)
78-
iferr!=nil {
79-
returnerr
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-
ifswitchToOrg=="" {
88-
err:=conf.Organization().Delete()
89-
iferr!=nil&&!errors.Is(err,os.ErrNotExist) {
90-
returnxerrors.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-
returnorg.Name==switchToOrg||org.ID.String()==switchToOrg
97-
})
98-
ifindex<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-
returnerr
108-
}
109-
110-
// Always write the uuid to the config file. Names can change.
111-
err:=conf.Organization().Write(orgs[index].ID.String())
112-
iferr!=nil {
113-
returnxerrors.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-
iferr!=nil {
120-
// An SDK error could be a permission error. So offer the advice to unset the org
121-
// and reset the context.
122-
varsdkError*codersdk.Error
123-
iferrors.As(err,&sdkError) {
124-
ifsdkError.Helper==""&&sdkError.StatusCode()!=500 {
125-
sdkError.Helper=`If this error persists, try unsetting your org with 'coder organizations set ""'`
126-
}
127-
returnsdkError
128-
}
129-
returnxerrors.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-
returnnil
134-
},
135-
}
136-
137-
returncmd
138-
}
139-
140-
// promptUserSelectOrg will prompt the user to select an organization from a list
141-
// of their organizations.
142-
funcpromptUserSelectOrg(inv*serpent.Invocation,conf config.Root,orgs []codersdk.Organization) (string,error) {
143-
// Default choice
144-
vardefaultOrgstring
145-
// Comes from config file
146-
ifconf.Organization().Exists() {
147-
defaultOrg,_=conf.Organization().Read()
148-
}
149-
150-
// No config? Comes from default org in the list
151-
ifdefaultOrg=="" {
152-
defIndex:=slices.IndexFunc(orgs,func(org codersdk.Organization)bool {
153-
returnorg.IsDefault
154-
})
155-
ifdefIndex>=0 {
156-
defaultOrg=orgs[defIndex].Name
157-
}
158-
}
159-
160-
// Defer to first org
161-
ifdefaultOrg==""&&len(orgs)>0 {
162-
defaultOrg=orgs[0].Name
163-
}
164-
165-
// Ensure the `defaultOrg` value is an org name, not a uuid.
166-
// If it is a uuid, change it to the org name.
167-
index:=slices.IndexFunc(orgs,func(org codersdk.Organization)bool {
168-
returnorg.ID.String()==defaultOrg||org.Name==defaultOrg
169-
})
170-
ifindex>=0 {
171-
defaultOrg=orgs[index].Name
172-
}
173-
174-
// deselectOption is the option to delete the organization config file and defer
175-
// to default behavior.
176-
constdeselectOption="[Default]"
177-
ifdefaultOrg=="" {
178-
defaultOrg=deselectOption
179-
}
180-
181-
// Pull value from a prompt
182-
_,_=fmt.Fprintln(inv.Stdout,pretty.Sprint(cliui.DefaultStyles.Wrap,"Select an organization below to set the current CLI context to:"))
183-
value,err:=cliui.Select(inv, cliui.SelectOptions{
184-
Options:append([]string{deselectOption},orgNames(orgs)...),
185-
Default:defaultOrg,
186-
Size:10,
187-
HideSearch:false,
188-
})
189-
iferr!=nil {
190-
return"",err
191-
}
192-
// Deselect is an alias for ""
193-
ifvalue==deselectOption {
194-
value=""
195-
}
196-
197-
returnvalue,nil
198-
}
199-
200-
// orgNames is a helper function to turn a list of organizations into a list of
201-
// their names as strings.
202-
funcorgNames(orgs []codersdk.Organization) []string {
203-
names:=make([]string,0,len(orgs))
204-
for_,org:=rangeorgs {
205-
names=append(names,org.Name)
206-
}
207-
returnnames
208-
}
209-
210-
func (r*RootCmd)currentOrganization()*serpent.Command {
37+
func (r*RootCmd)showOrganization(orgContext*OrganizationContext)*serpent.Command {
21138
var (
21239
stringFormatfunc(orgs []codersdk.Organization) (string,error)
21340
client=new(codersdk.Client)
@@ -226,8 +53,29 @@ func (r *RootCmd) currentOrganization() *serpent.Command {
22653
onlyID=false
22754
)
22855
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.",
56+
Use:"show [\"selected\"|\"me\"|uuid|org_name]",
57+
Short:"Show the organization. "+
58+
"Using\"selected\" will show the selected organization from the\"--org\" flag. "+
59+
"Using\"me\" will show all organizations you are a member of.",
60+
Long:FormatExamples(
61+
Example{
62+
Description:"coder org show selected",
63+
Command:"Shows the organizations selected with '--org=<org_name>'. "+
64+
"This organization is the organization used by the cli.",
65+
},
66+
Example{
67+
Description:"coder org show me",
68+
Command:"List of all organizations you are a member of.",
69+
},
70+
Example{
71+
Description:"coder org show developers",
72+
Command:"Show organization with name 'developers'",
73+
},
74+
Example{
75+
Description:"coder org show 90ee1875-3db5-43b3-828e-af3687522e43",
76+
Command:"Show organization with the given ID.",
77+
},
78+
),
23179
Middleware:serpent.Chain(
23280
r.InitClient(client),
23381
serpent.RequireRangeArgs(0,1),
@@ -242,22 +90,22 @@ func (r *RootCmd) currentOrganization() *serpent.Command {
24290
},
24391
},
24492
Handler:func(inv*serpent.Invocation)error {
245-
orgArg:="current"
93+
orgArg:="selected"
24694
iflen(inv.Args)>=1 {
24795
orgArg=inv.Args[0]
24896
}
24997

25098
varorgs []codersdk.Organization
25199
varerrerror
252100
switchstrings.ToLower(orgArg) {
253-
case"current":
101+
case"selected":
254102
stringFormat=func(orgs []codersdk.Organization) (string,error) {
255103
iflen(orgs)!=1 {
256104
return"",xerrors.Errorf("expected 1 organization, got %d",len(orgs))
257105
}
258106
returnfmt.Sprintf("Current CLI Organization: %s (%s)\n",orgs[0].Name,orgs[0].ID.String()),nil
259107
}
260-
org,err:=CurrentOrganization(r,inv,client)
108+
org,err:=orgContext.Selected(inv,client)
261109
iferr!=nil {
262110
returnerr
263111
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp