Skip to content

Commit aa9e5b7

Browse files
committed
Merge branch 'main' into oauth
2 parents 9c3d81e + 3976994 commit aa9e5b7

File tree

34 files changed

+770
-187
lines changed

34 files changed

+770
-187
lines changed

.github/workflows/coder.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ jobs:
9494
- name: Install Protoc
9595
uses: arduino/setup-protoc@v1
9696
with:
97-
version: "3.19.4"
97+
version: "3.20.0"
9898
- uses: actions/setup-go@v3
9999
with:
100100
go-version: "~1.18"

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,5 @@ site/out/
3535
*.tfplan
3636
*.lock.hcl
3737
.terraform/
38+
39+
.vscode/*.log

.vscode/settings.json

+1
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
"tcpip",
5454
"TCSETS",
5555
"tfexec",
56+
"tfjson",
5657
"tfstate",
5758
"trimprefix",
5859
"unconvert",

Makefile

+4-16
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ coderd/database/dump.sql: $(wildcard coderd/database/migrations/*.sql)
1515
.PHONY: coderd/database/dump.sql
1616

1717
# Generates Go code for querying the database.
18-
coderd/database/generate: fmt/sql coderd/database/dump.sql $(wildcard coderd/database/queries/*.sql)
18+
coderd/database/generate: coderd/database/dump.sql $(wildcard coderd/database/queries/*.sql)
1919
coderd/database/generate.sh
2020
.PHONY: coderd/database/generate
2121

@@ -34,30 +34,18 @@ else
3434
endif
3535
.PHONY: fmt/prettier
3636

37-
fmt/sql: $(wildcard coderd/database/queries/*.sql)
38-
for fi in coderd/database/queries/*.sql; do \
39-
npx sql-formatter \
40-
--language postgresql \
41-
--lines-between-queries 2 \
42-
--tab-indent \
43-
$$fi \
44-
--output $$fi; \
45-
done
46-
47-
sed -i 's/@ /@/g' ./coderd/database/queries/*.sql
48-
4937
fmt/terraform: $(wildcard *.tf)
5038
terraform fmt -recursive
5139

52-
fmt: fmt/prettier fmt/sql fmt/terraform
40+
fmt: fmt/prettier fmt/terraform
5341
.PHONY: fmt
5442

5543
gen: coderd/database/generate peerbroker/proto provisionersdk/proto provisionerd/proto apitypings/generate
5644
.PHONY: gen
5745

5846
install: bin
5947
@echo "--- Copying from bin to $(INSTALL_DIR)"
60-
cp -r ./dist/coder_$(GOOS)_$(GOARCH)/* $(INSTALL_DIR)
48+
cp -r ./dist/coder-$(GOOS)_$(GOOS)_$(GOARCH)*/* $(INSTALL_DIR)
6149
@echo "-- CLI available at $(shell ls $(INSTALL_DIR)/coder*)"
6250
.PHONY: install
6351

@@ -92,7 +80,7 @@ provisionersdk/proto: provisionersdk/proto/provisioner.proto
9280
./provisionersdk/proto/provisioner.proto
9381
.PHONY: provisionersdk/proto
9482

95-
release:
83+
release: site/out
9684
goreleaser release --snapshot --rm-dist --skip-sign
9785
.PHONY: release
9886

cli/root.go

+2-2
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

+2-2
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ import (
4646
"github.com/coder/coder/provisionersdk/proto"
4747
)
4848

