Skip to content

Commit b101ae7

Browse files
authored
merge main into groups (#4439)
1 parent 9e199d3 commit b101ae7

File tree

209 files changed

+3723
-2150
lines changed

Some content is hidden

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

209 files changed

+3723
-2150
lines changed

.github/workflows/coder.yaml

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ on:
44
push:
55
branches:
66
- main
7-
tags:
8-
- "*"
97

108
pull_request:
119

@@ -36,7 +34,7 @@ jobs:
3634
- name: Checkout
3735
uses: actions/checkout@v2
3836
- name: typos-action
39-
uses: crate-ci/typos@master
37+
uses: crate-ci/typos@v1.12.8
4038
with:
4139
config: .github/workflows/typos.toml
4240
- name: Fix Helper
@@ -630,7 +628,7 @@ jobs:
630628
with:
631629
name: failed-test-videos
632630
path: ./site/test-results/**/*.webm
633-
retention:days: 7
631+
retention-days: 7
634632

635633
chromatic:
636634
# REMARK: this is only used to build storybook and deploy it to Chromatic.

.github/workflows/dogfood.yaml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ on:
44
push:
55
branches:
66
- main
7-
tags:
8-
- "*"
97
paths:
108
- "dogfood/**"
119
pull_request:

.vscode/settings.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
"cliflag",
1010
"cliui",
1111
"codecov",
12-
"Codespaces",
1312
"coderd",
13+
"coderdenttest",
1414
"coderdtest",
1515
"codersdk",
1616
"cronstrue",
@@ -24,6 +24,7 @@
2424
"drpcmux",
2525
"drpcserver",
2626
"Dsts",
27+
"enablements",
2728
"fatih",
2829
"Formik",
2930
"gitsshkey",

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ Once installed, you can start a production deployment<sup>1</sup> with a single
5858

5959
```sh
6060
# Automatically sets up an external access URL on *.try.coder.app
61-
coder server --tunnel
61+
coder server
6262

6363
# Requires a PostgreSQL instance and external access URL
6464
coder server --postgres-url <url> --access-url <url>

agent/agent.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"fmt"
1111
"io"
1212
"net"
13+
"net/http"
1314
"net/netip"
1415
"os"
1516
"os/exec"
@@ -206,6 +207,7 @@ func (a *agent) runTailnet(ctx context.Context, derpMap *tailcfg.DERPMap) {
206207
go a.sshServer.HandleConn(a.stats.wrapConn(conn))
207208
}
208209
}()
210+
209211
reconnectingPTYListener, err := a.network.Listen("tcp", ":"+strconv.Itoa(codersdk.TailnetReconnectingPTYPort))
210212
if err != nil {
211213
a.logger.Critical(ctx, "listen for reconnecting pty", slog.Error(err))
@@ -240,6 +242,7 @@ func (a *agent) runTailnet(ctx context.Context, derpMap *tailcfg.DERPMap) {
240242
go a.handleReconnectingPTY(ctx, msg, conn)
241243
}
242244
}()
245+
243246
speedtestListener, err := a.network.Listen("tcp", ":"+strconv.Itoa(codersdk.TailnetSpeedtestPort))
244247
if err != nil {
245248
a.logger.Critical(ctx, "listen for speedtest", slog.Error(err))
@@ -261,6 +264,31 @@ func (a *agent) runTailnet(ctx context.Context, derpMap *tailcfg.DERPMap) {
261264
}()
262265
}
263266
}()
267+
268+
statisticsListener, err := a.network.Listen("tcp", ":"+strconv.Itoa(codersdk.TailnetStatisticsPort))
269+
if err != nil {
270+
a.logger.Critical(ctx, "listen for statistics", slog.Error(err))
271+
return
272+
}
273+
go func() {
274+
defer statisticsListener.Close()
275+
server := &http.Server{
276+
Handler: a.statisticsHandler(),
277+
ReadTimeout: 20 * time.Second,
278+
ReadHeaderTimeout: 20 * time.Second,
279+
WriteTimeout: 20 * time.Second,
280+
ErrorLog: slog.Stdlib(ctx, a.logger.Named("statistics_http_server"), slog.LevelInfo),
281+
}
282+
go func() {
283+
<-ctx.Done()
284+
_ = server.Close()
285+
}()
286+
287+
err = server.Serve(statisticsListener)
288+
if err != nil && !xerrors.Is(err, http.ErrServerClosed) && !strings.Contains(err.Error(), "use of closed network connection") {
289+
a.logger.Critical(ctx, "serve statistics HTTP server", slog.Error(err))
290+
}
291+
}()
264292
}
265293

266294
// runCoordinator listens for nodes and updates the self-node as it changes.

agent/ports_supported.go

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
//go:build linux || (windows && amd64)
2+
3+
package agent
4+
5+
import (
6+
"time"
7+
8+
"github.com/cakturk/go-netstat/netstat"
9+
"golang.org/x/xerrors"
10+
11+
"github.com/coder/coder/codersdk"
12+
)
13+
14+
func (lp *listeningPortsHandler) getListeningPorts() ([]codersdk.ListeningPort, error) {
15+
lp.mut.Lock()
16+
defer lp.mut.Unlock()
17+
18+
if time.Since(lp.mtime) < time.Second {
19+
// copy
20+
ports := make([]codersdk.ListeningPort, len(lp.ports))
21+
copy(ports, lp.ports)
22+
return ports, nil
23+
}
24+
25+
tabs, err := netstat.TCPSocks(func(s *netstat.SockTabEntry) bool {
26+
return s.State == netstat.Listen
27+
})
28+
if err != nil {
29+
return nil, xerrors.Errorf("scan listening ports: %w", err)
30+
}
31+
32+
seen := make(map[uint16]struct{}, len(tabs))
33+
ports := []codersdk.ListeningPort{}
34+
for _, tab := range tabs {
35+
if tab.LocalAddr == nil || tab.LocalAddr.Port < uint16(codersdk.MinimumListeningPort) {
36+
continue
37+
}
38+
39+
// Don't include ports that we've already seen. This can happen on
40+
// Windows, and maybe on Linux if you're using a shared listener socket.
41+
if _, ok := seen[tab.LocalAddr.Port]; ok {
42+
continue
43+
}
44+
seen[tab.LocalAddr.Port] = struct{}{}
45+
46+
procName := ""
47+
if tab.Process != nil {
48+
procName = tab.Process.Name
49+
}
50+
ports = append(ports, codersdk.ListeningPort{
51+
ProcessName: procName,
52+
Network: codersdk.ListeningPortNetworkTCP,
53+
Port: tab.LocalAddr.Port,
54+
})
55+
}
56+
57+
lp.ports = ports
58+
lp.mtime = time.Now()
59+
60+
// copy
61+
ports = make([]codersdk.ListeningPort, len(lp.ports))
62+
copy(ports, lp.ports)
63+
return ports, nil
64+
}

agent/ports_unsupported.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
//go:build !linux && !(windows && amd64)
2+
3+
package agent
4+
5+
import "github.com/coder/coder/codersdk"
6+
7+
func (lp *listeningPortsHandler) getListeningPorts() ([]codersdk.ListeningPort, error) {
8+
// Can't scan for ports on non-linux or non-windows_amd64 systems at the
9+
// moment. The UI will not show any "no ports found" message to the user, so
10+
// the user won't suspect a thing.
11+
return []codersdk.ListeningPort{}, nil
12+
}

agent/statsendpoint.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package agent
2+
3+
import (
4+
"net/http"
5+
"sync"
6+
"time"
7+
8+
"github.com/go-chi/chi"
9+
10+
"github.com/coder/coder/coderd/httpapi"
11+
"github.com/coder/coder/codersdk"
12+
)
13+
14+
func (*agent) statisticsHandler() http.Handler {
15+
r := chi.NewRouter()
16+
r.Get("/", func(rw http.ResponseWriter, r *http.Request) {
17+
httpapi.Write(r.Context(), rw, http.StatusOK, codersdk.Response{
18+
Message: "Hello from the agent!",
19+
})
20+
})
21+
22+
lp := &listeningPortsHandler{}
23+
r.Get("/api/v0/listening-ports", lp.handler)
24+
25+
return r
26+
}
27+
28+
type listeningPortsHandler struct {
29+
mut sync.Mutex
30+
ports []codersdk.ListeningPort
31+
mtime time.Time
32+
}
33+
34+
// handler returns a list of listening ports. This is tested by coderd's
35+
// TestWorkspaceAgentListeningPorts test.
36+
func (lp *listeningPortsHandler) handler(rw http.ResponseWriter, r *http.Request) {
37+
ports, err := lp.getListeningPorts()
38+
if err != nil {
39+
httpapi.Write(r.Context(), rw, http.StatusInternalServerError, codersdk.Response{
40+
Message: "Could not scan for listening ports.",
41+
Detail: err.Error(),
42+
})
43+
return
44+
}
45+
46+
httpapi.Write(r.Context(), rw, http.StatusOK, codersdk.ListeningPortsResponse{
47+
Ports: ports,
48+
})
49+
}

cli/agent.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -168,15 +168,15 @@ func workspaceAgent() *cobra.Command {
168168
}
169169
}
170170

171-
ctx, cancelFunc := context.WithTimeout(cmd.Context(), time.Hour)
172-
defer cancelFunc()
173-
for retry.New(100*time.Millisecond, 5*time.Second).Wait(ctx) {
174-
err := client.PostWorkspaceAgentVersion(cmd.Context(), version)
171+
retryCtx, cancelRetry := context.WithTimeout(cmd.Context(), time.Hour)
172+
defer cancelRetry()
173+
for retrier := retry.New(100*time.Millisecond, 5*time.Second); retrier.Wait(retryCtx); {
174+
err := client.PostWorkspaceAgentVersion(retryCtx, version)
175175
if err != nil {
176-
logger.Warn(cmd.Context(), "post agent version: %w", slog.Error(err), slog.F("version", version))
176+
logger.Warn(retryCtx, "post agent version: %w", slog.Error(err), slog.F("version", version))
177177
continue
178178
}
179-
logger.Info(ctx, "updated agent version", slog.F("version", version))
179+
logger.Info(retryCtx, "updated agent version", slog.F("version", version))
180180
break
181181
}
182182

cli/cliui/table.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,10 +153,14 @@ func DisplayTable(out any, sort string, filterColumns []string) (string, error)
153153
// Special type formatting.
154154
switch val := v.(type) {
155155
case time.Time:
156-
v = val.Format(time.Stamp)
156+
v = val.Format(time.RFC3339)
157157
case *time.Time:
158158
if val != nil {
159-
v = val.Format(time.Stamp)
159+
v = val.Format(time.RFC3339)
160+
}
161+
case *int64:
162+
if val != nil {
163+
v = *val
160164
}
161165
case fmt.Stringer:
162166
if val != nil {

cli/cliui/table_test.go

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -131,10 +131,10 @@ func Test_DisplayTable(t *testing.T) {
131131
t.Parallel()
132132

133133
expected := `
134-
NAME AGE ROLES SUB 1 NAME SUB 1 AGE SUB 2 NAME SUB 2 AGE SUB 3 INNER NAME SUB 3 INNER AGE SUB 4 TIME TIME PTR
135-
foo 10 [a b c] foo1 11 foo2 12 foo3 13 {foo4 14 } Aug 2 15:49:10 Aug 2 15:49:10
136-
bar 20 [a] bar1 21 <nil> <nil> bar3 23 {bar4 24 } Aug 2 15:49:10 <nil>
137-
baz 30 [] baz1 31 <nil> <nil> baz3 33 {baz4 34 } Aug 2 15:49:10 <nil>
134+
NAME AGE ROLES SUB 1 NAME SUB 1 AGE SUB 2 NAME SUB 2 AGE SUB 3 INNER NAME SUB 3 INNER AGE SUB 4 TIME TIME PTR
135+
foo 10 [a b c] foo1 11 foo2 12 foo3 13 {foo4 14 } 2022-08-02T15:49:10Z 2022-08-02T15:49:10Z
136+
bar 20 [a] bar1 21 <nil> <nil> bar3 23 {bar4 24 } 2022-08-02T15:49:10Z <nil>
137+
baz 30 [] baz1 31 <nil> <nil> baz3 33 {baz4 34 } 2022-08-02T15:49:10Z <nil>
138138
`
139139

140140
// Test with non-pointer values.
@@ -158,10 +158,10 @@ baz 30 [] baz1 31 <nil> <nil> baz3
158158
t.Parallel()
159159

160160
expected := `
161-
NAME AGE ROLES SUB 1 NAME SUB 1 AGE SUB 2 NAME SUB 2 AGE SUB 3 INNER NAME SUB 3 INNER AGE SUB 4 TIME TIME PTR
162-
bar 20 [a] bar1 21 <nil> <nil> bar3 23 {bar4 24 } Aug 2 15:49:10 <nil>
163-
baz 30 [] baz1 31 <nil> <nil> baz3 33 {baz4 34 } Aug 2 15:49:10 <nil>
164-
foo 10 [a b c] foo1 11 foo2 12 foo3 13 {foo4 14 } Aug 2 15:49:10 Aug 2 15:49:10
161+
NAME AGE ROLES SUB 1 NAME SUB 1 AGE SUB 2 NAME SUB 2 AGE SUB 3 INNER NAME SUB 3 INNER AGE SUB 4 TIME TIME PTR
162+
bar 20 [a] bar1 21 <nil> <nil> bar3 23 {bar4 24 } 2022-08-02T15:49:10Z <nil>
163+
baz 30 [] baz1 31 <nil> <nil> baz3 33 {baz4 34 } 2022-08-02T15:49:10Z <nil>
164+
foo 10 [a b c] foo1 11 foo2 12 foo3 13 {foo4 14 } 2022-08-02T15:49:10Z 2022-08-02T15:49:10Z
165165
`
166166

167167
out, err := cliui.DisplayTable(in, "name", nil)
@@ -175,9 +175,9 @@ foo 10 [a b c] foo1 11 foo2 12 foo3
175175

176176
expected := `
177177
NAME SUB 1 NAME SUB 3 INNER NAME TIME
178-
foo foo1 foo3 Aug 2 15:49:10
179-
bar bar1 bar3 Aug 2 15:49:10
180-
baz baz1 baz3 Aug 2 15:49:10
178+
foo foo1 foo3 2022-08-02T15:49:10Z
179+
bar bar1 bar3 2022-08-02T15:49:10Z
180+
baz baz1 baz3 2022-08-02T15:49:10Z
181181
`
182182

183183
out, err := cliui.DisplayTable(in, "", []string{"name", "sub_1_name", "sub_3 inner name", "time"})

cli/parameters.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ func parameters() *cobra.Command {
2020
// constructing curl requests.
2121
Hidden: true,
2222
Aliases: []string{"params"},
23+
RunE: func(cmd *cobra.Command, args []string) error {
24+
return cmd.Help()
25+
},
2326
}
2427
cmd.AddCommand(
2528
parameterList(),

cli/resetpassword_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ func TestResetPassword(t *testing.T) {
4141
serverCmd, cfg := clitest.New(t,
4242
"server",
4343
"--address", ":0",
44+
"--access-url", "example.com",
4445
"--postgres-url", connectionURL,
4546
"--cache-dir", t.TempDir(),
4647
)

cli/root.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ func Core() []*cobra.Command {
9393
users(),
9494
versionCmd(),
9595
workspaceAgent(),
96+
tokens(),
9697
}
9798
}
9899

cli/schedule.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ func schedules() *cobra.Command {
5858
Annotations: workspaceCommand,
5959
Use: "schedule { show | start | stop | override } <workspace>",
6060
Short: "Schedule automated start and stop times for workspaces",
61+
RunE: func(cmd *cobra.Command, args []string) error {
62+
return cmd.Help()
63+
},
6164
}
6265

6366
scheduleCmd.AddCommand(

0 commit comments

Comments
 (0)