Skip to content

Commit 8e7f8bd

Browse files
committed
Merge branch 'main' of github.com:coder/coder into bq/3516
2 parents a6f976e + 1b56a8c commit 8e7f8bd

File tree

172 files changed

+4507
-1669
lines changed

Some content is hidden

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

172 files changed

+4507
-1669
lines changed

.github/CODEOWNERS

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
site/ @coder/frontend
2-
docs/ @ammario
2+
docs/ @coder/docs
3+
README.md @coder/docs
4+
ADOPTERS.md @coder/docs

.github/workflows/coder.yaml

+11-3
Original file line numberDiff line numberDiff line change
@@ -194,9 +194,15 @@ jobs:
194194
run: ./scripts/yarn_install.sh
195195

196196
- name: Install Protoc
197-
uses: arduino/setup-protoc@v1
198-
with:
199-
version: "3.20.0"
197+
run: |
198+
# protoc must be in lockstep with our dogfood Dockerfile
199+
# or the version in the comments will differ.
200+
set -x
201+
cd dogfood
202+
DOCKER_BUILDKIT=1 docker build . --target proto -t protoc
203+
protoc_dir=/usr/local/bin/protoc
204+
docker run --rm --entrypoint cat protoc /tmp/bin/protoc > $protoc_dir
205+
chmod +x $protoc_dir
200206
- uses: actions/setup-go@v3
201207
with:
202208
go-version: "~1.19"
@@ -484,6 +490,8 @@ jobs:
484490
restore-keys: |
485491
js-${{ runner.os }}-
486492
493+
- name: Install goimports
494+
run: go install golang.org/x/tools/cmd/goimports@latest
487495
- name: Install nfpm
488496
run: go install github.com/goreleaser/nfpm/v2/cmd/nfpm@v2.16.0
489497

.github/workflows/release.yaml

+2-2
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ jobs:
5252

5353
- uses: actions/setup-go@v3
5454
with:
55-
go-version: "~1.18"
55+
go-version: "~1.19"
5656

5757
- name: Cache Node
5858
id: cache-node
@@ -165,7 +165,7 @@ jobs:
165165

166166
- uses: actions/setup-go@v3
167167
with:
168-
go-version: "~1.18"
168+
go-version: "~1.19"
169169

170170
- name: Import Signing Certificates
171171
uses: Apple-Actions/import-codesign-certs@v1

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,4 @@ site/out/
4242
.vscode/*.log
4343
**/*.swp
4444
.coderv2/*
45+
**/__debug_bin

