mirror of
https://github.com/coder/coder.git
synced 2026-10-16 14:48:56 +08:00
refactor(coderd): pass the agent's build ID to the manifest API
The agent token middleware already resolves the agent's build, so the manifest no longer re-reads the resource and build to list its secrets.
This commit is contained in:
committed by
Steven Masley
parent
79da70bd00
commit
3fb12d964c
@@ -96,6 +96,9 @@ type Options struct {
|
||||
WorkspaceID uuid.UUID
|
||||
OrganizationID uuid.UUID
|
||||
TemplateVersionID uuid.UUID
|
||||
// WorkspaceBuildID is the build that created the agent, resolved by the
|
||||
// agent token middleware.
|
||||
WorkspaceBuildID uuid.UUID
|
||||
|
||||
AuthenticatedCtx context.Context
|
||||
Log slog.Logger
|
||||
@@ -156,6 +159,7 @@ func New(opts Options, workspace database.Workspace, agent database.WorkspaceAge
|
||||
Database: opts.Database,
|
||||
DerpMapFn: opts.DerpMapFn,
|
||||
WorkspaceID: opts.WorkspaceID,
|
||||
WorkspaceBuildID: opts.WorkspaceBuildID,
|
||||
}
|
||||
|
||||
// Don't cache details for prebuilds, though the cached fields will eventually be updated
|
||||
|
||||
@@ -32,6 +32,9 @@ type ManifestAPI struct {
|
||||
DerpForceWebSockets bool
|
||||
DisableUserSecretFilePath bool
|
||||
WorkspaceID uuid.UUID
|
||||
// WorkspaceBuildID is the build that created the agent. Its live secrets
|
||||
// are delivered in the manifest.
|
||||
WorkspaceBuildID uuid.UUID
|
||||
|
||||
AgentFn func(ctx context.Context) (database.WorkspaceAgent, error)
|
||||
Database database.Store
|
||||
@@ -98,9 +101,10 @@ func (a *ManifestAPI) GetManifest(ctx context.Context, _ *agentproto.GetManifest
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("getting user secrets: %w", err)
|
||||
}
|
||||
workspaceSecrets, err := a.agentBuildSecrets(ctx, workspaceAgent)
|
||||
// nolint:gocritic // Only the workspace secret manager reads values.
|
||||
workspaceSecrets, err := a.Database.ListActiveWorkspaceSecrets(dbauthz.AsWorkspaceSecretManager(ctx), a.WorkspaceBuildID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, xerrors.Errorf("getting workspace secrets: %w", err)
|
||||
}
|
||||
|
||||
appSlug := appurl.ApplicationURL{
|
||||
@@ -168,29 +172,6 @@ func (a *ManifestAPI) GetManifest(ctx context.Context, _ *agentproto.GetManifest
|
||||
}, nil
|
||||
}
|
||||
|
||||
// agentBuildSecrets returns the live workspace secrets linked to the build
|
||||
// that created the agent. Only the latest build has live secrets, so an agent
|
||||
// left over from an earlier build receives none.
|
||||
func (a *ManifestAPI) agentBuildSecrets(ctx context.Context, agent database.WorkspaceAgent) ([]database.WorkspaceSecret, error) {
|
||||
// nolint:gocritic // System context needed to resolve the agent's build;
|
||||
// the agent is already authenticated.
|
||||
sysCtx := dbauthz.AsSystemRestricted(ctx)
|
||||
resource, err := a.Database.GetWorkspaceResourceByID(sysCtx, agent.ResourceID)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("getting workspace agent resource: %w", err)
|
||||
}
|
||||
build, err := a.Database.GetWorkspaceBuildByJobID(sysCtx, resource.JobID)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("getting workspace agent build: %w", err)
|
||||
}
|
||||
// nolint:gocritic // Only the workspace secret manager reads values.
|
||||
secrets, err := a.Database.ListActiveWorkspaceSecrets(dbauthz.AsWorkspaceSecretManager(ctx), build.ID)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("getting workspace secrets: %w", err)
|
||||
}
|
||||
return secrets, nil
|
||||
}
|
||||
|
||||
func vscodeProxyURI(app appurl.ApplicationURL, accessURL *url.URL, appHost string) string {
|
||||
// Proxying by port only works for subdomains. If subdomain support is not
|
||||
// available, return an empty string.
|
||||
|
||||
@@ -56,7 +56,6 @@ func TestGetManifest(t *testing.T) {
|
||||
agentBuild = database.WorkspaceBuild{
|
||||
ID: uuid.New(),
|
||||
WorkspaceID: workspace.ID,
|
||||
JobID: uuid.New(),
|
||||
}
|
||||
agent = database.WorkspaceAgent{
|
||||
ID: uuid.New(),
|
||||
@@ -341,10 +340,11 @@ func TestGetManifest(t *testing.T) {
|
||||
DisableDirectConnections: true,
|
||||
DerpForceWebSockets: true,
|
||||
|
||||
AgentFn: func(ctx context.Context) (database.WorkspaceAgent, error) { return agent, nil },
|
||||
WorkspaceID: workspace.ID,
|
||||
Database: mDB,
|
||||
DerpMapFn: derpMapFn,
|
||||
AgentFn: func(ctx context.Context) (database.WorkspaceAgent, error) { return agent, nil },
|
||||
WorkspaceID: workspace.ID,
|
||||
WorkspaceBuildID: agentBuild.ID,
|
||||
Database: mDB,
|
||||
DerpMapFn: derpMapFn,
|
||||
}
|
||||
|
||||
mDB.EXPECT().GetWorkspaceAppsByAgentID(gomock.Any(), agent.ID).Return(apps, nil)
|
||||
@@ -356,8 +356,6 @@ func TestGetManifest(t *testing.T) {
|
||||
mDB.EXPECT().GetWorkspaceAgentDevcontainersByAgentID(gomock.Any(), agent.ID).Return(devcontainers, nil)
|
||||
mDB.EXPECT().GetWorkspaceByID(gomock.Any(), workspace.ID).Return(workspace, nil)
|
||||
mDB.EXPECT().ListUserSecretsWithValues(gomock.Any(), workspace.OwnerID).Return(nil, nil)
|
||||
mDB.EXPECT().GetWorkspaceResourceByID(gomock.Any(), gomock.Any()).Return(database.WorkspaceResource{JobID: agentBuild.JobID}, nil)
|
||||
mDB.EXPECT().GetWorkspaceBuildByJobID(gomock.Any(), agentBuild.JobID).Return(agentBuild, nil)
|
||||
mDB.EXPECT().ListActiveWorkspaceSecrets(gomock.Any(), agentBuild.ID).Return(nil, nil)
|
||||
|
||||
got, err := api.GetManifest(context.Background(), &agentproto.GetManifestRequest{})
|
||||
@@ -411,10 +409,11 @@ func TestGetManifest(t *testing.T) {
|
||||
DisableDirectConnections: true,
|
||||
DerpForceWebSockets: true,
|
||||
|
||||
AgentFn: func(ctx context.Context) (database.WorkspaceAgent, error) { return childAgent, nil },
|
||||
WorkspaceID: workspace.ID,
|
||||
Database: mDB,
|
||||
DerpMapFn: derpMapFn,
|
||||
AgentFn: func(ctx context.Context) (database.WorkspaceAgent, error) { return childAgent, nil },
|
||||
WorkspaceID: workspace.ID,
|
||||
WorkspaceBuildID: agentBuild.ID,
|
||||
Database: mDB,
|
||||
DerpMapFn: derpMapFn,
|
||||
}
|
||||
|
||||
mDB.EXPECT().GetWorkspaceAppsByAgentID(gomock.Any(), childAgent.ID).Return([]database.WorkspaceApp{}, nil)
|
||||
@@ -426,8 +425,6 @@ func TestGetManifest(t *testing.T) {
|
||||
mDB.EXPECT().GetWorkspaceAgentDevcontainersByAgentID(gomock.Any(), childAgent.ID).Return([]database.WorkspaceAgentDevcontainer{}, nil)
|
||||
mDB.EXPECT().GetWorkspaceByID(gomock.Any(), workspace.ID).Return(workspace, nil)
|
||||
mDB.EXPECT().ListUserSecretsWithValues(gomock.Any(), workspace.OwnerID).Return(nil, nil)
|
||||
mDB.EXPECT().GetWorkspaceResourceByID(gomock.Any(), gomock.Any()).Return(database.WorkspaceResource{JobID: agentBuild.JobID}, nil)
|
||||
mDB.EXPECT().GetWorkspaceBuildByJobID(gomock.Any(), agentBuild.JobID).Return(agentBuild, nil)
|
||||
mDB.EXPECT().ListActiveWorkspaceSecrets(gomock.Any(), agentBuild.ID).Return(nil, nil)
|
||||
|
||||
got, err := api.GetManifest(context.Background(), &agentproto.GetManifestRequest{})
|
||||
@@ -588,10 +585,11 @@ func TestGetManifest(t *testing.T) {
|
||||
DisableDirectConnections: true,
|
||||
DerpForceWebSockets: true,
|
||||
|
||||
AgentFn: func(ctx context.Context) (database.WorkspaceAgent, error) { return childAgent, nil },
|
||||
WorkspaceID: workspace.ID,
|
||||
Database: mDB,
|
||||
DerpMapFn: derpMapFn,
|
||||
AgentFn: func(ctx context.Context) (database.WorkspaceAgent, error) { return childAgent, nil },
|
||||
WorkspaceID: workspace.ID,
|
||||
WorkspaceBuildID: agentBuild.ID,
|
||||
Database: mDB,
|
||||
DerpMapFn: derpMapFn,
|
||||
}
|
||||
|
||||
mDB.EXPECT().GetWorkspaceAppsByAgentID(gomock.Any(), childAgent.ID).Return([]database.WorkspaceApp{}, nil)
|
||||
@@ -614,8 +612,6 @@ func TestGetManifest(t *testing.T) {
|
||||
}, nil)
|
||||
// Workspace secrets follow user secrets so a workspace secret that
|
||||
// targets the same env var wins when the agent applies them in order.
|
||||
mDB.EXPECT().GetWorkspaceResourceByID(gomock.Any(), gomock.Any()).Return(database.WorkspaceResource{JobID: agentBuild.JobID}, nil)
|
||||
mDB.EXPECT().GetWorkspaceBuildByJobID(gomock.Any(), agentBuild.JobID).Return(agentBuild, nil)
|
||||
mDB.EXPECT().ListActiveWorkspaceSecrets(gomock.Any(), agentBuild.ID).Return([]database.WorkspaceSecret{
|
||||
{EnvName: "GITHUB_TOKEN", Value: sql.NullString{String: "ghp_workspace", Valid: true}},
|
||||
}, nil)
|
||||
@@ -718,10 +714,11 @@ func TestGetManifest(t *testing.T) {
|
||||
DisableDirectConnections: true,
|
||||
DerpForceWebSockets: true,
|
||||
|
||||
AgentFn: func(ctx context.Context) (database.WorkspaceAgent, error) { return agent, nil },
|
||||
WorkspaceID: workspace.ID,
|
||||
Database: mDB,
|
||||
DerpMapFn: derpMapFn,
|
||||
AgentFn: func(ctx context.Context) (database.WorkspaceAgent, error) { return agent, nil },
|
||||
WorkspaceID: workspace.ID,
|
||||
WorkspaceBuildID: agentBuild.ID,
|
||||
Database: mDB,
|
||||
DerpMapFn: derpMapFn,
|
||||
}
|
||||
|
||||
mDB.EXPECT().GetWorkspaceAppsByAgentID(gomock.Any(), agent.ID).Return(apps, nil)
|
||||
@@ -733,8 +730,6 @@ func TestGetManifest(t *testing.T) {
|
||||
mDB.EXPECT().GetWorkspaceAgentDevcontainersByAgentID(gomock.Any(), agent.ID).Return(devcontainers, nil)
|
||||
mDB.EXPECT().GetWorkspaceByID(gomock.Any(), workspace.ID).Return(workspace, nil)
|
||||
mDB.EXPECT().ListUserSecretsWithValues(gomock.Any(), workspace.OwnerID).Return(nil, nil)
|
||||
mDB.EXPECT().GetWorkspaceResourceByID(gomock.Any(), gomock.Any()).Return(database.WorkspaceResource{JobID: agentBuild.JobID}, nil)
|
||||
mDB.EXPECT().GetWorkspaceBuildByJobID(gomock.Any(), agentBuild.JobID).Return(agentBuild, nil)
|
||||
mDB.EXPECT().ListActiveWorkspaceSecrets(gomock.Any(), agentBuild.ID).Return(nil, nil)
|
||||
|
||||
got, err := api.GetManifest(context.Background(), &agentproto.GetManifestRequest{})
|
||||
|
||||
@@ -159,6 +159,7 @@ func (api *API) workspaceAgentRPC(rw http.ResponseWriter, r *http.Request) {
|
||||
WorkspaceID: workspace.ID,
|
||||
OrganizationID: workspace.OrganizationID,
|
||||
TemplateVersionID: build.TemplateVersionID,
|
||||
WorkspaceBuildID: build.ID,
|
||||
|
||||
AuthenticatedCtx: ctx,
|
||||
Log: logger,
|
||||
|
||||
Reference in New Issue
Block a user