Skip to content

Commit 773862a

Browse files
authored
feat(cli): make url optional for login command (#10925) (#12466)
Allow `coder login` to log into existing deployment if available. Update help and error messages to indicate that `coder login` is available as a command. Fixes #10925 Fixes #9551
1 parent bed61f7 commit 773862a

File tree

6 files changed

+75
-7
lines changed

6 files changed

+75
-7
lines changed

cli/login.go

+16-1
Original file line numberDiff line numberDiff line change
@@ -136,16 +136,28 @@ func (r *RootCmd) login() *clibase.Cmd {
136136
useTokenForSession bool
137137
)
138138
cmd := &clibase.Cmd{
139-
Use: "login <url>",
139+
Use: "login [<url>]",
140140
Short: "Authenticate with Coder deployment",
141141
Middleware: clibase.RequireRangeArgs(0, 1),
142142
Handler: func(inv *clibase.Invocation) error {
143143
ctx := inv.Context()
144144
rawURL := ""
145+
var urlSource string
146+
145147
if len(inv.Args) == 0 {
146148
rawURL = r.clientURL.String()
149+
urlSource = "flag"
150+
if rawURL != "" && rawURL == inv.Environ.Get(envURL) {
151+
urlSource = "environment"
152+
}
147153
} else {
148154
rawURL = inv.Args[0]
155+
urlSource = "argument"
156+
}
157+
158+
if url, err := r.createConfig().URL().Read(); rawURL == "" && err == nil {
159+
urlSource = "config"
160+
rawURL = url
149161
}
150162

151163
if rawURL == "" {
@@ -187,6 +199,9 @@ func (r *RootCmd) login() *clibase.Cmd {
187199
if err != nil {
188200
return xerrors.Errorf("Failed to check server %q for first user, is the URL correct and is coder accessible from your browser? Error - has initial user: %w", serverURL.String(), err)
189201
}
202+
203+
_, _ = fmt.Fprintf(inv.Stdout, "Attempting to authenticate with %s URL: '%s'\n", urlSource, serverURL)
204+
190205
if !hasFirstUser {
191206
_, _ = fmt.Fprintf(inv.Stdout, Caret+"Your Coder deployment hasn't been set up!\n")
192207

cli/login_test.go

+48
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ func TestLogin(t *testing.T) {
116116

117117
clitest.Start(t, inv)
118118

119+
pty.ExpectMatch(fmt.Sprintf("Attempting to authenticate with flag URL: '%s'", client.URL.String()))
119120
matches := []string{
120121
"first user?", "yes",
121122
"username", "testuser",
@@ -205,6 +206,7 @@ func TestLogin(t *testing.T) {
205206
assert.NoError(t, err)
206207
}()
207208

209+
pty.ExpectMatch(fmt.Sprintf("Attempting to authenticate with argument URL: '%s'", client.URL.String()))
208210
pty.ExpectMatch("Paste your token here:")
209211
pty.WriteLine(client.SessionToken())
210212
if runtime.GOOS != "windows" {
@@ -215,6 +217,52 @@ func TestLogin(t *testing.T) {
215217
<-doneChan
216218
})
217219

220+
t.Run("ExistingUserURLSavedInConfig", func(t *testing.T) {
221+
t.Parallel()
222+
client := coderdtest.New(t, nil)
223+
url := client.URL.String()
224+
coderdtest.CreateFirstUser(t, client)
225+
226+
inv, root := clitest.New(t, "login", "--no-open")
227+
clitest.SetupConfig(t, client, root)
228+
229+
doneChan := make(chan struct{})
230+
pty := ptytest.New(t).Attach(inv)
231+
go func() {
232+
defer close(doneChan)
233+
err := inv.Run()
234+
assert.NoError(t, err)
235+
}()
236+
237+
pty.ExpectMatch(fmt.Sprintf("Attempting to authenticate with config URL: '%s'", url))
238+
pty.ExpectMatch("Paste your token here:")
239+
pty.WriteLine(client.SessionToken())
240+
<-doneChan
241+
})
242+
243+
t.Run("ExistingUserURLSavedInEnv", func(t *testing.T) {
244+
t.Parallel()
245+
client := coderdtest.New(t, nil)
246+
url := client.URL.String()
247+
coderdtest.CreateFirstUser(t, client)
248+
249+
inv, _ := clitest.New(t, "login", "--no-open")
250+
inv.Environ.Set("CODER_URL", url)
251+
252+
doneChan := make(chan struct{})
253+
pty := ptytest.New(t).Attach(inv)
254+
go func() {
255+
defer close(doneChan)
256+
err := inv.Run()
257+
assert.NoError(t, err)
258+
}()
259+
260+
pty.ExpectMatch(fmt.Sprintf("Attempting to authenticate with environment URL: '%s'", url))
261+
pty.ExpectMatch("Paste your token here:")
262+
pty.WriteLine(client.SessionToken())
263+
<-doneChan
264+
})
265+
218266
t.Run("ExistingUserInvalidTokenTTY", func(t *testing.T) {
219267
t.Parallel()
220268
client := coderdtest.New(t, nil)

cli/logout_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ func TestLogout(t *testing.T) {
119119
go func() {
120120
defer close(logoutChan)
121121
err = logout.Run()
122-
assert.ErrorContains(t, err, "You are not logged in. Try logging in using 'coder login <url>'.")
122+
assert.ErrorContains(t, err, "You are not logged in. Try logging in using 'coder login'.")
123123
}()
124124

125125
<-logoutChan

cli/root.go

+8-3
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,9 @@ const (
6565
varVerbose = "verbose"
6666
varOrganizationSelect = "organization"
6767
varDisableDirect = "disable-direct-connections"
68-
notLoggedInMessage = "You are not logged in. Try logging in using 'coder login <url>'."
68+
69+
notLoggedInMessage = "You are not logged in. Try logging in using 'coder login <url>'."
70+
notLoggedInURLSavedMessage = "You are not logged in. Try logging in using 'coder login'."
6971

7072
envNoVersionCheck = "CODER_NO_VERSION_WARNING"
7173
envNoFeatureWarning = "CODER_NO_FEATURE_WARNING"
@@ -77,7 +79,10 @@ const (
7779
envURL = "CODER_URL"
7880
)
7981

80-
var errUnauthenticated = xerrors.New(notLoggedInMessage)
82+
var (
83+
errUnauthenticated = xerrors.New(notLoggedInMessage)
84+
errUnauthenticatedURLSaved = xerrors.New(notLoggedInURLSavedMessage)
85+
)
8186

8287
func (r *RootCmd) Core() []*clibase.Cmd {
8388
// Please re-sort this list alphabetically if you change it!
@@ -574,7 +579,7 @@ func (r *RootCmd) initClientInternal(client *codersdk.Client, allowTokenMissing
574579
// If the configuration files are absent, the user is logged out
575580
if os.IsNotExist(err) {
576581
if !allowTokenMissing {
577-
return errUnauthenticated
582+
return errUnauthenticatedURLSaved
578583
}
579584
} else if err != nil {
580585
return err

cli/testdata/coder_login_--help.golden

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
coder v0.0.0-devel
22

33
USAGE:
4-
coder login [flags] <url>
4+
coder login [flags] [<url>]
55

66
Authenticate with Coder deployment
77

docs/cli/login.md

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)