ADOPTERS.md

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Adopters
2+
[!["Join us on
3+
Discord"](https://img.shields.io/badge/join-us%20on%20Discord-gray.svg?longCache=true&logo=discord&colorB=green)](https://coder.com/chat?utm_source=github.com/coder/coder&utm_medium=github&utm_campaign=adopters.md) [![Twitter
4+
Follow](https://img.shields.io/twitter/follow/coderhq?label=%40coderhq&style=social)](https://twitter.com/coderhq)
5+
6+
🦩 _If you're using Coder in your organization, please try to add your company name to this list. It really helps the project to gain momentum and credibility. It's a small contribution back to the project with a big impact. You can do this by by editing this file and contributing your changes via a pull-request on GitHub._
7+
8+
> 👋 _If you are considering using Coder in your organization please introduce yourself via https://coder.com/demo_ 🙇🏻‍♂️
9+
10+
| Organization | Contact | Description of Use |
11+
| --------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
12+
| [Coder](https://www.coder.com) | [@coderhq](https://twitter.com/coderhq) | Coder builds coder with Coder. |

Makefile

+27-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@ bin: $(shell find . -not -path './vendor/*' -type f -name '*.go') go.mod go.sum
3030
darwin:amd64,arm64
3131
.PHONY: bin
3232

33-
build: site/out/index.html $(shell find . -not -path './vendor/*' -type f -name '*.go') go.mod go.sum $(shell find ./examples/templates)
33+
GO_FILES=$(shell find . -not -path './vendor/*' -type f -name '*.go') go.mod go.sum $(shell find ./examples/templates)
34+
35+
build: site/out/index.html $(GO_FILES)
3436
rm -rf ./dist
3537
mkdir -p ./dist
3638
rm -f ./site/out/bin/coder*
@@ -55,6 +57,30 @@ build: site/out/index.html $(shell find . -not -path './vendor/*' -type f -name
5557
darwin:amd64,arm64
5658
.PHONY: build
5759

60+
# Builds a test binary for just Linux
61+
build-linux-test: site/out/index.html $(GO_FILES)
62+
rm -rf ./dist
63+
mkdir -p ./dist
64+
rm -f ./site/out/bin/coder*
65+
66+
# build slim artifacts and copy them to the site output directory
67+
./scripts/build_go_slim.sh \
68+
--version "$(VERSION)" \
69+
--compress 6 \
70+
--output ./dist/ \
71+
linux:amd64,armv7,arm64 \
72+
windows:amd64,arm64 \
73+
darwin:amd64,arm64
74+
75+
# build not-so-slim artifacts with the default name format
76+
./scripts/build_go_matrix.sh \
77+
--version "$(VERSION)" \
78+
--output ./dist/ \
79+
--archive \
80+
--package-linux \
81+
linux:amd64
82+
.PHONY: build-linux-test
83+
5884
# Runs migrations to output a dump of the database.
5985
coderd/database/dump.sql: coderd/database/gen/dump/main.go $(wildcard coderd/database/migrations/*.sql)
6086
go run coderd/database/gen/dump/main.go

README.md

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Coder
22

33
[!["Join us on
4-
Discord"](https://img.shields.io/badge/join-us%20on%20Discord-gray.svg?longCache=true&logo=discord&colorB=green)](https://discord.gg/coder)
4+
Discord"](https://img.shields.io/badge/join-us%20on%20Discord-gray.svg?longCache=true&logo=discord&colorB=green)](https://coder.com/chat?utm_source=github.com/coder/coder&utm_medium=github&utm_campaign=readme.md)
55
[![codecov](https://codecov.io/gh/coder/coder/branch/main/graph/badge.svg?token=TNLW3OAP6G)](https://codecov.io/gh/coder/coder)
66
[![Go Reference](https://pkg.go.dev/badge/github.com/coder/coder.svg)](https://pkg.go.dev/github.com/coder/coder)
77
[![Twitter
@@ -89,12 +89,14 @@ _Last updated: 5/27/22_
8989

9090
## Community and Support
9191

92-
Join our community on [Discord](https://discord.gg/coder) and [Twitter](https://twitter.com/coderhq)!
92+
Join our community on [Discord](https://coder.com/chat?utm_source=github.com/coder/coder&utm_medium=github&utm_campaign=readme.md) and [Twitter](https://twitter.com/coderhq)!
9393

9494
[Suggest improvements and report problems](https://github.com/coder/coder/issues/new/choose)
9595

9696
## Contributing
9797

98+
If you're using Coder in your organization, please try to add your company name to the [ADOPTERS.md](./ADOPTERS.md). It really helps the project to gain momentum and credibility. It's a small contribution back to the project with a big impact.
99+
98100
Read the [contributing docs](https://coder.com/docs/coder-oss/latest/CONTRIBUTING).
99101

100102
Find our list of contributors [here](https://github.com/coder/coder/graphs/contributors).

agent/agent.go

+67-15
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import (
2929
"go.uber.org/atomic"
3030
gossh "golang.org/x/crypto/ssh"
3131
"golang.org/x/xerrors"
32+
"tailscale.com/net/speedtest"
3233
"tailscale.com/tailcfg"
3334

3435
"cdr.dev/slog"
@@ -58,13 +59,15 @@ var (
5859
tailnetIP = netip.MustParseAddr("fd7a:115c:a1e0:49d6:b259:b7ac:b1b2:48f4")
5960
tailnetSSHPort = 1
6061
tailnetReconnectingPTYPort = 2
62+
tailnetSpeedtestPort = 3
6163
)
6264

6365
type Options struct {
6466
CoordinatorDialer CoordinatorDialer
6567
WebRTCDialer WebRTCDialer
6668
FetchMetadata FetchMetadata
6769

70+
StatsReporter StatsReporter
6871
ReconnectingPTYTimeout time.Duration
6972
EnvironmentVariables map[string]string
7073
Logger slog.Logger
@@ -100,6 +103,8 @@ func New(options Options) io.Closer {
100103
envVars: options.EnvironmentVariables,
101104
coordinatorDialer: options.CoordinatorDialer,
102105
fetchMetadata: options.FetchMetadata,
106+
stats: &Stats{},
107+
statsReporter: options.StatsReporter,
103108
}
104109
server.init(ctx)
105110
return server
@@ -125,6 +130,8 @@ type agent struct {
125130

126131
network *tailnet.Conn
127132
coordinatorDialer CoordinatorDialer
133+
stats *Stats
134+
statsReporter StatsReporter
128135
}
129136

130137
func (a *agent) run(ctx context.Context) {
@@ -194,6 +201,13 @@ func (a *agent) runTailnet(ctx context.Context, derpMap *tailcfg.DERPMap) {
194201
a.logger.Critical(ctx, "create tailnet", slog.Error(err))
195202
return
196203
}
204+
a.network.SetForwardTCPCallback(func(conn net.Conn, listenerExists bool) net.Conn {
205+
if listenerExists {
206+
// If a listener already exists, we would double-wrap the conn.
207+
return conn
208+
}
209+
return a.stats.wrapConn(conn)
210+
})
197211
go a.runCoordinator(ctx)
198212

199213
sshListener, err := a.network.Listen("tcp", ":"+strconv.Itoa(tailnetSSHPort))
@@ -207,7 +221,7 @@ func (a *agent) runTailnet(ctx context.Context, derpMap *tailcfg.DERPMap) {
207221
if err != nil {
208222
return
209223
}
210-
go a.sshServer.HandleConn(conn)
224+
go a.sshServer.HandleConn(a.stats.wrapConn(conn))
211225
}
212226
}()
213227
reconnectingPTYListener, err := a.network.Listen("tcp", ":"+strconv.Itoa(tailnetReconnectingPTYPort))
@@ -219,8 +233,10 @@ func (a *agent) runTailnet(ctx context.Context, derpMap *tailcfg.DERPMap) {
219233
for {
220234
conn, err := reconnectingPTYListener.Accept()
221235
if err != nil {
236+
a.logger.Debug(ctx, "accept pty failed", slog.Error(err))
222237
return
223238
}
239+
conn = a.stats.wrapConn(conn)
224240
// This cannot use a JSON decoder, since that can
225241
// buffer additional data that is required for the PTY.
226242
rawLen := make([]byte, 2)
@@ -242,6 +258,23 @@ func (a *agent) runTailnet(ctx context.Context, derpMap *tailcfg.DERPMap) {
242258
go a.handleReconnectingPTY(ctx, msg, conn)
243259
}
244260
}()
261+
speedtestListener, err := a.network.Listen("tcp", ":"+strconv.Itoa(tailnetSpeedtestPort))
262+
if err != nil {
263+
a.logger.Critical(ctx, "listen for speedtest", slog.Error(err))
264+
return
265+
}
266+
go func() {
267+
for {
268+
conn, err := speedtestListener.Accept()
269+
if err != nil {
270+
a.logger.Debug(ctx, "speedtest listener failed", slog.Error(err))
271+
return
272+
}
273+
go func() {
274+
_ = speedtest.ServeConn(conn)
275+
}()
276+
}
277+
}()
245278
}
246279

247280
// runCoordinator listens for nodes and updates the self-node as it changes.
@@ -364,17 +397,17 @@ func (a *agent) runStartupScript(ctx context.Context, script string) error {
364397
return nil
365398
}
366399

367-
func (a *agent) handlePeerConn(ctx context.Context, conn *peer.Conn) {
400+
func (a *agent) handlePeerConn(ctx context.Context, peerConn *peer.Conn) {
368401
go func() {
369402
select {
370403
case <-a.closed:
371-
case <-conn.Closed():
404+
case <-peerConn.Closed():
372405
}
373-
_ = conn.Close()
406+
_ = peerConn.Close()
374407
a.connCloseWait.Done()
375408
}()
376409
for {
377-
channel, err := conn.Accept(ctx)
410+
channel, err := peerConn.Accept(ctx)
378411
if err != nil {
379412
if errors.Is(err, peer.ErrClosed) || a.isClosed() {
380413
return
@@ -383,9 +416,11 @@ func (a *agent) handlePeerConn(ctx context.Context, conn *peer.Conn) {
383416
return
384417
}
385418

419+
conn := channel.NetConn()
420+
386421
switch channel.Protocol() {
387422
case ProtocolSSH:
388-
go a.sshServer.HandleConn(channel.NetConn())
423+
go a.sshServer.HandleConn(a.stats.wrapConn(conn))
389424
case ProtocolReconnectingPTY:
390425
rawID := channel.Label()
391426
// The ID format is referenced in conn.go.
@@ -418,9 +453,9 @@ func (a *agent) handlePeerConn(ctx context.Context, conn *peer.Conn) {
418453
Height: uint16(height),
419454
Width: uint16(width),
420455
Command: idParts[3],
421-
}, channel.NetConn())
456+
}, a.stats.wrapConn(conn))
422457
case ProtocolDial:
423-
go a.handleDial(ctx, channel.Label(), channel.NetConn())
458+
go a.handleDial(ctx, channel.Label(), a.stats.wrapConn(conn))
424459
default:
425460
a.logger.Warn(ctx, "unhandled protocol from channel",
426461
slog.F("protocol", channel.Protocol()),
@@ -514,6 +549,21 @@ func (a *agent) init(ctx context.Context) {
514549
}
515550

516551
go a.run(ctx)
552+
if a.statsReporter != nil {
553+
cl, err := a.statsReporter(ctx, a.logger, func() *Stats {
554+
return a.stats.Copy()
555+
})
556+
if err != nil {
557+
a.logger.Error(ctx, "report stats", slog.Error(err))
558+
return
559+
}
560+
a.connCloseWait.Add(1)
561+
go func() {
562+
defer a.connCloseWait.Done()
563+
<-a.closed
564+
cl.Close()
565+
}()
566+
}
517567
}
518568

519569
// createCommand processes raw command input with OpenSSH-like behavior.
@@ -697,26 +747,28 @@ func (a *agent) handleReconnectingPTY(ctx context.Context, msg reconnectingPTYIn
697747
if ok {
698748
rpty, ok = rawRPTY.(*reconnectingPTY)
699749
if !ok {
700-
a.logger.Warn(ctx, "found invalid type in reconnecting pty map", slog.F("id", msg.ID))
750+
a.logger.Error(ctx, "found invalid type in reconnecting pty map", slog.F("id", msg.ID))
751+
return
701752
}
702753
} else {
703754
// Empty command will default to the users shell!
704755
cmd, err := a.createCommand(ctx, msg.Command, nil)
705756
if err != nil {
706-
a.logger.Warn(ctx, "create reconnecting pty command", slog.Error(err))
757+
a.logger.Error(ctx, "create reconnecting pty command", slog.Error(err))
707758
return
708759
}
709760
cmd.Env = append(cmd.Env, "TERM=xterm-256color")
710761

711-
ptty, process, err := pty.Start(cmd)
762+
// Default to buffer 64KiB.
763+
circularBuffer, err := circbuf.NewBuffer(64 << 10)
712764
if err != nil {
713-
a.logger.Warn(ctx, "start reconnecting pty command", slog.F("id", msg.ID))
765+
a.logger.Error(ctx, "create circular buffer", slog.Error(err))
766+
return
714767
}
715768

716-
// Default to buffer 64KiB.
717-
circularBuffer, err := circbuf.NewBuffer(64 << 10)
769+
ptty, process, err := pty.Start(cmd)
718770
if err != nil {
719-
a.logger.Warn(ctx, "create circular buffer", slog.Error(err))
771+
a.logger.Error(ctx, "start reconnecting pty command", slog.F("id", msg.ID))
720772
return
721773
}
722774

0 commit comments

Comments
 (0)