Skip to content

Commit ed56c3b

Browse files
committed
Merge branch 'main' into 3321-template-space-b
2 parents a24eac4 + 3c10c7f commit ed56c3b

File tree

82 files changed

+1237
-549
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

82 files changed

+1237
-549
lines changed

Makefile

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,11 @@ else
4444
ZSTDFLAGS := -6
4545
endif
4646

47+
# Source files used for make targets, evaluated on use.
48+
GO_SRC_FILES = $(shell find . -not \( -path './.git/*' -o -path './build/*' -o -path './vendor/*' -o -path './.coderv2/*' -o -path './site/node_modules/*' -o -path './site/out/*' \) -type f -name '*.go')
49+
# All the shell files in the repo, excluding ignored files.
50+
SHELL_SRC_FILES = $(shell find . -not \( -path './.git/*' -o -path './build/*' -o -path './vendor/*' -o -path './.coderv2/*' -o -path './site/node_modules/*' -o -path './site/out/*' \) -type f -name '*.sh')
51+
4752
# All ${OS}_${ARCH} combos we build for. Windows binaries have the .exe suffix.
4853
OS_ARCHES := \
4954
linux_amd64 linux_arm64 linux_armv7 \
@@ -171,7 +176,7 @@ endef
171176
# You should probably use the non-version targets above instead if you're
172177
# calling this manually.
173178
$(CODER_ALL_BINARIES): go.mod go.sum \
174-
$(shell find . -not -path './vendor/*' -type f -name '*.go') \
179+
$(GO_SRC_FILES) \
175180
$(shell find ./examples/templates)
176181

177182
$(get-mode-os-arch-ext)
@@ -333,7 +338,7 @@ build/coder_helm_$(VERSION).tgz:
333338
--version "$(VERSION)" \
334339
--output "$@"
335340

336-
site/out/index.html: $(shell find ./site -not -path './site/node_modules/*' -type f -name '*.tsx') $(shell find ./site -not -path './site/node_modules/*' -type f -name '*.ts') site/package.json
341+
site/out/index.html: site/package.json $(shell find ./site -not -path './site/node_modules/*' -type f \( -name '*.ts' -o -name '*.tsx' \))
337342
./scripts/yarn_install.sh
338343
cd site
339344
yarn build
@@ -364,13 +369,13 @@ fmt/terraform: $(wildcard *.tf)
364369
terraform fmt -recursive
365370
.PHONY: fmt/terraform
366371

367-
fmt/shfmt: $(shell shfmt -f .)
372+
fmt/shfmt: $(SHELL_SRC_FILES)
368373
echo "--- shfmt"
369374
# Only do diff check in CI, errors on diff.
370375
ifdef CI
371-
shfmt -d $(shell shfmt -f .)
376+
shfmt -d $(SHELL_SRC_FILES)
372377
else
373-
shfmt -w $(shell shfmt -f .)
378+
shfmt -w $(SHELL_SRC_FILES)
374379
endif
375380
.PHONY: fmt/shfmt
376381

@@ -383,9 +388,9 @@ lint/go:
383388
.PHONY: lint/go
384389

385390
# Use shfmt to determine the shell files, takes editorconfig into consideration.
386-
lint/shellcheck: $(shell shfmt -f .)
391+
lint/shellcheck: $(SHELL_SRC_FILES)
387392
echo "--- shellcheck"
388-
shellcheck --external-sources $(shell shfmt -f .)
393+
shellcheck --external-sources $(SHELL_SRC_FILES)
389394
.PHONY: lint/shellcheck
390395

