mirror of https://github.com/coder/coder.git
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
This commit is contained in:
parent
bed61f7d2a
commit
773862a9f5
17
cli/login.go
17
cli/login.go
|
@ -136,16 +136,28 @@ func (r *RootCmd) login() *clibase.Cmd {
|
|||
useTokenForSession bool
|
||||
)
|
||||
cmd := &clibase.Cmd{
|
||||
Use: "login <url>",
|
||||
Use: "login [<url>]",
|
||||
Short: "Authenticate with Coder deployment",
|
||||
Middleware: clibase.RequireRangeArgs(0, 1),
|
||||
Handler: func(inv *clibase.Invocation) error {
|
||||
ctx := inv.Context()
|
||||
rawURL := ""
|
||||
var urlSource string
|
||||
|
||||
if len(inv.Args) == 0 {
|
||||
rawURL = r.clientURL.String()
|
||||
urlSource = "flag"
|
||||
if rawURL != "" && rawURL == inv.Environ.Get(envURL) {
|
||||
urlSource = "environment"
|
||||
}
|
||||
} else {
|
||||
rawURL = inv.Args[0]
|
||||
urlSource = "argument"
|
||||
}
|
||||
|
||||
if url, err := r.createConfig().URL().Read(); rawURL == "" && err == nil {
|
||||
urlSource = "config"
|
||||
rawURL = url
|
||||
}
|
||||
|
||||
if rawURL == "" {
|
||||
|
@ -187,6 +199,9 @@ func (r *RootCmd) login() *clibase.Cmd {
|
|||
if err != nil {
|
||||
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)
|
||||
}
|
||||
|
||||
_, _ = fmt.Fprintf(inv.Stdout, "Attempting to authenticate with %s URL: '%s'\n", urlSource, serverURL)
|
||||
|
||||
if !hasFirstUser {
|
||||
_, _ = fmt.Fprintf(inv.Stdout, Caret+"Your Coder deployment hasn't been set up!\n")
|
||||
|
||||
|
|
|
@ -116,6 +116,7 @@ func TestLogin(t *testing.T) {
|
|||
|
||||
clitest.Start(t, inv)
|
||||
|
||||
pty.ExpectMatch(fmt.Sprintf("Attempting to authenticate with flag URL: '%s'", client.URL.String()))
|
||||
matches := []string{
|
||||
"first user?", "yes",
|
||||
"username", "testuser",
|
||||
|
@ -205,6 +206,7 @@ func TestLogin(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
}()
|
||||
|
||||
pty.ExpectMatch(fmt.Sprintf("Attempting to authenticate with argument URL: '%s'", client.URL.String()))
|
||||
pty.ExpectMatch("Paste your token here:")
|
||||
pty.WriteLine(client.SessionToken())
|
||||
if runtime.GOOS != "windows" {
|
||||
|
@ -215,6 +217,52 @@ func TestLogin(t *testing.T) {
|
|||
<-doneChan
|
||||
})
|
||||
|
||||
t.Run("ExistingUserURLSavedInConfig", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
client := coderdtest.New(t, nil)
|
||||
url := client.URL.String()
|
||||
coderdtest.CreateFirstUser(t, client)
|
||||
|
||||
inv, root := clitest.New(t, "login", "--no-open")
|
||||
clitest.SetupConfig(t, client, root)
|
||||
|
||||
doneChan := make(chan struct{})
|
||||
pty := ptytest.New(t).Attach(inv)
|
||||
go func() {
|
||||
defer close(doneChan)
|
||||
err := inv.Run()
|
||||
assert.NoError(t, err)
|
||||
}()
|
||||
|
||||
pty.ExpectMatch(fmt.Sprintf("Attempting to authenticate with config URL: '%s'", url))
|
||||
pty.ExpectMatch("Paste your token here:")
|
||||
pty.WriteLine(client.SessionToken())
|
||||
<-doneChan
|
||||
})
|
||||
|
||||
t.Run("ExistingUserURLSavedInEnv", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
client := coderdtest.New(t, nil)
|
||||
url := client.URL.String()
|
||||
coderdtest.CreateFirstUser(t, client)
|
||||
|
||||
inv, _ := clitest.New(t, "login", "--no-open")
|
||||
inv.Environ.Set("CODER_URL", url)
|
||||
|
||||
doneChan := make(chan struct{})
|
||||
pty := ptytest.New(t).Attach(inv)
|
||||
go func() {
|
||||
defer close(doneChan)
|
||||
err := inv.Run()
|
||||
assert.NoError(t, err)
|
||||
}()
|
||||
|
||||
pty.ExpectMatch(fmt.Sprintf("Attempting to authenticate with environment URL: '%s'", url))
|
||||
pty.ExpectMatch("Paste your token here:")
|
||||
pty.WriteLine(client.SessionToken())
|
||||
<-doneChan
|
||||
})
|
||||
|
||||
t.Run("ExistingUserInvalidTokenTTY", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
client := coderdtest.New(t, nil)
|
||||
|
|
|
@ -119,7 +119,7 @@ func TestLogout(t *testing.T) {
|
|||
go func() {
|
||||
defer close(logoutChan)
|
||||
err = logout.Run()
|
||||
assert.ErrorContains(t, err, "You are not logged in. Try logging in using 'coder login <url>'.")
|
||||
assert.ErrorContains(t, err, "You are not logged in. Try logging in using 'coder login'.")
|
||||
}()
|
||||
|
||||
<-logoutChan
|
||||
|
|
11
cli/root.go
11
cli/root.go
|
@ -65,7 +65,9 @@ const (
|
|||
varVerbose = "verbose"
|
||||
varOrganizationSelect = "organization"
|
||||
varDisableDirect = "disable-direct-connections"
|
||||
notLoggedInMessage = "You are not logged in. Try logging in using 'coder login <url>'."
|
||||
|
||||
notLoggedInMessage = "You are not logged in. Try logging in using 'coder login <url>'."
|
||||
notLoggedInURLSavedMessage = "You are not logged in. Try logging in using 'coder login'."
|
||||
|
||||
envNoVersionCheck = "CODER_NO_VERSION_WARNING"
|
||||
envNoFeatureWarning = "CODER_NO_FEATURE_WARNING"
|
||||
|
@ -77,7 +79,10 @@ const (
|
|||
envURL = "CODER_URL"
|
||||
)
|
||||
|
||||
var errUnauthenticated = xerrors.New(notLoggedInMessage)
|
||||
var (
|
||||
errUnauthenticated = xerrors.New(notLoggedInMessage)
|
||||
errUnauthenticatedURLSaved = xerrors.New(notLoggedInURLSavedMessage)
|
||||
)
|
||||
|
||||
func (r *RootCmd) Core() []*clibase.Cmd {
|
||||
// Please re-sort this list alphabetically if you change it!
|
||||
|
@ -574,7 +579,7 @@ func (r *RootCmd) initClientInternal(client *codersdk.Client, allowTokenMissing
|
|||
// If the configuration files are absent, the user is logged out
|
||||
if os.IsNotExist(err) {
|
||||
if !allowTokenMissing {
|
||||
return errUnauthenticated
|
||||
return errUnauthenticatedURLSaved
|
||||
}
|
||||
} else if err != nil {
|
||||
return err
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
coder v0.0.0-devel
|
||||
|
||||
USAGE:
|
||||
coder login [flags] <url>
|
||||
coder login [flags] [<url>]
|
||||
|
||||
Authenticate with Coder deployment
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ Authenticate with Coder deployment
|
|||
## Usage
|
||||
|
||||
```console
|
||||
coder login [flags] <url>
|
||||
coder login [flags] [<url>]
|
||||
```
|
||||
|
||||
## Options
|
||||
|
|
Loading…
Reference in New Issue