Skip to content

Commit e94d9a3

Browse files
committed
Merge branch 'main' into colin/chore_codersdk_move_all_wireguard_functions_to_workspacesdk_
2 parents 1cd79f6 + 0bea890 commit e94d9a3

File tree

23 files changed

+185
-205
lines changed

23 files changed

+185
-205
lines changed

.github/workflows/contrib.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ jobs:
3434
steps:
3535
- name: cla
3636
if: (github.event.comment.body == 'recheck' || github.event.comment.body == 'I have read the CLA Document and I hereby sign the CLA') || github.event_name == 'pull_request_target'
37-
uses: contributor-assistant/github-action@v2.3.1
37+
uses: contributor-assistant/github-action@v2.3.2
3838
env:
3939
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
4040
# the below token should have repo scope and must be manually added by you in the repository's secret

cli/ssh_test.go

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,14 +117,26 @@ func TestSSH(t *testing.T) {
117117
clitest.SetupConfig(t, client, root)
118118
pty := ptytest.New(t).Attach(inv)
119119

120-
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
120+
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitSuperLong)
121121
defer cancel()
122122

123123
cmdDone := tGo(t, func() {
124124
err := inv.WithContext(ctx).Run()
125125
assert.NoError(t, err)
126126
})
127127

128+
// Delay until workspace is starting, otherwise the agent may be
129+
// booted due to outdated build.
130+
var err error
131+
for {
132+
workspace, err = client.Workspace(ctx, workspace.ID)
133+
require.NoError(t, err)
134+
if workspace.LatestBuild.Transition == codersdk.WorkspaceTransitionStart {
135+
break
136+
}
137+
time.Sleep(testutil.IntervalFast)
138+
}
139+
128140
// When the agent connects, the workspace was started, and we should
129141
// have access to the shell.
130142
_ = agenttest.New(t, client.URL, authToken)
@@ -365,7 +377,7 @@ func TestSSH(t *testing.T) {
365377
workspaceBuild := coderdtest.CreateWorkspaceBuild(t, client, workspace, database.WorkspaceTransitionStop)
366378
coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, workspaceBuild.ID)
367379

368-
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
380+
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitSuperLong)
369381
defer cancel()
370382

371383
clientStdinR, clientStdinW := io.Pipe()
@@ -461,6 +473,18 @@ func TestSSH(t *testing.T) {
461473
assert.NoError(t, err)
462474
})
463475

476+
// Delay until workspace is starting, otherwise the agent may be
477+
// booted due to outdated build.
478+
var err error
479+
for {
480+
workspace, err = client.Workspace(ctx, workspace.ID)
481+
require.NoError(t, err)
482+
if workspace.LatestBuild.Transition == codersdk.WorkspaceTransitionStart {
483+
break
484+
}
485+
time.Sleep(testutil.IntervalFast)
486+
}
487+
464488
// When the agent connects, the workspace was started, and we should
465489
// have access to the shell.
466490
_ = agenttest.New(t, client.URL, authToken)

coderd/coderd.go

Lines changed: 73 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -689,6 +689,34 @@ func New(options *Options) *API {
689689
})
690690
}
691691