49-
func start() *cobra.Command {
49+
func server() *cobra.Command {
5050
var (
5151
accessURL string
5252
address string
@@ -74,7 +74,7 @@ func start() *cobra.Command {
7474
)
7575

7676
root := &cobra.Command{
77-
Use: "start",
77+
Use: "server",
7878
RunE: func(cmd *cobra.Command, args []string) error {
7979
logger := slog.Make(sloghuman.Sink(os.Stderr))
8080
if traceDatadog {

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

+9-9
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)

coder.env

+1-1
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

+1-1
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

coderd/coderd.go

+16-9
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,18 @@ type Options struct {
3535
Pubsub database.Pubsub
3636

3737
AgentConnectionUpdateFrequency time.Duration
38-
AWSCertificates awsidentity.Certificates
39-
AzureCertificates x509.VerifyOptions
40-
GoogleTokenValidator *idtoken.Validator
41-
GithubOAuth2Config *GithubOAuth2Config
42-
ICEServers []webrtc.ICEServer
43-
SecureAuthCookie bool
44-
SSHKeygenAlgorithm gitsshkey.Algorithm
45-
TURNServer *turnconn.Server
38+
// APIRateLimit is the minutely throughput rate limit per user or ip.
39+
// Setting a rate limit <0 will disable the rate limiter across the entire
40+
// app. Specific routes may have their own limiters.
41+
APIRateLimit int
42+
AWSCertificates awsidentity.Certificates
43+
AzureCertificates x509.VerifyOptions
44+
GoogleTokenValidator *idtoken.Validator
45+
GithubOAuth2Config *GithubOAuth2Config
46+
ICEServers []webrtc.ICEServer
47+
SecureAuthCookie bool
48+
SSHKeygenAlgorithm gitsshkey.Algorithm
49+
TURNServer *turnconn.Server
4650
}
4751

4852
// New constructs the Coder API into an HTTP handler.
@@ -53,6 +57,9 @@ func New(options *Options) (http.Handler, func()) {
5357
if options.AgentConnectionUpdateFrequency == 0 {
5458
options.AgentConnectionUpdateFrequency = 3 * time.Second
5559
}
60+
if options.APIRateLimit == 0 {
61+
options.APIRateLimit = 512
62+
}
5663
api := &api{
5764
Options: options,
5865
}
@@ -65,7 +72,7 @@ func New(options *Options) (http.Handler, func()) {
6572
r.Use(
6673
chitrace.Middleware(),
6774
// Specific routes can specify smaller limits.
68-
httpmw.RateLimitPerMinute(512),
75+
httpmw.RateLimitPerMinute(options.APIRateLimit),
6976
debugLogRequest(api.Logger),
7077
)
7178
r.Get("/", func(w http.ResponseWriter, r *http.Request) {

coderd/coderdtest/coderdtest.go

+2
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ type Options struct {
5656
GithubOAuth2Config *coderd.GithubOAuth2Config
5757
GoogleTokenValidator *idtoken.Validator
5858
SSHKeygenAlgorithm gitsshkey.Algorithm
59+
APIRateLimit int
5960
}
6061

6162
// New constructs an in-memory coderd instance and returns
@@ -127,6 +128,7 @@ func New(t *testing.T, options *Options) *codersdk.Client {
127128
GoogleTokenValidator: options.GoogleTokenValidator,
128129
SSHKeygenAlgorithm: options.SSHKeygenAlgorithm,
129130
TURNServer: turnServer,
131+
APIRateLimit: options.APIRateLimit,
130132
})
131133
t.Cleanup(func() {
132134
cancelFunc()

coderd/database/databasefake/databasefake.go

+64-2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package databasefake
33
import (
44
"context"
55
"database/sql"
6+
"sort"
67
"strings"
78
"sync"
89

@@ -164,11 +165,72 @@ func (q *fakeQuerier) GetUserCount(_ context.Context) (int64, error) {
164165
return int64(len(q.users)), nil
165166
}
166167

167-
func (q *fakeQuerier) GetUsers(_ context.Context) ([]database.User, error) {
168+
func (q *fakeQuerier) GetUsers(_ context.Context, params database.GetUsersParams) ([]database.User, error) {
168169
q.mutex.RLock()
169170
defer q.mutex.RUnlock()
170171

171-
return q.users, nil
172+
users := q.users
173+
// Database orders by created_at
174+
sort.Slice(users, func(i, j int) bool {
175+
if users[i].CreatedAt.Equal(users[j].CreatedAt) {
176+
// Technically the postgres database also orders by uuid. So match
177+
// that behavior
178+
return users[i].ID.String() < users[j].ID.String()
179+
}
180+
return users[i].CreatedAt.Before(users[j].CreatedAt)
181+
})
182+
183+
if params.AfterUser != uuid.Nil {
184+
found := false
185+
for i := range users {
186+
if users[i].ID == params.AfterUser {
187+
// We want to return all users after index i.
188+
if i+1 >= len(users) {
189+
return []database.User{}, nil
190+
}
191+
users = users[i+1:]
192+
found = true
193+
break
194+
}
195+
}
196+
197+
// If no users after the time, then we return an empty list.
198+
if !found {
199+
return []database.User{}, nil
200+
}
201+
}
202+
203+
if params.Search != "" {
204+
tmp := make([]database.User, 0, len(users))
205+
for i, user := range users {
206+
if strings.Contains(user.Email, params.Search) {
207+
tmp = append(tmp, users[i])
208+
} else if strings.Contains(user.Username, params.Search) {
209+
tmp = append(tmp, users[i])
210+
} else if strings.Contains(user.Name, params.Search) {
211+
tmp = append(tmp, users[i])
212+
}
213+
}
214+
users = tmp
215+
}
216+
217+
if params.OffsetOpt > 0 {
218+
if int(params.OffsetOpt) > len(users)-1 {
219+
return []database.User{}, nil
220+
}
221+
users = users[params.OffsetOpt:]
222+
}
223+
224+
if params.LimitOpt > 0 {
225+
if int(params.LimitOpt) > len(users) {
226+
params.LimitOpt = int32(len(users))
227+
}
228+
users = users[:params.LimitOpt]
229+
}
230+
tmp := make([]database.User, len(users))
231+
copy(tmp, users)
232+
233+
return tmp, nil
172234
}
173235

174236
func (q *fakeQuerier) GetWorkspacesByTemplateID(_ context.Context, arg database.GetWorkspacesByTemplateIDParams) ([]database.Workspace, error) {

coderd/database/querier.go

+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)