Skip to content

Commit eab73d9

Browse files
committed
feat(agent): disable devcontainers for sub agents
Updates coder/internal#621
1 parent fca9917 commit eab73d9

File tree

5 files changed

+53
-0
lines changed

5 files changed

+53
-0
lines changed

agent/agent.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1080,6 +1080,18 @@ func (a *agent) handleManifest(manifestOK *checkpoint) func(ctx context.Context,
10801080
if manifest.AgentID == uuid.Nil {
10811081
return xerrors.New("nil agentID returned by manifest")
10821082
}
1083+
if manifest.ParentID != uuid.Nil {
1084+
// This is a sub agent, disable all the features that should not
1085+
// be used by sub agents.
1086+
a.logger.Info(ctx, "sub agent detected, disabling features",
1087+
slog.F("parent_id", manifest.ParentID),
1088+
slog.F("agent_id", manifest.AgentID),
1089+
)
1090+
if a.experimentalDevcontainersEnabled {
1091+
a.logger.Warn(ctx, "devcontainers are not supported on sub agents, disabling feature")
1092+
a.experimentalDevcontainersEnabled = false
1093+
}
1094+
}
10831095
a.client.RewriteDERPMap(manifest.DERPMap)
10841096

10851097
// Expand the directory and send it back to coderd so external

agent/agent_test.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2423,6 +2423,34 @@ waitForOutcomeLoop:
24232423
}(container)
24242424
}
24252425

2426+
func TestAgent_DevcontainersDisabledForSubAgent(t *testing.T) {
2427+
t.Parallel()
2428+
2429+
// Create a manifest with a ParentID to make this a sub agent.
2430+
manifest := agentsdk.Manifest{
2431+
AgentID: uuid.New(),
2432+
ParentID: uuid.New(),
2433+
}
2434+
2435+
// Setup the agent with devcontainers enabled initially.
2436+
//nolint:dogsled
2437+
conn, _, _, _, _ := setupAgent(t, manifest, 0, func(_ *agenttest.Client, o *agent.Options) {
2438+
o.ExperimentalDevcontainersEnabled = true
2439+
})
2440+
2441+
// Query the containers API endpoint. This should fail because
2442+
// devcontainers have been disabled for the sub agent.
2443+
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitMedium)
2444+
defer cancel()
2445+
2446+
_, err := conn.ListContainers(ctx)
2447+
require.Error(t, err)
2448+
2449+
// Verify the error message contains the expected text.
2450+
require.Contains(t, err.Error(), "The agent dev containers feature is experimental and not enabled by default.")
2451+
require.Contains(t, err.Error(), "To enable this feature, set CODER_AGENT_DEVCONTAINERS_ENABLE=true in your template.")
2452+
}
2453+
24262454
func TestAgent_Dial(t *testing.T) {
24272455
t.Parallel()
24282456

codersdk/agentsdk/agentsdk.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ type PostMetadataRequest struct {
102102
type PostMetadataRequestDeprecated = codersdk.WorkspaceAgentMetadataResult
103103

104104
type Manifest struct {
105+
ParentID uuid.UUID `json:"parent_id"`
105106
AgentID uuid.UUID `json:"agent_id"`
106107
AgentName string `json:"agent_name"`
107108
// OwnerUsername and WorkspaceID are used by an open-source user to identify the workspace.

codersdk/agentsdk/convert.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,14 @@ import (
1515
)
1616

1717
func ManifestFromProto(manifest *proto.Manifest) (Manifest, error) {
18+
parentID := uuid.Nil
19+
if pid := manifest.GetParentId(); pid != nil {
20+
var err error
21+
parentID, err = uuid.FromBytes(pid)
22+
if err != nil {
23+
return Manifest{}, xerrors.Errorf("error converting workspace agent parent ID: %w", err)
24+
}
25+
}
1826
apps, err := AppsFromProto(manifest.Apps)
1927
if err != nil {
2028
return Manifest{}, xerrors.Errorf("error converting workspace agent apps: %w", err)
@@ -36,6 +44,7 @@ func ManifestFromProto(manifest *proto.Manifest) (Manifest, error) {
3644
return Manifest{}, xerrors.Errorf("error converting workspace agent devcontainers: %w", err)
3745
}
3846
return Manifest{
47+
ParentID: parentID,
3948
AgentID: agentID,
4049
AgentName: manifest.AgentName,
4150
OwnerName: manifest.OwnerUsername,
@@ -62,6 +71,7 @@ func ProtoFromManifest(manifest Manifest) (*proto.Manifest, error) {
6271
return nil, xerrors.Errorf("convert workspace apps: %w", err)
6372
}
6473
return &proto.Manifest{
74+
ParentId: manifest.ParentID[:],
6575
AgentId: manifest.AgentID[:],
6676
AgentName: manifest.AgentName,
6777
OwnerUsername: manifest.OwnerName,

codersdk/agentsdk/convert_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
func TestManifest(t *testing.T) {
2020
t.Parallel()
2121
manifest := agentsdk.Manifest{
22+
ParentID: uuid.New(),
2223
AgentID: uuid.New(),
2324
AgentName: "test-agent",
2425
OwnerName: "test-owner",
@@ -142,6 +143,7 @@ func TestManifest(t *testing.T) {
142143
require.NoError(t, err)
143144
back, err := agentsdk.ManifestFromProto(p)
144145
require.NoError(t, err)
146+
require.Equal(t, manifest.ParentID, back.ParentID)
145147
require.Equal(t, manifest.AgentID, back.AgentID)
146148
require.Equal(t, manifest.AgentName, back.AgentName)
147149
require.Equal(t, manifest.OwnerName, back.OwnerName)

0 commit comments

Comments
 (0)