Skip to content

Commit 0ba8fa2

Browse files
committed
Merge branch 'main' into colin/rm-wsconncache2
2 parents b5ea538 + 1406838 commit 0ba8fa2

File tree

101 files changed

+3538
-513
lines changed

Some content is hidden

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

101 files changed

+3538
-513
lines changed

.github/workflows/ci.yaml

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,10 @@ jobs:
4747
docs:
4848
- "docs/**"
4949
- "README.md"
50-
# For testing:
51-
# - ".github/**"
50+
- "examples/templates/**"
51+
- "examples/web-server/**"
52+
- "examples/monitoring/**"
53+
- "examples/lima/**"
5254
go:
5355
- "**.sql"
5456
- "**.go"
@@ -231,7 +233,7 @@ jobs:
231233

232234
- uses: hashicorp/setup-terraform@v2
233235
with:
234-
terraform_version: 1.1.9
236+
terraform_version: 1.5.1
235237
terraform_wrapper: false
236238

237239
- name: Test with Mock Database
@@ -296,7 +298,7 @@ jobs:
296298

297299
- uses: hashicorp/setup-terraform@v2
298300
with:
299-
terraform_version: 1.1.9
301+
terraform_version: 1.5.1
300302
terraform_wrapper: false
301303

302304
- name: Test with PostgreSQL Database
@@ -338,6 +340,11 @@ jobs:
338340

339341
- uses: ./.github/actions/setup-go
340342

343+
- uses: hashicorp/setup-terraform@v2
344+
with:
345+
terraform_version: 1.5.1
346+
terraform_wrapper: false
347+
341348
- name: Run Tests
342349
run: |
343350
gotestsum --junitfile="gotests.xml" -- -race ./...
@@ -474,7 +481,7 @@ jobs:
474481

475482
- uses: hashicorp/setup-terraform@v2
476483
with:
477-
terraform_version: 1.1.9
484+
terraform_version: 1.5.1
478485
terraform_wrapper: false
479486

480487
- name: Build

.github/workflows/pr-cleanup.yaml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ jobs:
2525
fi
2626
2727
- name: Delete image
28+
continue-on-error: true
2829
uses: bots-house/ghcr-delete-image-action@v1.1.0
2930
with:
3031
owner: coder
@@ -33,20 +34,17 @@ jobs:
3334
tag: pr${{ steps.pr_number.outputs.PR_NUMBER }}
3435

3536
- name: Set up kubeconfig
36-
if: always()
3737
run: |
3838
set -euxo pipefail
3939
mkdir -p ~/.kube
4040
echo "${{ secrets.DELIVERYBOT_KUBECONFIG }}" > ~/.kube/config
4141
export KUBECONFIG=~/.kube/config
4242
4343
- name: Delete helm release
44-
if: always()
4544
run: |
4645
set -euxo pipefail
4746
helm delete --namespace "pr${{ steps.pr_number.outputs.PR_NUMBER }}" "pr${{ steps.pr_number.outputs.PR_NUMBER }}" || echo "helm release not found"
4847
4948
- name: "Remove PR namespace"
50-
if: always()
5149
run: |
5250
kubectl delete namespace "pr${{ steps.pr_number.outputs.PR_NUMBER }}" || echo "namespace not found"

agent/agent.go

Lines changed: 19 additions & 153 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package agent
22

