Skip to content

Commit be08e2b

Browse files
committed
fix: Multiple builds using the incorrect agent token
This was an issue with our in-memory database that caused newer builds to return an outdated agent, which would then be rejected. A test case has been added to ensure this can't happen again!
1 parent 52271ff commit be08e2b

File tree

2 files changed

+60
-2
lines changed

2 files changed

+60
-2
lines changed

coderd/database/databasefake/databasefake.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -626,7 +626,9 @@ func (q *fakeQuerier) GetWorkspaceAgentByAuthToken(_ context.Context, authToken
626626
q.mutex.RLock()
627627
defer q.mutex.RUnlock()
628628

629-
for _, agent := range q.provisionerJobAgent {
629+
// The schema sorts this by created at, so we iterate the array backwards.
630+
for i := len(q.provisionerJobAgent) - 1; i >= 0; i-- {
631+
agent := q.provisionerJobAgent[i]
630632
if agent.AuthToken.String() == authToken.String() {
631633
return agent, nil
632634
}
@@ -990,7 +992,7 @@ func (q *fakeQuerier) InsertProvisionerJob(_ context.Context, arg database.Inser
990992
return job, nil
991993
}
992994

993-
func (q *fakeQuerier) InsertWorkspaceAgent(_ context.Context, arg database.InsertWorkspaceAgentParams) (database.WorkspaceAgent, error) {
995+
func (q *fakeQuerier) InsertWorkspaceAgent(ctx context.Context, arg database.InsertWorkspaceAgentParams) (database.WorkspaceAgent, error) {
994996
q.mutex.Lock()
995997
defer q.mutex.Unlock()
996998

coderd/workspacebuilds_test.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,16 @@ import (
66
"testing"
77
"time"
88

9+
"github.com/google/uuid"
910
"github.com/stretchr/testify/require"
1011

12+
"cdr.dev/slog/sloggers/slogtest"
13+
14+
"github.com/coder/coder/agent"
1115
"github.com/coder/coder/coderd/coderdtest"
16+
"github.com/coder/coder/coderd/database"
1217
"github.com/coder/coder/codersdk"
18+
"github.com/coder/coder/peer"
1319
"github.com/coder/coder/provisioner/echo"
1420
"github.com/coder/coder/provisionersdk/proto"
1521
)
@@ -115,6 +121,56 @@ func TestWorkspaceBuildResources(t *testing.T) {
115121
require.Equal(t, "example", resources[0].Type)
116122
require.Len(t, resources[0].Agents, 1)
117123
})
124+
t.Run("MultipleBuilds", func(t *testing.T) {
125+
// This ensures that the latest agent can connect through multiple builds.
126+
// Agents won't always have new authentication tokens on rebuild, because
127+
// infrastructure as code won't always recreate the resource.
128+
t.Parallel()
129+
client := coderdtest.New(t, nil)
130+
user := coderdtest.CreateFirstUser(t, client)
131+
coderdtest.NewProvisionerDaemon(t, client)
132+
authToken := uuid.NewString()
133+
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{
134+
Parse: echo.ParseComplete,
135+
Provision: []*proto.Provision_Response{{
136+
Type: &proto.Provision_Response_Complete{
137+
Complete: &proto.Provision_Complete{
138+
Resources: []*proto.Resource{{
139+
Name: "some",
140+
Type: "example",
141+
Agents: []*proto.Agent{{
142+
Id: "something",
143+
Auth: &proto.Agent_Token{
144+
Token: authToken,
145+
},
146+
}},
147+
}},
148+
},
149+
},
150+
}},
151+
})
152+
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
153+
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
154+
workspace := coderdtest.CreateWorkspace(t, client, codersdk.Me, template.ID)
155+
coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
156+
build, err := client.CreateWorkspaceBuild(context.Background(), workspace.ID, codersdk.CreateWorkspaceBuildRequest{
157+
TemplateVersionID: template.ActiveVersionID,
158+
Transition: database.WorkspaceTransitionStart,
159+
DryRun: false,
160+
})
161+
require.NoError(t, err)
162+
coderdtest.AwaitWorkspaceBuildJob(t, client, build.ID)
163+
164+
agentClient := codersdk.New(client.URL)
165+
agentClient.SessionToken = authToken
166+
agentCloser := agent.New(agentClient.ListenWorkspaceAgent, &peer.ConnOptions{
167+
Logger: slogtest.Make(t, nil),
168+
})
169+
t.Cleanup(func() {
170+
_ = agentCloser.Close()
171+
})
172+
coderdtest.AwaitWorkspaceAgents(t, client, build.ID)
173+
})
118174
}
119175

120176
func TestWorkspaceBuildLogs(t *testing.T) {

0 commit comments

Comments
 (0)