Skip to content

Commit bd4ac82

Browse files
committed
Merge branch 'main' into 8789-update-params
2 parents fc306f5 + 5993f85 commit bd4ac82

33 files changed

+829
-481
lines changed

cli/templateplan.go

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

cli/templates.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ func (r *RootCmd) templates() *clibase.Cmd {
3737
r.templateEdit(),
3838
r.templateInit(),
3939
r.templateList(),
40-
r.templatePlan(),
4140
r.templatePush(),
4241
r.templateVersions(),
4342
r.templateDelete(),

cli/testdata/coder_templates_--help.golden

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ Templates are written in standard Terraform and describe the infrastructure for
2424
edit Edit the metadata of a template by name.
2525
init Get started with a templated template.
2626
list List all the templates available for the organization
27-
plan Plan a template push from the current directory
2827
pull Download the latest version of a template to a path.
2928
push Push a new template version from the current directory or as
3029
specified by flag

coderd/httpapi/cookie.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,9 @@ func StripCoderCookies(header string) string {
2323
if name == codersdk.SessionTokenCookie ||
2424
name == codersdk.OAuth2StateCookie ||
2525
name == codersdk.OAuth2RedirectCookie ||
26-
name == codersdk.DevURLSessionTokenCookie ||
27-
name == codersdk.DevURLSignedAppTokenCookie {
26+
name == codersdk.PathAppSessionTokenCookie ||
27+
name == codersdk.SubdomainAppSessionTokenCookie ||
28+
name == codersdk.SignedAppTokenCookie {
2829
continue
2930
}
3031
cookies = append(cookies, part)

coderd/httpmw/apikey.go

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -447,10 +447,10 @@ func ExtractAPIKey(rw http.ResponseWriter, r *http.Request, cfg ExtractAPIKeyCon
447447
// APITokenFromRequest returns the api token from the request.
448448
// Find the session token from:
449449
// 1: The cookie
450-
// 1: The devurl cookie
451-
// 3: The old cookie
452-
// 4. The coder_session_token query parameter
453-
// 5. The custom auth header
450+
// 2. The coder_session_token query parameter
451+
// 3. The custom auth header
452+
//
453+
// API tokens for apps are read from workspaceapps/cookies.go.
454454
func APITokenFromRequest(r *http.Request) string {
455455
cookie, err := r.Cookie(codersdk.SessionTokenCookie)
456456
if err == nil && cookie.Value != "" {
@@ -467,11 +467,6 @@ func APITokenFromRequest(r *http.Request) string {
467467
return headerValue
468468
}
469469

470-
cookie, err = r.Cookie(codersdk.DevURLSessionTokenCookie)
471-
if err == nil && cookie.Value != "" {
472-
return cookie.Value
473-
}
474-
475470
return ""
476471
}
477472

coderd/workspaceagents.go

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"github.com/go-chi/chi/v5"
2424
"github.com/google/uuid"
2525
"golang.org/x/exp/maps"
26+
"golang.org/x/exp/slices"
2627
"golang.org/x/mod/semver"
2728
"golang.org/x/sync/errgroup"
2829
"golang.org/x/xerrors"
@@ -481,6 +482,15 @@ func (api *API) workspaceAgentLogs(rw http.ResponseWriter, r *http.Request) {
481482
return
482483
}
483484

485+
workspace, err := api.Database.GetWorkspaceByAgentID(ctx, workspaceAgent.ID)
486+
if err != nil {
487+
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
488+
Message: "Internal error fetching workspace by agent id.",
489+
Detail: err.Error(),
490+
})
491+
return
492+
}
493+
484494
api.WebsocketWaitMutex.Lock()
485495
api.WebsocketWaitGroup.Add(1)
486496
api.WebsocketWaitMutex.Unlock()
@@ -556,7 +566,8 @@ func (api *API) workspaceAgentLogs(rw http.ResponseWriter, r *http.Request) {
556566
go func() {
557567
defer close(bufferedLogs)
558568

559-
for {
569+
keepGoing := true
570+
for keepGoing {
560571
select {
561572
case <-ctx.Done():
562573
return
@@ -565,6 +576,18 @@ func (api *API) workspaceAgentLogs(rw http.ResponseWriter, r *http.Request) {
565576
t.Reset(recheckInterval)
566577
}
567578

579+
agents, err := api.Database.GetWorkspaceAgentsInLatestBuildByWorkspaceID(ctx, workspace.ID)
580+
if err != nil {
581+
if xerrors.Is(err, context.Canceled) {
582+
return
583+
}
584+
logger.Warn(ctx, "failed to get workspace agents in latest build", slog.Error(err))
585+
continue
586+
}
587+
// If the agent is no longer in the latest build, we can stop after
588+
// checking once.
589+
keepGoing = slices.ContainsFunc(agents, func(agent database.WorkspaceAgent) bool { return agent.ID == workspaceAgent.ID })
590+
568591
logs, err := api.Database.GetWorkspaceAgentLogsAfter(ctx, database.GetWorkspaceAgentLogsAfterParams{
569592
AgentID: workspaceAgent.ID,
570593
CreatedAfter: lastSentLogID,
@@ -878,13 +901,15 @@ func (api *API) derpMapUpdates(rw http.ResponseWriter, r *http.Request) {
878901
})
879902
return
880903
}
881-
nconn := websocket.NetConn(ctx, ws, websocket.MessageBinary)
904+
ctx, nconn := websocketNetConn(ctx, ws, websocket.MessageBinary)
882905
defer nconn.Close()
883906

884907
// Slurp all packets from the connection into io.Discard so pongs get sent
885-
// by the websocket package.
908+
// by the websocket package. We don't do any reads ourselves so this is
909+
// necessary.
886910
go func() {
887911
_, _ = io.Copy(io.Discard, nconn)
912+
_ = nconn.Close()
888913
}()
889914

890915
go func(ctx context.Context) {
@@ -899,13 +924,11 @@ func (api *API) derpMapUpdates(rw http.ResponseWriter, r *http.Request) {
899924
return
900925
}
901926

902-
// We don't need a context that times out here because the ping will
903-
// eventually go through. If the context times out, then other
904-
// websocket read operations will receive an error, obfuscating the
905-
// actual problem.
927+
ctx, cancel := context.WithTimeout(ctx, 30*time.Second)
906928
err := ws.Ping(ctx)
929+
cancel()
907930
if err != nil {
908-
_ = ws.Close(websocket.StatusInternalError, err.Error())
931+
_ = nconn.Close()
909932
return
910933
}
911934
}
@@ -920,7 +943,7 @@ func (api *API) derpMapUpdates(rw http.ResponseWriter, r *http.Request) {
920943
if lastDERPMap == nil || !tailnet.CompareDERPMaps(lastDERPMap, derpMap) {
921944
err := json.NewEncoder(nconn).Encode(derpMap)
922945
if err != nil {
923-
_ = ws.Close(websocket.StatusInternalError, err.Error())
946+
_ = nconn.Close()
924947
return
925948
}
926949
lastDERPMap = derpMap

coderd/workspaceagents_test.go

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,91 @@ func TestWorkspaceAgentStartupLogs(t *testing.T) {
242242
require.Equal(t, "testing", logChunk[0].Output)
243243
require.Equal(t, "testing2", logChunk[1].Output)
244244
})
245+
t.Run("Close logs on outdated build", func(t *testing.T) {
246+
t.Parallel()
247+
ctx := testutil.Context(t, testutil.WaitMedium)
248+
client := coderdtest.New(t, &coderdtest.Options{
249+
IncludeProvisionerDaemon: true,
250+
})
251+
user := coderdtest.CreateFirstUser(t, client)
252+
authToken := uuid.NewString()
253+
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{
254+
Parse: echo.ParseComplete,
255+
ProvisionPlan: echo.PlanComplete,
256+
ProvisionApply: []*proto.Response{{
257+
Type: &proto.Response_Apply{
258+
Apply: &proto.ApplyComplete{
259+
Resources: []*proto.Resource{{
260+
Name: "example",
261+
Type: "aws_instance",
262+
Agents: []*proto.Agent{{
263+
Id: uuid.NewString(),
264+
Auth: &proto.Agent_Token{
265+
Token: authToken,
266+
},
267+
}},
268+
}},
269+
},
270+
},
271+
}},
272+
})
273+
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
274+
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
275+
workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID)
276+
build := coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
277+
278+
agentClient := agentsdk.New(client.URL)
279+
agentClient.SetSessionToken(authToken)
280+
err := agentClient.PatchLogs(ctx, agentsdk.PatchLogs{
281+
Logs: []agentsdk.Log{
282+
{
283+
CreatedAt: database.Now(),
284+
Output: "testing",
285+
},
286+
},
287+
})
288+
require.NoError(t, err)
289+
290+
logs, closer, err := client.WorkspaceAgentLogsAfter(ctx, build.Resources[0].Agents[0].ID, 0, true)
291+
require.NoError(t, err)
292+
defer func() {
293+
_ = closer.Close()
294+
}()
295+
296+
first := make(chan struct{})
297+
go func() {
298+
select {
299+
case <-ctx.Done():
300+
assert.Fail(t, "context done while waiting in goroutine")
301+
case <-logs:
302+
close(first)
303+
}
304+
}()
305+
select {
306+
case <-ctx.Done():
307+
require.FailNow(t, "context done while waiting for first log")
308+
case <-first:
309+
}
310+
311+
_ = coderdtest.CreateWorkspaceBuild(t, client, workspace, database.WorkspaceTransitionStart)
312+
313+
// Send a new log message to trigger a re-check.
314+
err = agentClient.PatchLogs(ctx, agentsdk.PatchLogs{
315+
Logs: []agentsdk.Log{
316+
{
317+
CreatedAt: database.Now(),
318+
Output: "testing2",
319+
},
320+
},
321+
})
322+
require.NoError(t, err)
323+
324+
select {
325+
case <-ctx.Done():
326+
require.FailNow(t, "context done while waiting for logs close")
327+
case <-logs:
328+
}
329+
})
245330
t.Run("PublishesOnOverflow", func(t *testing.T) {
246331
t.Parallel()
247332
ctx := testutil.Context(t, testutil.WaitMedium)

coderd/workspaceapps/apptest/apptest.go

Lines changed: 16 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ func Run(t *testing.T, appHostIsPrimary bool, factory DeploymentFactory) {
257257

258258
var appTokenCookie *http.Cookie
259259
for _, c := range resp.Cookies() {
260-
if c.Name == codersdk.DevURLSignedAppTokenCookie {
260+
if c.Name == codersdk.SignedAppTokenCookie {
261261
appTokenCookie = c
262262
break
263263
}
@@ -302,7 +302,7 @@ func Run(t *testing.T, appHostIsPrimary bool, factory DeploymentFactory) {
302302

303303
var appTokenCookie *http.Cookie
304304
for _, c := range resp.Cookies() {
305-
if c.Name == codersdk.DevURLSignedAppTokenCookie {
305+
if c.Name == codersdk.SignedAppTokenCookie {
306306
appTokenCookie = c
307307
break
308308
}
@@ -400,30 +400,19 @@ func Run(t *testing.T, appHostIsPrimary bool, factory DeploymentFactory) {
400400
appDetails := setupProxyTest(t, nil)
401401

402402
cases := []struct {
403-
name string
404-
appURL *url.URL
405-
verifyCookie func(t *testing.T, c *http.Cookie)
403+
name string
404+
appURL *url.URL
405+
sessionTokenCookieName string
406406
}{
407407
{
408-
name: "Subdomain",
409-
appURL: appDetails.SubdomainAppURL(appDetails.Apps.Owner),
410-
verifyCookie: func(t *testing.T, c *http.Cookie) {
411-
// TODO(@dean): fix these asserts, they don't seem to
412-
// work. I wonder if Go strips the domain from the
413-
// cookie object if it's invalid or something.
414-
// domain := strings.SplitN(appDetails.Options.AppHost, ".", 2)
415-
// require.Equal(t, "."+domain[1], c.Domain, "incorrect domain on app token cookie")
416-
},
408+
name: "Subdomain",
409+
appURL: appDetails.SubdomainAppURL(appDetails.Apps.Owner),
410+
sessionTokenCookieName: codersdk.SubdomainAppSessionTokenCookie,
417411
},
418412
{
419-
name: "Path",
420-
appURL: appDetails.PathAppURL(appDetails.Apps.Owner),
421-
verifyCookie: func(t *testing.T, c *http.Cookie) {
422-
// TODO(@dean): fix these asserts, they don't seem to
423-
// work. I wonder if Go strips the domain from the
424-
// cookie object if it's invalid or something.
425-
// require.Equal(t, "", c.Domain, "incorrect domain on app token cookie")
426-
},
413+
name: "Path",
414+
appURL: appDetails.PathAppURL(appDetails.Apps.Owner),
415+
sessionTokenCookieName: codersdk.PathAppSessionTokenCookie,
427416
},
428417
}
429418

@@ -508,14 +497,13 @@ func Run(t *testing.T, appHostIsPrimary bool, factory DeploymentFactory) {
508497

509498
cookies := resp.Cookies()
510499
var cookie *http.Cookie
511-
for _, c := range cookies {
512-
if c.Name == codersdk.DevURLSessionTokenCookie {
513-
cookie = c
500+
for _, co := range cookies {
501+
if co.Name == c.sessionTokenCookieName {
502+
cookie = co
514503
break
515504
}
516505
}
517506
require.NotNil(t, cookie, "no app session token cookie was set")
518-
c.verifyCookie(t, cookie)
519507
apiKey := cookie.Value
520508

521509
// Fetch the API key from the API.
@@ -715,7 +703,7 @@ func Run(t *testing.T, appHostIsPrimary bool, factory DeploymentFactory) {
715703

716704
var appTokenCookie *http.Cookie
717705
for _, c := range resp.Cookies() {
718-
if c.Name == codersdk.DevURLSignedAppTokenCookie {
706+
if c.Name == codersdk.SignedAppTokenCookie {
719707
appTokenCookie = c
720708
break
721709
}
@@ -759,7 +747,7 @@ func Run(t *testing.T, appHostIsPrimary bool, factory DeploymentFactory) {
759747

760748
var appTokenCookie *http.Cookie
761749
for _, c := range resp.Cookies() {
762-
if c.Name == codersdk.DevURLSignedAppTokenCookie {
750+
if c.Name == codersdk.SignedAppTokenCookie {
763751
appTokenCookie = c
764752
break
765753
}

0 commit comments

Comments
 (0)