692+
// OAuth2 linking routes do not make sense under the /api/v2 path. These are
693+
// for an external application to use Coder as an OAuth2 provider, not for
694+
// logging into Coder with an external OAuth2 provider.
695+
r.Route("/oauth2", func(r chi.Router) {
696+
r.Use(
697+
api.oAuth2ProviderMiddleware,
698+
// Fetch the app as system because in the /tokens route there will be no
699+
// authenticated user.
700+
httpmw.AsAuthzSystem(httpmw.ExtractOAuth2ProviderApp(options.Database)),
701+
)
702+
r.Route("/authorize", func(r chi.Router) {
703+
r.Use(apiKeyMiddlewareRedirect)
704+
r.Get("/", api.getOAuth2ProviderAppAuthorize())
705+
})
706+
r.Route("/tokens", func(r chi.Router) {
707+
r.Group(func(r chi.Router) {
708+
r.Use(apiKeyMiddleware)
709+
// DELETE on /tokens is not part of the OAuth2 spec. It is our own
710+
// route used to revoke permissions from an application. It is here for
711+
// parity with POST on /tokens.
712+
r.Delete("/", api.deleteOAuth2ProviderAppTokens())
713+
})
714+
// The POST /tokens endpoint will be called from an unauthorized client so
715+
// we cannot require an API key.
716+
r.Post("/", api.postOAuth2ProviderAppToken())
717+
})
718+
})
719+
692720
r.Route("/api/v2", func(r chi.Router) {
693721
api.APIHandler = r
694722

@@ -1098,6 +1126,34 @@ func New(options *Options) *API {
10981126
}
10991127
r.Method("GET", "/expvar", expvar.Handler()) // contains DERP metrics as well as cmdline and memstats
11001128
})
1129+
// Manage OAuth2 applications that can use Coder as an OAuth2 provider.
1130+
r.Route("/oauth2-provider", func(r chi.Router) {
1131+
r.Use(
1132+
apiKeyMiddleware,
1133+
api.oAuth2ProviderMiddleware,
1134+
)
1135+
r.Route("/apps", func(r chi.Router) {
1136+
r.Get("/", api.oAuth2ProviderApps)
1137+
r.Post("/", api.postOAuth2ProviderApp)
1138+
1139+
r.Route("/{app}", func(r chi.Router) {
1140+
r.Use(httpmw.ExtractOAuth2ProviderApp(options.Database))
1141+
r.Get("/", api.oAuth2ProviderApp)
1142+
r.Put("/", api.putOAuth2ProviderApp)
1143+
r.Delete("/", api.deleteOAuth2ProviderApp)
1144+
1145+
r.Route("/secrets", func(r chi.Router) {
1146+
r.Get("/", api.oAuth2ProviderAppSecrets)
1147+
r.Post("/", api.postOAuth2ProviderAppSecret)
1148+
1149+
r.Route("/{secretID}", func(r chi.Router) {
1150+
r.Use(httpmw.ExtractOAuth2ProviderAppSecret(options.Database))
1151+
r.Delete("/", api.deleteOAuth2ProviderAppSecret)
1152+
})
1153+
})
1154+
})
1155+
})
1156+
})
11011157
})
11021158

11031159
if options.SwaggerEndpoint {
@@ -1229,9 +1285,23 @@ func (api *API) Close() error {
12291285
api.derpCloseFunc()
12301286
}
12311287

1232-
api.WebsocketWaitMutex.Lock()
1233-
api.WebsocketWaitGroup.Wait()
1234-
api.WebsocketWaitMutex.Unlock()
1288+
wsDone := make(chan struct{})
1289+
timer := time.NewTimer(10 * time.Second)
1290+
defer timer.Stop()
1291+
go func() {
1292+
api.WebsocketWaitMutex.Lock()
1293+
defer api.WebsocketWaitMutex.Unlock()
1294+
api.WebsocketWaitGroup.Wait()
1295+
close(wsDone)
1296+
}()
1297+
// This will technically leak the above func if the timer fires, but this is
1298+
// maintly a last ditch effort to un-stuck coderd on shutdown. This
1299+
// shouldn't affect tests at all.
1300+
select {
1301+
case <-wsDone:
1302+
case <-timer.C:
1303+
api.Logger.Warn(api.ctx, "websocket shutdown timed out after 10 seconds")
1304+
}
12351305

12361306
api.dbRolluper.Close()
12371307
api.metricsCache.Close()

coderd/database/queries.sql.go

Lines changed: 3 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/database/queries/insights.sql

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -599,7 +599,9 @@ WITH
599599
JOIN
600600
workspace_agent_stats AS was
601601
ON
602-
date_trunc('minute', was.created_at) = mb.minute_bucket
602+
was.created_at >= (SELECT t FROM latest_start)
603+
AND was.created_at < NOW()
604+
AND date_trunc('minute', was.created_at) = mb.minute_bucket
603605
AND was.template_id = mb.template_id
604606
AND was.user_id = mb.user_id
605607
AND was.connection_median_latency_ms >= 0

0 commit comments

Comments
 (0)