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

Commit6f71825

Browse files
committed
feat: Add built-in PostgreSQL for simple production setup
Fixes#2321.
1 parent0a949aa commit6f71825

File tree

19 files changed

+406
-467
lines changed

19 files changed

+406
-467
lines changed

‎README.md‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,14 @@ To install, run:
4747
curl -fsSL https://coder.com/install.sh| sh
4848
```
4949

50-
Once installed, you canrun atemporary deploymentin dev mode (all data is in-memory and destroyed on exit):
50+
Once installed, you canstart aproduction deploymentwith a single command:
5151

5252
```sh
53-
coder server --dev
53+
# Automatically sets up PostgreSQL and an external access URL on *.try.coder.app
54+
coder server --postgres-builtin --tunnel
55+
56+
# Requires a PostgreSQL instance and external access URL
57+
coder server --postgres-url<url> --access-url<url>
5458
```
5559

5660
Use`coder --help` to get a complete list of flags and environment variables. Use our[quickstart guide](./docs/quickstart.md) for a full walkthrough.

‎cli/config/file.go‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,18 @@ func (r Root) DotfilesURL() File {
2525
returnFile(filepath.Join(string(r),"dotfilesurl"))
2626
}
2727

28+
func (rRoot)PostgresPath()string {
29+
returnfilepath.Join(string(r),"postgres")
30+
}
31+
32+
func (rRoot)PostgresPassword()File {
33+
returnFile(filepath.Join(r.PostgresPath(),"password"))
34+
}
35+
36+
func (rRoot)PostgresPort()File {
37+
returnFile(filepath.Join(r.PostgresPath(),"port"))
38+
}
39+
2840
// File provides convenience methods for interacting with *os.File.
2941
typeFilestring
3042

‎cli/login.go‎

Lines changed: 75 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,12 @@ func init() {
3737
}
3838

3939
funclogin()*cobra.Command {
40-
return&cobra.Command{
40+
var (
41+
emailstring
42+
usernamestring
43+
passwordstring
44+
)
45+
cmd:=&cobra.Command{
4146
Use:"login <url>",
4247
Short:"Authenticate with a Coder deployment",
4348
Args:cobra.ExactArgs(1),
@@ -66,71 +71,77 @@ func login() *cobra.Command {
6671
returnxerrors.Errorf("has initial user: %w",err)
6772
}
6873
if!hasInitialUser {
69-
if!isTTY(cmd) {
70-
returnxerrors.New("the initial user cannot be created in non-interactive mode. use the API")
71-
}
7274
_,_=fmt.Fprintf(cmd.OutOrStdout(),caret+"Your Coder deployment hasn't been set up!\n")
7375

74-
_,err:=cliui.Prompt(cmd, cliui.PromptOptions{
75-
Text:"Would you like to create the first user?",
76-
Default:"yes",
77-
IsConfirm:true,
78-
})
79-
iferrors.Is(err,cliui.Canceled) {
80-
returnnil
81-
}
82-
iferr!=nil {
83-
returnerr
84-
}
85-
currentUser,err:=user.Current()
86-
iferr!=nil {
87-
returnxerrors.Errorf("get current user: %w",err)
88-
}
89-
username,err:=cliui.Prompt(cmd, cliui.PromptOptions{
90-
Text:"What "+cliui.Styles.Field.Render("username")+" would you like?",
91-
Default:currentUser.Username,
92-
})
93-
iferrors.Is(err,cliui.Canceled) {
94-
returnnil
95-
}
96-
iferr!=nil {
97-
returnxerrors.Errorf("pick username prompt: %w",err)
98-
}
99-
100-
email,err:=cliui.Prompt(cmd, cliui.PromptOptions{
101-
Text:"What's your "+cliui.Styles.Field.Render("email")+"?",
102-
Validate:func(sstring)error {
103-
err:=validator.New().Var(s,"email")
104-
iferr!=nil {
105-
returnxerrors.New("That's not a valid email address!")
106-
}
76+
ifusername=="" {
77+
if!isTTY(cmd) {
78+
returnxerrors.New("the initial user cannot be created in non-interactive mode. use the API")
79+
}
80+
_,err:=cliui.Prompt(cmd, cliui.PromptOptions{
81+
Text:"Would you like to create the first user?",
82+
Default:"yes",
83+
IsConfirm:true,
84+
})
85+
iferrors.Is(err,cliui.Canceled) {
86+
returnnil
87+
}
88+
iferr!=nil {
10789
returnerr
108-
},
109-
})
110-
iferr!=nil {
111-
returnxerrors.Errorf("specify email prompt: %w",err)
90+
}
91+
currentUser,err:=user.Current()
92+
iferr!=nil {
93+
returnxerrors.Errorf("get current user: %w",err)
94+
}
95+
username,err=cliui.Prompt(cmd, cliui.PromptOptions{
96+
Text:"What "+cliui.Styles.Field.Render("username")+" would you like?",
97+
Default:currentUser.Username,
98+
})
99+
iferrors.Is(err,cliui.Canceled) {
100+
returnnil
101+
}
102+
iferr!=nil {
103+
returnxerrors.Errorf("pick username prompt: %w",err)
104+
}
112105
}
113106

114-
password,err:=cliui.Prompt(cmd, cliui.PromptOptions{
115-
Text:"Enter a "+cliui.Styles.Field.Render("password")+":",
116-
Secret:true,
117-
Validate:cliui.ValidateNotEmpty,
118-
})
119-
iferr!=nil {
120-
returnxerrors.Errorf("specify password prompt: %w",err)
107+
ifemail=="" {
108+
email,err=cliui.Prompt(cmd, cliui.PromptOptions{
109+
Text:"What's your "+cliui.Styles.Field.Render("email")+"?",
110+
Validate:func(sstring)error {
111+
err:=validator.New().Var(s,"email")
112+
iferr!=nil {
113+
returnxerrors.New("That's not a valid email address!")
114+
}
115+
returnerr
116+
},
117+
})
118+
iferr!=nil {
119+
returnxerrors.Errorf("specify email prompt: %w",err)
120+
}
121121
}
122-
_,err=cliui.Prompt(cmd, cliui.PromptOptions{
123-
Text:"Confirm "+cliui.Styles.Field.Render("password")+":",
124-
Secret:true,
125-
Validate:func(sstring)error {
126-
ifs!=password {
127-
returnxerrors.Errorf("Passwords do not match")
128-
}
129-
returnnil
130-
},
131-
})
132-
iferr!=nil {
133-
returnxerrors.Errorf("confirm password prompt: %w",err)
122+
123+
ifpassword=="" {
124+
password,err=cliui.Prompt(cmd, cliui.PromptOptions{
125+
Text:"Enter a "+cliui.Styles.Field.Render("password")+":",
126+
Secret:true,
127+
Validate:cliui.ValidateNotEmpty,
128+
})
129+
iferr!=nil {
130+
returnxerrors.Errorf("specify password prompt: %w",err)
131+
}
132+
_,err=cliui.Prompt(cmd, cliui.PromptOptions{
133+
Text:"Confirm "+cliui.Styles.Field.Render("password")+":",
134+
Secret:true,
135+
Validate:func(sstring)error {
136+
ifs!=password {
137+
returnxerrors.Errorf("Passwords do not match")
138+
}
139+
returnnil
140+
},
141+
})
142+
iferr!=nil {
143+
returnxerrors.Errorf("confirm password prompt: %w",err)
144+
}
134145
}
135146

136147
_,err=client.CreateFirstUser(cmd.Context(), codersdk.CreateFirstUserRequest{
@@ -219,6 +230,10 @@ func login() *cobra.Command {
219230
returnnil
220231
},
221232
}
233+
cmd.Flags().StringVarP(&email,"email","e","","Specifies an email address to authenticate with.")
234+
cmd.Flags().StringVarP(&username,"username","u","","Specifies a username to authenticate with.")
235+
cmd.Flags().StringVarP(&password,"password","p","","Specifies a password to authenticate with.")
236+
returncmd
222237
}
223238

224239
// isWSL determines if coder-cli is running within Windows Subsystem for Linux

‎cli/login_test.go‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,26 @@ func TestLogin(t *testing.T) {
5656
<-doneChan
5757
})
5858

59+
t.Run("InitialUserFlags",func(t*testing.T) {
60+
t.Parallel()
61+
client:=coderdtest.New(t,nil)
62+
// The --force-tty flag is required on Windows, because the `isatty` library does not
63+
// accurately detect Windows ptys when they are not attached to a process:
64+
// https://github.com/mattn/go-isatty/issues/59
65+
doneChan:=make(chanstruct{})
66+
root,_:=clitest.New(t,"login",client.URL.String(),"--username","testuser","--email","user@coder.com","--password","password")
67+
pty:=ptytest.New(t)
68+
root.SetIn(pty.Input())
69+
root.SetOut(pty.Output())
70+
gofunc() {
71+
deferclose(doneChan)
72+
err:=root.Execute()
73+
assert.NoError(t,err)
74+
}()
75+
pty.ExpectMatch("Welcome to Coder")
76+
<-doneChan
77+
})
78+
5979
t.Run("InitialUserTTYConfirmPasswordFailAndReprompt",func(t*testing.T) {
6080
t.Parallel()
6181
ctx,cancel:=context.WithCancel(context.Background())

‎cli/root.go‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,8 @@ func Root() *cobra.Command {
5757
SilenceUsage:true,
5858
Long:`Coder — A tool for provisioning self-hosted development environments.
5959
`,
60-
Example:` StartCoder 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 withCoder.
61-
`+cliui.Styles.Code.Render("$ coder server --dev")+`
60+
Example:` StartaCoder server.
61+
`+cliui.Styles.Code.Render("$ coder server")+`
6262
6363
Get started by creating a template from an example.
6464
`+cliui.Styles.Code.Render("$ coder templates init"),

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp