Skip to content

Commit da8e511

Browse files
committed
chore: Rename "start" to "server" (#1110)
Workspace commands will be aliased at the top-level, so "start" would easily be confused with starting a workspace. Server seems like a more appropriate name too.
1 parent da36812 commit da8e511

31 files changed

+256
-139
lines changed

cli/root.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ func Root() *cobra.Command {
4343
`,
4444
Example: cliui.Styles.Paragraph.Render(`Start Coder in "dev" mode. This dev-mode requires no further setup, and your local `+cliui.Styles.Code.Render("coder")+` CLI will be authenticated to talk to it. This makes it easy to experiment with Coder.`) + `
4545
46-
` + cliui.Styles.Code.Render("$ coder start --dev") + `
46+
` + cliui.Styles.Code.Render("$ coder server --dev") + `
4747
` + cliui.Styles.Paragraph.Render("Get started by creating a template from an example.") + `
4848
4949
` + cliui.Styles.Code.Render("$ coder templates init"),
@@ -63,7 +63,7 @@ func Root() *cobra.Command {
6363

6464
cmd.AddCommand(
6565
configSSH(),
66-
start(),
66+
server(),
6767
login(),
6868
parameters(),
6969
templates(),

cli/start.go renamed to cli/server.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ import (
4343
"github.com/coder/coder/provisionersdk/proto"
4444
)
4545

46-
func start() *cobra.Command {
46+
func server() *cobra.Command {
4747
var (
4848
accessURL string
4949
address string
@@ -67,7 +67,7 @@ func start() *cobra.Command {
6767
)
6868

6969
root := &cobra.Command{
70-
Use: "start",
70+
Use: "server",
7171
RunE: func(cmd *cobra.Command, args []string) error {
7272
logger := slog.Make(sloghuman.Sink(os.Stderr))
7373
if traceDatadog {

cli/start_test.go renamed to cli/server_test.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ import (
2929

3030
// This cannot be ran in parallel because it uses a signal.
3131
// nolint:tparallel
32-
func TestStart(t *testing.T) {
32+
func TestServer(t *testing.T) {
3333
t.Run("Production", func(t *testing.T) {
3434
t.Parallel()
3535
if runtime.GOOS != "linux" || testing.Short() {
@@ -41,7 +41,7 @@ func TestStart(t *testing.T) {
4141
defer closeFunc()
4242
ctx, cancelFunc := context.WithCancel(context.Background())
4343
done := make(chan struct{})
44-
root, cfg := clitest.New(t, "start", "--address", ":0", "--postgres-url", connectionURL)
44+
root, cfg := clitest.New(t, "server", "--address", ":0", "--postgres-url", connectionURL)
4545
go func() {
4646
defer close(done)
4747
err = root.ExecuteContext(ctx)
@@ -72,7 +72,7 @@ func TestStart(t *testing.T) {
7272
t.Parallel()
7373
ctx, cancelFunc := context.WithCancel(context.Background())
7474
defer cancelFunc()
75-
root, cfg := clitest.New(t, "start", "--dev", "--skip-tunnel", "--address", ":0")
75+
root, cfg := clitest.New(t, "server", "--dev", "--skip-tunnel", "--address", ":0")
7676
go func() {
7777
err := root.ExecuteContext(ctx)
7878
require.ErrorIs(t, err, context.Canceled)
@@ -97,7 +97,7 @@ func TestStart(t *testing.T) {
9797
t.Parallel()
9898
ctx, cancelFunc := context.WithCancel(context.Background())
9999
defer cancelFunc()
100-
root, _ := clitest.New(t, "start", "--dev", "--skip-tunnel", "--address", ":0",
100+
root, _ := clitest.New(t, "server", "--dev", "--skip-tunnel", "--address", ":0",
101101
"--tls-enable", "--tls-min-version", "tls9")
102102
err := root.ExecuteContext(ctx)
103103
require.Error(t, err)
@@ -106,7 +106,7 @@ func TestStart(t *testing.T) {
106106
t.Parallel()
107107
ctx, cancelFunc := context.WithCancel(context.Background())
108108
defer cancelFunc()
109-
root, _ := clitest.New(t, "start", "--dev", "--skip-tunnel", "--address", ":0",
109+
root, _ := clitest.New(t, "server", "--dev", "--skip-tunnel", "--address", ":0",
110110
"--tls-enable", "--tls-client-auth", "something")
111111
err := root.ExecuteContext(ctx)
112112
require.Error(t, err)
@@ -115,7 +115,7 @@ func TestStart(t *testing.T) {
115115
t.Parallel()
116116
ctx, cancelFunc := context.WithCancel(context.Background())
117117
defer cancelFunc()
118-
root, _ := clitest.New(t, "start", "--dev", "--skip-tunnel", "--address", ":0",
118+
root, _ := clitest.New(t, "server", "--dev", "--skip-tunnel", "--address", ":0",
119119
"--tls-enable")
120120
err := root.ExecuteContext(ctx)
121121
require.Error(t, err)
@@ -126,7 +126,7 @@ func TestStart(t *testing.T) {
126126
defer cancelFunc()
127127

128128
certPath, keyPath := generateTLSCertificate(t)
129-
root, cfg := clitest.New(t, "start", "--dev", "--skip-tunnel", "--address", ":0",
129+
root, cfg := clitest.New(t, "server", "--dev", "--skip-tunnel", "--address", ":0",
130130
"--tls-enable", "--tls-cert-file", certPath, "--tls-key-file", keyPath)
131131
go func() {
132132
err := root.ExecuteContext(ctx)
@@ -162,7 +162,7 @@ func TestStart(t *testing.T) {
162162
}
163163
ctx, cancelFunc := context.WithCancel(context.Background())
164164
defer cancelFunc()
165-
root, cfg := clitest.New(t, "start", "--dev", "--skip-tunnel", "--address", ":0", "--provisioner-daemons", "0")
165+
root, cfg := clitest.New(t, "server", "--dev", "--skip-tunnel", "--address", ":0", "--provisioner-daemons", "0")
166166
done := make(chan struct{})
167167
go func() {
168168
defer close(done)
@@ -204,7 +204,7 @@ func TestStart(t *testing.T) {
204204
t.Parallel()
205205
ctx, cancelFunc := context.WithCancel(context.Background())
206206
defer cancelFunc()
207-
root, _ := clitest.New(t, "start", "--dev", "--skip-tunnel", "--address", ":0", "--trace-datadog=true")
207+
root, _ := clitest.New(t, "server", "--dev", "--skip-tunnel", "--address", ":0", "--trace-datadog=true")
208208
done := make(chan struct{})
209209
go func() {
210210
defer close(done)

cli/usercreate.go

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
package cli
2+
3+
import (
4+
"fmt"
5+
6+
"github.com/go-playground/validator/v10"
7+
"github.com/spf13/cobra"
8+
"golang.org/x/xerrors"
9+
10+
"github.com/coder/coder/cli/cliui"
11+
"github.com/coder/coder/codersdk"
12+
"github.com/coder/coder/cryptorand"
13+
)
14+
15+
func userCreate() *cobra.Command {
16+
var (
17+
email string
18+
username string
19+
password string
20+
)
21+
cmd := &cobra.Command{
22+
Use: "create",
23+
RunE: func(cmd *cobra.Command, args []string) error {
24+
client, err := createClient(cmd)
25+
if err != nil {
26+
return err
27+
}
28+
organization, err := currentOrganization(cmd, client)
29+
if err != nil {
30+
return err
31+
}
32+
if username == "" {
33+
username, err = cliui.Prompt(cmd, cliui.PromptOptions{
34+
Text: "Username:",
35+
})
36+
if err != nil {
37+
return err
38+
}
39+
}
40+
if email == "" {
41+
email, err = cliui.Prompt(cmd, cliui.PromptOptions{
42+
Text: "Email:",
43+
Validate: func(s string) error {
44+
err := validator.New().Var(s, "email")
45+
if err != nil {
46+
return xerrors.New("That's not a valid email address!")
47+
}
48+
return err
49+
},
50+
})
51+
if err != nil {
52+
return err
53+
}
54+
}
55+
if password == "" {
56+
password, err = cryptorand.StringCharset(cryptorand.Human, 12)
57+
if err != nil {
58+
return err
59+
}
60+
}
61+
62+
_, err = client.CreateUser(cmd.Context(), codersdk.CreateUserRequest{
63+
Email: email,
64+
Username: username,
65+
Password: password,
66+
OrganizationID: organization.ID,
67+
})
68+
if err != nil {
69+
return err
70+
}
71+
_, _ = fmt.Fprintln(cmd.ErrOrStderr(), `A new user has been created!
72+
Share the instructions below to get them started.
73+
`+cliui.Styles.Placeholder.Render("—————————————————————————————————————————————————")+`
74+
Download the Coder command line for your operating system:
75+
https://github.com/coder/coder/releases
76+
77+
Run `+cliui.Styles.Code.Render("coder login "+client.URL.String())+` to authenticate.
78+
79+
Your email is: `+cliui.Styles.Field.Render(email)+`
80+
Your password is: `+cliui.Styles.Field.Render(password)+`
81+
82+
Create a workspace `+cliui.Styles.Code.Render("coder workspaces create")+`!`)
83+
return nil
84+
},
85+
}
86+
cmd.Flags().StringVarP(&email, "email", "e", "", "Specifies an email address for the new user.")
87+
cmd.Flags().StringVarP(&username, "username", "u", "", "Specifies a username for the new user.")
88+
cmd.Flags().StringVarP(&password, "password", "p", "", "Specifies a password for the new user.")
89+
return cmd
90+
}

cli/usercreate_test.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package cli_test
2+
3+
import (
4+
"testing"
5+
6+
"github.com/coder/coder/cli/clitest"
7+
"github.com/coder/coder/coderd/coderdtest"
8+
"github.com/coder/coder/pty/ptytest"
9+
"github.com/stretchr/testify/require"
10+
)
11+
12+
func TestUserCreate(t *testing.T) {
13+
t.Parallel()
14+
t.Run("Prompts", func(t *testing.T) {
15+
t.Parallel()
16+
client := coderdtest.New(t, nil)
17+
coderdtest.CreateFirstUser(t, client)
18+
cmd, root := clitest.New(t, "users", "create")
19+
clitest.SetupConfig(t, client, root)
20+
doneChan := make(chan struct{})
21+
pty := ptytest.New(t)
22+
cmd.SetIn(pty.Input())
23+
cmd.SetOut(pty.Output())
24+
go func() {
25+
defer close(doneChan)
26+
err := cmd.Execute()
27+
require.NoError(t, err)
28+
}()
29+
matches := []string{
30+
"Username", "dean",
31+
"Email", "dean@coder.com",
32+
}
33+
for i := 0; i < len(matches); i += 2 {
34+
match := matches[i]
35+
value := matches[i+1]
36+
pty.ExpectMatch(match)
37+
pty.WriteLine(value)
38+
}
39+
<-doneChan
40+
})
41+
}

cli/userlist.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package cli
2+
3+
import (
4+
"fmt"
5+
"sort"
6+
"time"
7+
8+
"github.com/jedib0t/go-pretty/v6/table"
9+
"github.com/spf13/cobra"
10+
11+
"github.com/coder/coder/codersdk"
12+
)
13+
14+
func userList() *cobra.Command {
15+
return &cobra.Command{
16+
Use: "list",
17+
Aliases: []string{"ls"},
18+
RunE: func(cmd *cobra.Command, args []string) error {
19+
client, err := createClient(cmd)
20+
if err != nil {
21+
return err
22+
}
23+
users, err := client.Users(cmd.Context(), codersdk.UsersRequest{})
24+
if err != nil {
25+
return err
26+
}
27+
sort.Slice(users, func(i, j int) bool {
28+
return users[i].Username < users[j].Username
29+
})
30+
31+
tableWriter := table.NewWriter()
32+
tableWriter.SetStyle(table.StyleLight)
33+
tableWriter.Style().Options.SeparateColumns = false
34+
tableWriter.AppendHeader(table.Row{"Username", "Email", "Created At"})
35+
for _, user := range users {
36+
tableWriter.AppendRow(table.Row{
37+
user.Username,
38+
user.Email,
39+
user.CreatedAt.Format(time.Stamp),
40+
})
41+
}
42+
_, err = fmt.Fprintln(cmd.OutOrStdout(), tableWriter.Render())
43+
return err
44+
},
45+
}
46+
}

cli/userlist_test.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package cli_test
2+
3+
import (
4+
"testing"
5+
6+
"github.com/coder/coder/cli/clitest"
7+
"github.com/coder/coder/coderd/coderdtest"
8+
"github.com/coder/coder/pty/ptytest"
9+
"github.com/stretchr/testify/require"
10+
)
11+
12+
func TestUserList(t *testing.T) {
13+
t.Parallel()
14+
client := coderdtest.New(t, nil)
15+
coderdtest.CreateFirstUser(t, client)
16+
cmd, root := clitest.New(t, "users", "list")
17+
clitest.SetupConfig(t, client, root)
18+
doneChan := make(chan struct{})
19+
pty := ptytest.New(t)
20+
cmd.SetIn(pty.Input())
21+
cmd.SetOut(pty.Output())
22+
go func() {
23+
defer close(doneChan)
24+
err := cmd.Execute()
25+
require.NoError(t, err)
26+
}()
27+
pty.ExpectMatch("coder.com")
28+
<-doneChan
29+
}

cli/users.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,6 @@ func users() *cobra.Command {
66
cmd := &cobra.Command{
77
Use: "users",
88
}
9+
cmd.AddCommand(userCreate(), userList())
910
return cmd
1011
}

coder.env

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Run "coder start --help" for flag information.
1+
# Run "coder server --help" for flag information.
22
CODER_ADDRESS=
33
CODER_PG_CONNECTION_URL=
44
CODER_TLS_CERT_FILE=

coder.service

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ AmbientCapabilities=CAP_IPC_LOCK
1919
CacheDirectory=coder
2020
CapabilityBoundingSet=CAP_SYSLOG CAP_IPC_LOCK CAP_NET_BIND_SERVICE
2121
NoNewPrivileges=yes
22-
ExecStart=/usr/bin/coder start
22+
ExecStart=/usr/bin/coder server
2323
Restart=on-failure
2424
RestartSec=5
2525
TimeoutStopSec=30

0 commit comments

Comments
 (0)