feat(coderd/agentapi): support terraform-defined subagent ids#21837
feat(coderd/agentapi): support terraform-defined subagent ids#21837DanielleMaywood merged 6 commits intomainfrom
Conversation
ca6855c to
2b48d69
Compare
2b48d69 to
fa0ccbc
Compare
7f95be2 to
9643b75
Compare
9643b75 to
ca54e30
Compare
There was a problem hiding this comment.
Code Review
Reviewed PR #21837: Support for terraform-defined subagent IDs. The changes enable updating pre-created subagents from terraform rather than always creating new ones. Found 3 issues requiring attention.
Summary
Strengths:
- Good separation of create vs. update logic paths
- Comprehensive test coverage with 6 test cases covering various scenarios
- Proper authorization checks via dbauthz layer
- Clear validation of parent-child relationships
Issues:
- Logic reordering breaks existing behavior (validation happens after operations)
- Missing validation when ID is provided in request
- Security: No validation that provided ID actually belongs to current workspace
General Comments
- The new update path is well-designed and properly validates parent relationships
- Test cases are thorough and test both success and error scenarios
- Database query and authorization changes follow project patterns correctly
mafredri
left a comment
There was a problem hiding this comment.
The agentapi look fine to me. 👍🏻 Only potential blocker I see is rbac.
| s.Run("UpdateWorkspaceAgentDisplayAppsByID", s.Mocked(func(dbm *dbmock.MockStore, faker *gofakeit.Faker, check *expects) { | ||
| w := testutil.Fake(s.T(), faker, database.Workspace{}) | ||
| agt := testutil.Fake(s.T(), faker, database.WorkspaceAgent{}) | ||
| arg := database.UpdateWorkspaceAgentDisplayAppsByIDParams{ | ||
| ID: agt.ID, | ||
| DisplayApps: []database.DisplayApp{database.DisplayAppVscode}, | ||
| } | ||
| dbm.EXPECT().GetWorkspaceByAgentID(gomock.Any(), agt.ID).Return(w, nil).AnyTimes() | ||
| dbm.EXPECT().UpdateWorkspaceAgentDisplayAppsByID(gomock.Any(), arg).Return(nil).AnyTimes() | ||
| check.Args(arg).Asserts(w, policy.ActionUpdate).Returns() | ||
| })) |
There was a problem hiding this comment.
This might be a good place to ensure that we don't allow sub-agents to update across workspaces?
There was a problem hiding this comment.
Re-reading this, I'm unsure what you mean. Are these check.Args(...).Asserts(...) capable of testing this explicitly?
There was a problem hiding this comment.
I think you're right. I zoomed in on WithNotAuthorized() but appear to have misunderstood what it actually does.
4960519 to
cf851aa
Compare
cf851aa to
4e92897
Compare
| func (q *querier) UpdateWorkspaceAgentDisplayAppsByID(ctx context.Context, arg database.UpdateWorkspaceAgentDisplayAppsByIDParams) error { | ||
| workspace, err := q.db.GetWorkspaceByAgentID(ctx, arg.ID) | ||
| if err != nil { | ||
| return err | ||
| } | ||
|
|
||
| if err := q.authorizeContext(ctx, policy.ActionUpdateAgent, workspace); err != nil { | ||
| return err | ||
| } | ||
|
|
||
| return q.db.UpdateWorkspaceAgentDisplayAppsByID(ctx, arg) | ||
| } |
| APIKeyScopeWorkspaceDormantStart APIKeyScope = "workspace_dormant:start" | ||
| APIKeyScopeWorkspaceDormantStop APIKeyScope = "workspace_dormant:stop" | ||
| APIKeyScopeWorkspaceDormantUpdate APIKeyScope = "workspace_dormant:update" | ||
| APIKeyScopeWorkspaceDormantUpdateAgent APIKeyScope = "workspace_dormant:update_agent" |
There was a problem hiding this comment.
This is an interesting question - when is this going to happen?
There was a problem hiding this comment.
I think these scopes are internal by-default and have to be explicitly exported? I'm a little unsure about API Key Scopes, so I might need to do some reading to get more context.
mafredri
left a comment
There was a problem hiding this comment.
Looks good! One last question/suggestion, but I leave it up to you as it's not a blocker.
| check: func(t *testing.T, ctx context.Context, db database.Store, resp *proto.CreateSubAgentResponse, agent database.WorkspaceAgent) { | ||
| // Then: The response contains the original agent name, not the new one. | ||
| require.NotNil(t, resp.Agent) | ||
| require.Equal(t, baseChildAgent.Name, resp.Agent.Name) |
There was a problem hiding this comment.
Will the client side see that some inputs were discarded? If not, that might lead to some confusion.
Should we consider introducing an errors field (like app creation errors)? Or perhaps erroring out if the name is changed? (Forcing the client to provide valid input for existing agents.)
There was a problem hiding this comment.
Not at the moment, no.
I think I'll address this as a follow-up once the feature is fully implemented, and will follow the pattern introduced with app creation errors.
Relates to coder/internal#1243
Update
coderd/agentapito handle pre-created sub agents