391396
# all gen targets should be added here and to gen/mark-fresh
@@ -446,8 +451,7 @@ site/src/api/typesGenerated.ts: scripts/apitypings/main.go $(shell find codersdk
446451
update-golden-files: cli/testdata/.gen-golden
447452
.PHONY: update-golden-files
448453

449-
cli/testdata/.gen-golden: $(wildcard cli/testdata/*.golden) \
450-
$(shell find . -not -path './vendor/*' -type f -name '*.go')
454+
cli/testdata/.gen-golden: $(wildcard cli/testdata/*.golden) $(GO_SRC_FILES)
451455

452456
go test ./cli -run=TestCommandHelp -update
453457
touch "$@"

cli/agent.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ func workspaceAgent() *cobra.Command {
9797
if err != nil {
9898
return xerrors.Errorf("CODER_AGENT_TOKEN must be set for token auth: %w", err)
9999
}
100-
client.SessionToken = token
100+
client.SetSessionToken(token)
101101
case "google-instance-identity":
102102
// This is *only* done for testing to mock client authentication.
103103
// This will never be set in a production scenario.
@@ -153,13 +153,13 @@ func workspaceAgent() *cobra.Command {
153153
Logger: logger,
154154
ExchangeToken: func(ctx context.Context) (string, error) {
155155
if exchangeToken == nil {
156-
return client.SessionToken, nil
156+
return client.SessionToken(), nil
157157
}
158158
resp, err := exchangeToken(ctx)
159159
if err != nil {
160160
return "", err
161161
}
162-
client.SessionToken = resp.SessionToken
162+
client.SetSessionToken(resp.SessionToken)
163163
return resp.SessionToken, nil
164164
},
165165
EnvironmentVariables: map[string]string{

cli/clitest/clitest.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ func NewWithSubcommands(
4343

4444
// SetupConfig applies the URL and SessionToken of the client to the config.
4545
func SetupConfig(t *testing.T, client *codersdk.Client, root config.Root) {
46-
err := root.Session().Write(client.SessionToken)
46+
err := root.Session().Write(client.SessionToken())
4747
require.NoError(t, err)
4848
err = root.URL().Write(client.URL.String())
4949
require.NoError(t, err)

cli/cliui/agent.go

Lines changed: 48 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,11 @@ func Agent(ctx context.Context, writer io.Writer, opts AgentOptions) error {
3535
if err != nil {
3636
return xerrors.Errorf("fetch: %w", err)
3737
}
38+
3839
if agent.Status == codersdk.WorkspaceAgentConnected {
3940
return nil
4041
}
41-
if agent.Status == codersdk.WorkspaceAgentDisconnected {
42-
opts.WarnInterval = 0
43-
}
42+
4443
spin := spinner.New(spinner.CharSets[78], 100*time.Millisecond, spinner.WithColor("fgHiGreen"))
4544
spin.Writer = writer
4645
spin.ForceOutput = true
@@ -65,43 +64,70 @@ func Agent(ctx context.Context, writer io.Writer, opts AgentOptions) error {
6564
os.Exit(1)
6665
}()
6766

68-
ticker := time.NewTicker(opts.FetchInterval)
69-
defer ticker.Stop()
70-
timer := time.NewTimer(opts.WarnInterval)
71-
defer timer.Stop()
72-
go func() {
73-
select {
74-
case <-ctx.Done():
75-
return
76-
case <-timer.C:
77-
}
67+
warningShown := false
68+
warnAfter := time.NewTimer(opts.WarnInterval)
69+
defer warnAfter.Stop()
70+
showWarning := func() {
71+
warnAfter.Stop()
72+
7873
resourceMutex.Lock()
7974
defer resourceMutex.Unlock()
80-
message := "Don't panic, your workspace is booting up!"
81-
if agent.Status == codersdk.WorkspaceAgentDisconnected {
82-
message = "The workspace agent lost connection! Wait for it to reconnect or restart your workspace."
75+
if warningShown {
76+
return
8377
}
78+
warningShown = true
79+
80+
message := waitingMessage(agent)
8481
// This saves the cursor position, then defers clearing from the cursor
8582
// position to the end of the screen.
8683
_, _ = fmt.Fprintf(writer, "\033[s\r\033[2K%s\n\n", Styles.Paragraph.Render(Styles.Prompt.String()+message))
8784
defer fmt.Fprintf(writer, "\033[u\033[J")
85+
}
86+
go func() {
87+
select {
88+
case <-ctx.Done():
89+
case <-warnAfter.C:
90+
showWarning()
91+
}
8892
}()
93+
94+
fetchInterval := time.NewTicker(opts.FetchInterval)
95+
defer fetchInterval.Stop()
8996
for {
9097
select {
9198
case <-ctx.Done():
9299
return ctx.Err()
93-
case <-ticker.C:
100+
case <-fetchInterval.C:
94101
}
95102
resourceMutex.Lock()
96103
agent, err = opts.Fetch(ctx)
97104
if err != nil {
98-
return xerrors.Errorf("fetch: %w", err)
99-
}
100-
if agent.Status != codersdk.WorkspaceAgentConnected {
101105
resourceMutex.Unlock()
102-
continue
106+
return xerrors.Errorf("fetch: %w", err)
103107
}
104108
resourceMutex.Unlock()
105-
return nil
109+
switch agent.Status {
110+
case codersdk.WorkspaceAgentConnected:
111+
return nil
112+
case codersdk.WorkspaceAgentTimeout, codersdk.WorkspaceAgentDisconnected:
113+
showWarning()
114+
}
115+
}
116+
}
117+
118+
func waitingMessage(agent codersdk.WorkspaceAgent) string {
119+
var m string
120+
switch agent.Status {
121+
case codersdk.WorkspaceAgentTimeout:
122+
m = "The workspace agent is having trouble connecting."
123+
case codersdk.WorkspaceAgentDisconnected:
124+
m = "The workspace agent lost connection!"
125+
default:
126+
// Not a failure state, no troubleshooting necessary.
127+
return "Don't panic, your workspace is booting up!"
128+
}
129+
if agent.TroubleshootingURL != "" {
130+
return fmt.Sprintf("%s See troubleshooting instructions at: %s", m, agent.TroubleshootingURL)
106131
}
132+
return fmt.Sprintf("%s Wait for it to (re)connect or restart your workspace.", m)
107133
}

cli/cliui/resources.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,13 @@ func renderAgentStatus(agent codersdk.WorkspaceAgent) string {
127127
since := database.Now().Sub(*agent.DisconnectedAt)
128128
return Styles.Error.Render("⦾ disconnected") + " " +
129129
Styles.Placeholder.Render("["+strconv.Itoa(int(since.Seconds()))+"s]")
130+
case codersdk.WorkspaceAgentTimeout:
131+
since := database.Now().Sub(agent.CreatedAt)
132+
return fmt.Sprintf(
133+
"%s %s",
134+
Styles.Warn.Render("⦾ timeout"),
135+
Styles.Placeholder.Render("["+strconv.Itoa(int(since.Seconds()))+"s]"),
136+
)
130137
case codersdk.WorkspaceAgentConnected:
131138
return Styles.Keyword.Render("⦿ connected")
132139
default:

cli/configssh_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ func TestConfigSSH(t *testing.T) {
105105
workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID)
106106
coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
107107
agentClient := codersdk.New(client.URL)
108-
agentClient.SessionToken = authToken
108+
agentClient.SetSessionToken(authToken)
109109
agentCloser := agent.New(agent.Options{
110110
Client: agentClient,
111111
Logger: slogtest.Make(t, nil).Named("agent"),

cli/login.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ func login() *cobra.Command {
214214
Text: "Paste your token here:",
215215
Secret: true,
216216
Validate: func(token string) error {
217-
client.SessionToken = token
217+
client.SetSessionToken(token)
218218
_, err := client.User(cmd.Context(), codersdk.Me)
219219
if err != nil {
220220
return xerrors.New("That's not a valid token!")
@@ -228,7 +228,7 @@ func login() *cobra.Command {
228228
}
229229

230230
// Login to get user data - verify it is OK before persisting
231-
client.SessionToken = sessionToken
231+
client.SetSessionToken(sessionToken)
232232
resp, err := client.User(cmd.Context(), codersdk.Me)
233233
if err != nil {
234234
return xerrors.Errorf("get user: %w", err)

cli/login_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ func TestLogin(t *testing.T) {
148148
}()
149149

150150
pty.ExpectMatch("Paste your token here:")
151-
pty.WriteLine(client.SessionToken)
151+
pty.WriteLine(client.SessionToken())
152152
pty.ExpectMatch("Welcome to Coder")
153153
<-doneChan
154154
})
@@ -183,11 +183,11 @@ func TestLogin(t *testing.T) {
183183
t.Parallel()
184184
client := coderdtest.New(t, nil)
185185
coderdtest.CreateFirstUser(t, client)
186-
root, cfg := clitest.New(t, "login", client.URL.String(), "--token", client.SessionToken)
186+
root, cfg := clitest.New(t, "login", client.URL.String(), "--token", client.SessionToken())
187187
err := root.Execute()
188188
require.NoError(t, err)
189189
sessionFile, err := cfg.Session().Read()
190190
require.NoError(t, err)
191-
require.Equal(t, client.SessionToken, sessionFile)
191+
require.Equal(t, client.SessionToken(), sessionFile)
192192
})
193193
}

cli/logout_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ func login(t *testing.T, pty *ptytest.PTY) config.Root {
209209
}()
210210

211211
pty.ExpectMatch("Paste your token here:")
212-
pty.WriteLine(client.SessionToken)
212+
pty.WriteLine(client.SessionToken())
213213
pty.ExpectMatch("Welcome to Coder")
214214
<-doneChan
215215

cli/root.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,7 @@ func CreateClient(cmd *cobra.Command) (*codersdk.Client, error) {
306306
if err != nil {
307307
return nil, err
308308
}
309-
client.SessionToken = token
309+
client.SetSessionToken(token)
310310
return client, nil
311311
}
312312

@@ -347,7 +347,7 @@ func createAgentClient(cmd *cobra.Command) (*codersdk.Client, error) {
347347
return nil, err
348348
}
349349
client := codersdk.New(serverURL)
350-
client.SessionToken = token
350+
client.SetSessionToken(token)
351351
return client, nil
352352
}
353353

cli/server.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,24 @@ func Server(vip *viper.Viper, newAPI func(context.Context, *coderd.Options) (*co
447447
if err != nil {
448448
return xerrors.Errorf("migrate up: %w", err)
449449
}
450+
// The default is 0 but the request will fail with a 500 if the DB
451+
// cannot accept new connections, so we try to limit that here.
452+
// Requests will wait for a new connection instead of a hard error
453+
// if a limit is set.
454+
sqlDB.SetMaxOpenConns(10)
455+
// Allow a max of 3 idle connections at a time. Lower values end up
456+
// creating a lot of connection churn. Since each connection uses about
457+
// 10MB of memory, we're allocating 30MB to Postgres connections per
458+
// replica, but is better than causing Postgres to spawn a thread 15-20
459+
// times/sec. PGBouncer's transaction pooling is not the greatest so
460+
// it's not optimal for us to deploy.
461+
//
462+
// This was set to 10 before we started doing HA deployments, but 3 was
463+
// later determined to be a better middle ground as to not use up all
464+
// of PGs default connection limit while simultaneously avoiding a lot
465+
// of connection churn.
466+
sqlDB.SetMaxIdleConns(3)
467+
450468
options.Database = database.New(sqlDB)
451469
options.Pubsub, err = database.NewPubsub(ctx, sqlDB, cfg.PostgresURL.Value)
452470
if err != nil {

cli/speedtest_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@ func TestSpeedtest(t *testing.T) {
2020
if testing.Short() {
2121
t.Skip("This test takes a minimum of 5ms per a hardcoded value in Tailscale!")
2222
}
23-
client, workspace, agentToken := setupWorkspaceForAgent(t)
23+
client, workspace, agentToken := setupWorkspaceForAgent(t, nil)
2424
agentClient := codersdk.New(client.URL)
25-
agentClient.SessionToken = agentToken
25+
agentClient.SetSessionToken(agentToken)
2626
agentCloser := agent.New(agent.Options{
2727
Client: agentClient,
2828
Logger: slogtest.Make(t, nil).Named("agent"),

0 commit comments

Comments
 (0)