33
import (
4-
"bufio"
54
"bytes"
65
"context"
76
"encoding/binary"
@@ -876,26 +875,30 @@ func (a *agent) runScript(ctx context.Context, lifecycle, script string) (err er
876875
}
877876
cmd := cmdPty.AsExec()
878877

879-
var writer io.Writer = fileWriter
878+
var stdout, stderr io.Writer = fileWriter, fileWriter
880879
if lifecycle == "startup" {
881-
// Create pipes for startup logs reader and writer
882-
logsReader, logsWriter := io.Pipe()
880+
send, flushAndClose := agentsdk.StartupLogsSender(a.client.PatchStartupLogs, logger)
881+
// If ctx is canceled here (or in a writer below), we may be
882+
// discarding logs, but that's okay because we're shutting down
883+
// anyway. We could consider creating a new context here if we
884+
// want better control over flush during shutdown.
883885
defer func() {
884-
_ = logsReader.Close()
885-
}()
886-
writer = io.MultiWriter(fileWriter, logsWriter)
887-
flushedLogs, err := a.trackScriptLogs(ctx, logsReader)
888-
if err != nil {
889-
return xerrors.Errorf("track %s script logs: %w", lifecycle, err)
890-
}
891-
defer func() {
892-
_ = logsWriter.Close()
893-
<-flushedLogs
886+
if err := flushAndClose(ctx); err != nil {
887+
logger.Warn(ctx, "flush startup logs failed", slog.Error(err))
888+
}
894889
}()
890+
891+
infoW := agentsdk.StartupLogsWriter(ctx, send, codersdk.LogLevelInfo)
892+
defer infoW.Close()
893+
errW := agentsdk.StartupLogsWriter(ctx, send, codersdk.LogLevelError)
894+
defer errW.Close()
895+
896+
stdout = io.MultiWriter(fileWriter, infoW)
897+
stderr = io.MultiWriter(fileWriter, errW)
895898
}
896899

897-
cmd.Stdout = writer
898-
cmd.Stderr = writer
900+
cmd.Stdout = stdout
901+
cmd.Stderr = stderr
899902

900903
start := time.Now()
901904
defer func() {
@@ -926,143 +929,6 @@ func (a *agent) runScript(ctx context.Context, lifecycle, script string) (err er
926929
return nil
927930
}
928931

929-
func (a *agent) trackScriptLogs(ctx context.Context, reader io.ReadCloser) (chan struct{}, error) {
930-
// Synchronous sender, there can only be one outbound send at a time.
931-
//
932-
// It's important that we either flush or drop all logs before returning
933-
// because the startup state is reported after flush.
934-
sendDone := make(chan struct{})
935-
send := make(chan []agentsdk.StartupLog, 1)
936-
go func() {
937-
// Set flushTimeout and backlogLimit so that logs are uploaded
938-
// once every 250ms or when 100 logs have been added to the
939-
// backlog, whichever comes first.
940-
flushTimeout := 250 * time.Millisecond
941-
backlogLimit := 100
942-
943-
flush := time.NewTicker(flushTimeout)
944-
945-
var backlog []agentsdk.StartupLog
946-
defer func() {
947-
flush.Stop()
948-
_ = reader.Close() // Ensure read routine is closed.
949-
if len(backlog) > 0 {
950-
a.logger.Debug(ctx, "track script logs sender exiting, discarding logs", slog.F("discarded_logs_count", len(backlog)))
951-
}
952-
a.logger.Debug(ctx, "track script logs sender exited")
953-
close(sendDone)
954-
}()
955-
956-
done := false
957-
for {
958-
flushed := false
959-
select {
960-
case <-ctx.Done():
961-
return
962-
case <-a.closed:
963-
return
964-
// Close (!ok) can be triggered by the reader closing due to
965-
// EOF or due to agent closing, when this happens we attempt
966-
// a final flush. If the context is canceled this will be a
967-
// no-op.
968-
case logs, ok := <-send:
969-
done = !ok
970-
if ok {
971-
backlog = append(backlog, logs...)
972-
flushed = len(backlog) >= backlogLimit
973-
}
974-
case <-flush.C:
975-
flushed = true
976-
}
977-
978-
if (done || flushed) && len(backlog) > 0 {
979-
flush.Stop() // Lower the chance of a double flush.
980-
981-
// Retry uploading logs until successful or a specific
982-
// error occurs.
983-
for r := retry.New(time.Second, 5*time.Second); r.Wait(ctx); {
984-
err := a.client.PatchStartupLogs(ctx, agentsdk.PatchStartupLogs{
985-
Logs: backlog,
986-
})
987-
if err == nil {
988-
break
989-
}
990-
991-
if errors.Is(err, context.Canceled) {
992-
return
993-
}
994-
var sdkErr *codersdk.Error
995-
if errors.As(err, &sdkErr) {
996-
if sdkErr.StatusCode() == http.StatusRequestEntityTooLarge {
997-
a.logger.Warn(ctx, "startup logs too large, dropping logs")
998-
break
999-
}
1000-
}
1001-
a.logger.Error(ctx, "upload startup logs failed", slog.Error(err), slog.F("to_send", backlog))
1002-
}
1003-
if ctx.Err() != nil {
1004-
return
1005-
}
1006-
backlog = nil
1007-
1008-
// Anchor flush to the last log upload.
1009-
flush.Reset(flushTimeout)
1010-
}
1011-
if done {
1012-
return
1013-
}
1014-
}
1015-
}()
1016-
1017-
// Forward read lines to the sender or queue them for when the
1018-
// sender is ready to process them.
1019-
//
1020-
// We only need to track this goroutine since it will ensure that
1021-
// the sender has closed before returning.
1022-
logsDone := make(chan struct{})
1023-
err := a.trackConnGoroutine(func() {
1024-
defer func() {
1025-
close(send)
1026-
<-sendDone
1027-
a.logger.Debug(ctx, "track script logs reader exited")
1028-
close(logsDone)
1029-
}()
1030-
1031-
var queue []agentsdk.StartupLog
1032-
1033-
s := bufio.NewScanner(reader)
1034-
for s.Scan() {
1035-
select {
1036-
case <-ctx.Done():
1037-
return
1038-
case <-a.closed:
1039-
return
1040-
case queue = <-send:
1041-
// Not captured by sender yet, re-use.
1042-
default:
1043-
}
1044-
1045-
queue = append(queue, agentsdk.StartupLog{
1046-
CreatedAt: database.Now(),
1047-
Output: s.Text(),
1048-
})
1049-
send <- queue
1050-
queue = nil
1051-
}
1052-
if err := s.Err(); err != nil {
1053-
a.logger.Warn(ctx, "scan startup logs ended unexpectedly", slog.Error(err))
1054-
}
1055-
})
1056-
if err != nil {
1057-
close(send)
1058-
<-sendDone
1059-
close(logsDone)
1060-
return logsDone, err
1061-
}
1062-
1063-
return logsDone, nil
1064-
}
1065-
1066932
func (a *agent) handleReconnectingPTY(ctx context.Context, logger slog.Logger, msg codersdk.WorkspaceAgentReconnectingPTYInit, conn net.Conn) (retErr error) {
1067933
defer conn.Close()
1068934
a.metrics.connectionsTotal.Add(1)

cli/clistat/cgroup.go

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,10 @@ func (s *Statter) ContainerCPU() (*Result, error) {
8484
}
8585

8686
r := &Result{
87-
Unit: "cores",
88-
Used: used2 - used1,
89-
Total: ptr.To(total),
87+
Unit: "cores",
88+
Used: used2 - used1,
89+
Total: ptr.To(total),
90+
Prefix: PrefixDefault,
9091
}
9192
return r, nil
9293
}
@@ -184,20 +185,20 @@ func (s *Statter) cGroupV1CPUUsed() (float64, error) {
184185

185186
// ContainerMemory returns the memory usage of the container cgroup.
186187
// If the system is not containerized, this always returns nil.
187-
func (s *Statter) ContainerMemory() (*Result, error) {
188+
func (s *Statter) ContainerMemory(p Prefix) (*Result, error) {
188189
if ok, err := IsContainerized(s.fs); err != nil || !ok {
189190
return nil, nil //nolint:nilnil
190191
}
191192

192193
if s.isCGroupV2() {
193-
return s.cGroupV2Memory()
194+
return s.cGroupV2Memory(p)
194195
}
195196

196197
// Fall back to CGroupv1
197-
return s.cGroupV1Memory()
198+
return s.cGroupV1Memory(p)
198199
}
199200

200-
func (s *Statter) cGroupV2Memory() (*Result, error) {
201+
func (s *Statter) cGroupV2Memory(p Prefix) (*Result, error) {
201202
maxUsageBytes, err := readInt64(s.fs, cgroupV2MemoryMaxBytes)
202203
if err != nil {
203204
return nil, xerrors.Errorf("read memory total: %w", err)
@@ -214,13 +215,14 @@ func (s *Statter) cGroupV2Memory() (*Result, error) {
214215
}
215216

216217
return &Result{
217-
Total: ptr.To(float64(maxUsageBytes)),
218-
Used: float64(currUsageBytes - inactiveFileBytes),
219-
Unit: "B",
218+
Total: ptr.To(float64(maxUsageBytes)),
219+
Used: float64(currUsageBytes - inactiveFileBytes),
220+
Unit: "B",
221+
Prefix: p,
220222
}, nil
221223
}
222224

223-
func (s *Statter) cGroupV1Memory() (*Result, error) {
225+
func (s *Statter) cGroupV1Memory(p Prefix) (*Result, error) {
224226
maxUsageBytes, err := readInt64(s.fs, cgroupV1MemoryMaxUsageBytes)
225227
if err != nil {
226228
return nil, xerrors.Errorf("read memory total: %w", err)
@@ -239,9 +241,10 @@ func (s *Statter) cGroupV1Memory() (*Result, error) {
239241

240242
// Total memory used is usage - total_inactive_file
241243
return &Result{
242-
Total: ptr.To(float64(maxUsageBytes)),
243-
Used: float64(usageBytes - totalInactiveFileBytes),
244-
Unit: "B",
244+
Total: ptr.To(float64(maxUsageBytes)),
245+
Used: float64(usageBytes - totalInactiveFileBytes),
246+
Unit: "B",
247+
Prefix: p,
245248
}, nil
246249
}
247250

cli/clistat/disk.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import (
1010

1111
// Disk returns the disk usage of the given path.
1212
// If path is empty, it returns the usage of the root directory.
13-
func (*Statter) Disk(path string) (*Result, error) {
13+
func (*Statter) Disk(p Prefix, path string) (*Result, error) {
1414
if path == "" {
1515
path = "/"
1616
}
@@ -22,5 +22,6 @@ func (*Statter) Disk(path string) (*Result, error) {
2222
r.Total = ptr.To(float64(stat.Blocks * uint64(stat.Bsize)))
2323
r.Used = float64(stat.Blocks-stat.Bfree) * float64(stat.Bsize)
2424
r.Unit = "B"
25+
r.Prefix = p
2526
return &r, nil
2627
}

cli/clistat/disk_windows.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import (
77

88
// Disk returns the disk usage of the given path.
99
// If path is empty, it defaults to C:\
10-
func (*Statter) Disk(path string) (*Result, error) {
10+
func (*Statter) Disk(p Prefix, path string) (*Result, error) {
1111
if path == "" {
1212
path = `C:\`
1313
}
@@ -31,5 +31,6 @@ func (*Statter) Disk(path string) (*Result, error) {
3131
r.Total = ptr.To(float64(totalBytes))
3232
r.Used = float64(totalBytes - freeBytes)
3333
r.Unit = "B"
34+
r.Prefix = p
3435
return &r, nil
3536
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy