From d6410d9655e56f9ccb7735b7d03f8ea3736b805e Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Wed, 27 Apr 2022 12:59:20 +0000 Subject: [PATCH 1/4] feat: Output username and password for `code server --dev` Fixes #825 --- cli/server.go | 21 +++++++++++++-------- cli/server_test.go | 7 +++++++ 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/cli/server.go b/cli/server.go index 4fad8a82560d9..95deb2dcad413 100644 --- a/cli/server.go +++ b/cli/server.go @@ -47,6 +47,13 @@ import ( "github.com/coder/coder/provisionersdk/proto" ) +var defaultDevUser = codersdk.CreateFirstUserRequest{ + Email: "admin@coder.com", + Username: "developer", + Password: "password", + OrganizationName: "acme-corp", +} + // nolint:gocyclo func server() *cobra.Command { var ( @@ -275,6 +282,9 @@ func server() *cobra.Command { if err != nil { return xerrors.Errorf("create first user: %w", err) } + _, _ = fmt.Fprintf(cmd.ErrOrStderr(), "email: %s\n", defaultDevUser.Email) + _, _ = fmt.Fprintf(cmd.ErrOrStderr(), "password: %s\n", defaultDevUser.Password) + _, _ = fmt.Fprintln(cmd.ErrOrStderr()) _, _ = fmt.Fprintf(cmd.ErrOrStderr(), cliui.Styles.Wrap.Render(`Started in dev mode. All data is in-memory! `+cliui.Styles.Bold.Render("Do not use in production")+`. Press `+ cliui.Styles.Field.Render("ctrl+c")+` to clean up provisioned infrastructure.`)+"\n\n") @@ -441,18 +451,13 @@ func server() *cobra.Command { } func createFirstUser(cmd *cobra.Command, client *codersdk.Client, cfg config.Root) error { - _, err := client.CreateFirstUser(cmd.Context(), codersdk.CreateFirstUserRequest{ - Email: "admin@coder.com", - Username: "developer", - Password: "password", - OrganizationName: "acme-corp", - }) + _, err := client.CreateFirstUser(cmd.Context(), defaultDevUser) if err != nil { return xerrors.Errorf("create first user: %w", err) } token, err := client.LoginWithPassword(cmd.Context(), codersdk.LoginWithPasswordRequest{ - Email: "admin@coder.com", - Password: "password", + Email: defaultDevUser.Email, + Password: defaultDevUser.Password, }) if err != nil { return xerrors.Errorf("login with first user: %w", err) diff --git a/cli/server_test.go b/cli/server_test.go index 91cec9e3470da..02e96c0fc6d5e 100644 --- a/cli/server_test.go +++ b/cli/server_test.go @@ -1,6 +1,7 @@ package cli_test import ( + "bytes" "context" "crypto/ecdsa" "crypto/elliptic" @@ -18,6 +19,7 @@ import ( "testing" "time" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/goleak" @@ -77,6 +79,8 @@ func TestServer(t *testing.T) { err := root.ExecuteContext(ctx) require.ErrorIs(t, err, context.Canceled) }() + var stdoutBuf bytes.Buffer + root.SetOutput(&stdoutBuf) var token string require.Eventually(t, func() bool { var err error @@ -88,6 +92,9 @@ func TestServer(t *testing.T) { require.NoError(t, err) parsed, err := url.Parse(accessURL) require.NoError(t, err) + // Verify that credentials were output to the terminal. + assert.Contains(t, stdoutBuf.String(), "email: admin@coder.com", "unexpected output") + assert.Contains(t, stdoutBuf.String(), "password: password", "unexpected output") client := codersdk.New(parsed) client.SessionToken = token _, err = client.User(ctx, codersdk.Me) From 24c0e1c8d5051aa9fa0e4e03bbc875455c7b9029 Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Wed, 27 Apr 2022 13:28:00 +0000 Subject: [PATCH 2/4] nit: Use clearer error messages for assert --- cli/server_test.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/cli/server_test.go b/cli/server_test.go index 02e96c0fc6d5e..44515ebdc6895 100644 --- a/cli/server_test.go +++ b/cli/server_test.go @@ -93,8 +93,10 @@ func TestServer(t *testing.T) { parsed, err := url.Parse(accessURL) require.NoError(t, err) // Verify that credentials were output to the terminal. - assert.Contains(t, stdoutBuf.String(), "email: admin@coder.com", "unexpected output") - assert.Contains(t, stdoutBuf.String(), "password: password", "unexpected output") + wantEmail := "email: admin@coder.com" + wantPassword := "password: password" + assert.Contains(t, stdoutBuf.String(), wantEmail, "expected output %q; got no match", wantEmail) + assert.Contains(t, stdoutBuf.String(), wantPassword, "expected output %q; got no match", wantPassword) client := codersdk.New(parsed) client.SessionToken = token _, err = client.User(ctx, codersdk.Me) From 3cd7460af4d373822c757fb80779018097c1a755 Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Wed, 27 Apr 2022 13:39:27 +0000 Subject: [PATCH 3/4] Fix data race in test --- cli/server_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cli/server_test.go b/cli/server_test.go index 44515ebdc6895..7014dc746d4ae 100644 --- a/cli/server_test.go +++ b/cli/server_test.go @@ -75,12 +75,12 @@ func TestServer(t *testing.T) { ctx, cancelFunc := context.WithCancel(context.Background()) defer cancelFunc() root, cfg := clitest.New(t, "server", "--dev", "--skip-tunnel", "--address", ":0") + var stdoutBuf bytes.Buffer + root.SetOutput(&stdoutBuf) go func() { err := root.ExecuteContext(ctx) require.ErrorIs(t, err, context.Canceled) }() - var stdoutBuf bytes.Buffer - root.SetOutput(&stdoutBuf) var token string require.Eventually(t, func() bool { var err error From e94fdaf4b8c3954d17cf55b4074532e8c4a61d14 Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Wed, 27 Apr 2022 14:20:10 +0000 Subject: [PATCH 4/4] Avoid data race on buffer by reading after exit --- cli/server_test.go | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/cli/server_test.go b/cli/server_test.go index 7014dc746d4ae..100f80f75febf 100644 --- a/cli/server_test.go +++ b/cli/server_test.go @@ -80,6 +80,12 @@ func TestServer(t *testing.T) { go func() { err := root.ExecuteContext(ctx) require.ErrorIs(t, err, context.Canceled) + + // Verify that credentials were output to the terminal. + wantEmail := "email: admin@coder.com" + wantPassword := "password: password" + assert.Contains(t, stdoutBuf.String(), wantEmail, "expected output %q; got no match", wantEmail) + assert.Contains(t, stdoutBuf.String(), wantPassword, "expected output %q; got no match", wantPassword) }() var token string require.Eventually(t, func() bool { @@ -92,11 +98,6 @@ func TestServer(t *testing.T) { require.NoError(t, err) parsed, err := url.Parse(accessURL) require.NoError(t, err) - // Verify that credentials were output to the terminal. - wantEmail := "email: admin@coder.com" - wantPassword := "password: password" - assert.Contains(t, stdoutBuf.String(), wantEmail, "expected output %q; got no match", wantEmail) - assert.Contains(t, stdoutBuf.String(), wantPassword, "expected output %q; got no match", wantPassword) client := codersdk.New(parsed) client.SessionToken = token _, err = client.User(ctx, codersdk.Me)