Skip to content

Commit 5faef2f

Browse files
committed
Merge branch 'main' into dean/tunnelsdk
2 parents efd41a9 + f59bf73 commit 5faef2f

File tree

225 files changed

+8668
-4376
lines changed

Some content is hidden

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

225 files changed

+8668
-4376
lines changed

.github/pull_request_template.md

Lines changed: 0 additions & 3 deletions
This file was deleted.

.github/workflows/ci.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -512,7 +512,7 @@ jobs:
512512
- name: Install node_modules
513513
run: ./scripts/yarn_install.sh
514514

515-
- run: yarn test:ci
515+
- run: yarn test:ci --max-workers ${{ steps.cpu-cores.outputs.count }}
516516
working-directory: site
517517

518518
- uses: codecov/codecov-action@v3

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,11 @@ site/test-results/*
2727
site/e2e/test-results/*
2828
site/e2e/states/*.json
2929
site/playwright-report/*
30+
site/.swc
3031

3132
# Make target for updating golden files.
3233
cli/testdata/.gen-golden
34+
helm/tests/testdata/.gen-golden
3335

3436
# Build
3537
/build/

.prettierignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,11 @@ site/test-results/*
3030
site/e2e/test-results/*
3131
site/e2e/states/*.json
3232
site/playwright-report/*
33+
site/.swc
3334

3435
# Make target for updating golden files.
3536
cli/testdata/.gen-golden
37+
helm/tests/testdata/.gen-golden
3638

3739
# Build
3840
/build/

.vscode/settings.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@
136136
"thead",
137137
"tios",
138138
"tmpdir",
139+
"tokenconfig",
139140
"tparallel",
140141
"trialer",
141142
"trimprefix",

Makefile

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -516,13 +516,17 @@ coderd/apidoc/swagger.json: $(shell find ./scripts/apidocgen $(FIND_EXCLUSIONS)
516516
./scripts/apidocgen/generate.sh
517517
yarn run --cwd=site format:write:only ../docs/api ../docs/manifest.json ../coderd/apidoc/swagger.json
518518

519-
update-golden-files: cli/testdata/.gen-golden
519+
update-golden-files: cli/testdata/.gen-golden helm/tests/testdata/.gen-golden
520520
.PHONY: update-golden-files
521521

522522
cli/testdata/.gen-golden: $(wildcard cli/testdata/*.golden) $(GO_SRC_FILES)
523523
go test ./cli -run=TestCommandHelp -update
524524
touch "$@"
525525

526+
helm/tests/testdata/.gen-golden: $(wildcard helm/tests/testdata/*.golden) $(GO_SRC_FILES)
527+
go test ./helm/tests -run=TestUpdateGoldenFiles -update
528+
touch "$@"
529+
526530
# Generate a prettierrc for the site package that uses relative paths for
527531
# overrides. This allows us to share the same prettier config between the
528532
# site and the root of the repo.

agent/agent.go

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ type Options struct {
7777
ReconnectingPTYTimeout time.Duration
7878
EnvironmentVariables map[string]string
7979
Logger slog.Logger
80+
AgentPorts map[int]string
81+
SSHMaxTimeout time.Duration
8082
}
8183

8284
type Client interface {
@@ -123,7 +125,9 @@ func New(options Options) io.Closer {
123125
tempDir: options.TempDir,
124126
lifecycleUpdate: make(chan struct{}, 1),
125127
lifecycleReported: make(chan codersdk.WorkspaceAgentLifecycle, 1),
128+
ignorePorts: options.AgentPorts,
126129
connStatsChan: make(chan *agentsdk.Stats, 1),
130+
sshMaxTimeout: options.SSHMaxTimeout,
127131
}
128132
a.init(ctx)
129133
return a
@@ -136,6 +140,10 @@ type agent struct {
136140
filesystem afero.Fs
137141
logDir string
138142
tempDir string
143+
// ignorePorts tells the api handler which ports to ignore when
144+
// listing all listening ports. This is helpful to hide ports that
145+
// are used by the agent, that the user does not care about.
146+
ignorePorts map[int]string
139147

140148
reconnectingPTYs sync.Map
141149
reconnectingPTYTimeout time.Duration
@@ -147,9 +155,10 @@ type agent struct {
147155

148156
envVars map[string]string
149157
// metadata is atomic because values can change after reconnection.
150-
metadata atomic.Value
151-
sessionToken atomic.Pointer[string]
152-
sshServer *ssh.Server
158+
metadata atomic.Value
159+
sessionToken atomic.Pointer[string]
160+
sshServer *ssh.Server
161+
sshMaxTimeout time.Duration
153162

154163
lifecycleUpdate chan struct{}
155164
lifecycleReported chan codersdk.WorkspaceAgentLifecycle
@@ -774,6 +783,7 @@ func (a *agent) init(ctx context.Context) {
774783
_ = session.Exit(1)
775784
},
776785
},
786+
MaxTimeout: a.sshMaxTimeout,
777787
}
778788

779789
go a.runLoop(ctx)

agent/api.go

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,24 +11,32 @@ import (
1111
"github.com/coder/coder/codersdk"
1212
)
1313

14-
func (*agent) apiHandler() http.Handler {
14+
func (a *agent) apiHandler() http.Handler {
1515
r := chi.NewRouter()
1616
r.Get("/", func(rw http.ResponseWriter, r *http.Request) {
1717
httpapi.Write(r.Context(), rw, http.StatusOK, codersdk.Response{
1818
Message: "Hello from the agent!",
1919
})
2020
})
2121

22-
lp := &listeningPortsHandler{}
22+
// Make a copy to ensure the map is not modified after the handler is
23+
// created.
24+
cpy := make(map[int]string)
25+
for k, b := range a.ignorePorts {
26+
cpy[k] = b
27+
}
28+
29+
lp := &listeningPortsHandler{ignorePorts: cpy}
2330
r.Get("/api/v0/listening-ports", lp.handler)
2431

2532
return r
2633
}
2734

2835
type listeningPortsHandler struct {
29-
mut sync.Mutex
30-
ports []codersdk.WorkspaceAgentListeningPort
31-
mtime time.Time
36+
mut sync.Mutex
37+
ports []codersdk.WorkspaceAgentListeningPort
38+
mtime time.Time
39+
ignorePorts map[int]string
3240
}
3341

3442
// handler returns a list of listening ports. This is tested by coderd's

agent/ports_supported.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,11 @@ func (lp *listeningPortsHandler) getListeningPorts() ([]codersdk.WorkspaceAgentL
3636
continue
3737
}
3838

39+
// Ignore ports that we've been told to ignore.
40+
if _, ok := lp.ignorePorts[int(tab.LocalAddr.Port)]; ok {
41+
continue
42+
}
43+
3944
// Don't include ports that we've already seen. This can happen on
4045
// Windows, and maybe on Linux if you're using a shared listener socket.
4146
if _, ok := seen[tab.LocalAddr.Port]; ok {

cli/agent.go

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"os/signal"
1212
"path/filepath"
1313
"runtime"
14+
"strconv"
1415
"sync"
1516
"time"
1617

@@ -30,10 +31,11 @@ import (
3031

3132
func workspaceAgent() *cobra.Command {
3233
var (
33-
auth string
34-
logDir string
35-
pprofAddress string
36-
noReap bool
34+
auth string
35+
logDir string
36+
pprofAddress string
37+
noReap bool
38+
sshMaxTimeout time.Duration
3739
)
3840
cmd := &cobra.Command{
3941
Use: "agent",
@@ -51,6 +53,7 @@ func workspaceAgent() *cobra.Command {
5153
if err != nil {
5254
return xerrors.Errorf("parse %q: %w", rawURL, err)
5355
}
56+
agentPorts := map[int]string{}
5457

5558
isLinux := runtime.GOOS == "linux"
5659

@@ -122,6 +125,10 @@ func workspaceAgent() *cobra.Command {
122125
_ = pprof.Handler
123126
pprofSrvClose := serveHandler(ctx, logger, nil, pprofAddress, "pprof")
124127
defer pprofSrvClose()
128+
// Do a best effort here. If this fails, it's not a big deal.
129+
if port, err := urlPort(pprofAddress); err == nil {
130+
agentPorts[port] = "pprof"
131+
}
125132

126133
// exchangeToken returns a session token.
127134
// This is abstracted to allow for the same looping condition
@@ -202,6 +209,8 @@ func workspaceAgent() *cobra.Command {
202209
EnvironmentVariables: map[string]string{
203210
"GIT_ASKPASS": executablePath,
204211
},
212+
AgentPorts: agentPorts,
213+
SSHMaxTimeout: sshMaxTimeout,
205214
})
206215
<-ctx.Done()
207216
return closer.Close()
@@ -212,6 +221,7 @@ func workspaceAgent() *cobra.Command {
212221
cliflag.StringVarP(cmd.Flags(), &logDir, "log-dir", "", "CODER_AGENT_LOG_DIR", os.TempDir(), "Specify the location for the agent log files")
213222
cliflag.StringVarP(cmd.Flags(), &pprofAddress, "pprof-address", "", "CODER_AGENT_PPROF_ADDRESS", "127.0.0.1:6060", "The address to serve pprof.")
214223
cliflag.BoolVarP(cmd.Flags(), &noReap, "no-reap", "", "", false, "Do not start a process reaper.")
224+
cliflag.DurationVarP(cmd.Flags(), &sshMaxTimeout, "ssh-max-timeout", "", "CODER_AGENT_SSH_MAX_TIMEOUT", time.Duration(0), "Specify the max timeout for a SSH connection")
215225
return cmd
216226
}
217227

@@ -264,3 +274,35 @@ func (c *closeWriter) Write(p []byte) (int, error) {
264274
}
265275
return c.w.Write(p)
266276
}
277+
278+
// extractPort handles different url strings.
279+
// - localhost:6060
280+
// - http://localhost:6060
281+
func extractPort(u string) (int, error) {
282+
port, firstError := urlPort(u)
283+
if firstError == nil {
284+
return port, nil
285+
}
286+
287+
// Try with a scheme
288+
port, err := urlPort("http://" + u)
289+
if err == nil {
290+
return port, nil
291+
}
292+
return -1, xerrors.Errorf("invalid url %q: %w", u, firstError)
293+
}
294+
295+
// urlPort extracts the port from a valid URL.
296+
func urlPort(u string) (int, error) {
297+
parsed, err := url.Parse(u)
298+
if err != nil {
299+
return -1, xerrors.Errorf("invalid url %q: %w", u, err)
300+
}
301+
if parsed.Port() != "" {
302+
port, err := strconv.ParseInt(parsed.Port(), 10, 64)
303+
if err == nil && port > 0 {
304+
return int(port), nil
305+
}
306+
}
307+
return -1, xerrors.Errorf("invalid port: %s", u)
308+
}

0 commit comments

Comments
 (0)