From 5b3ec52cdbaeec6fab31d446acaf9bc6a62cfd51 Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Tue, 10 Jun 2025 10:28:06 +0000 Subject: [PATCH] feat(agent): disable devcontainers for sub agents Updates coder/internal#621 --- agent/agent.go | 12 ++++++++++++ agent/agent_test.go | 28 ++++++++++++++++++++++++++++ codersdk/agentsdk/agentsdk.go | 1 + codersdk/agentsdk/convert.go | 10 ++++++++++ codersdk/agentsdk/convert_test.go | 2 ++ 5 files changed, 53 insertions(+) diff --git a/agent/agent.go b/agent/agent.go index 17298e7aa5772..9f105ee296f5c 100644 --- a/agent/agent.go +++ b/agent/agent.go @@ -1080,6 +1080,18 @@ func (a *agent) handleManifest(manifestOK *checkpoint) func(ctx context.Context, if manifest.AgentID == uuid.Nil { return xerrors.New("nil agentID returned by manifest") } + if manifest.ParentID != uuid.Nil { + // This is a sub agent, disable all the features that should not + // be used by sub agents. + a.logger.Debug(ctx, "sub agent detected, disabling features", + slog.F("parent_id", manifest.ParentID), + slog.F("agent_id", manifest.AgentID), + ) + if a.experimentalDevcontainersEnabled { + a.logger.Info(ctx, "devcontainers are not supported on sub agents, disabling feature") + a.experimentalDevcontainersEnabled = false + } + } a.client.RewriteDERPMap(manifest.DERPMap) // Expand the directory and send it back to coderd so external diff --git a/agent/agent_test.go b/agent/agent_test.go index 3ef9e4f4c75ba..9a8073a289b5f 100644 --- a/agent/agent_test.go +++ b/agent/agent_test.go @@ -2423,6 +2423,34 @@ waitForOutcomeLoop: }(container) } +func TestAgent_DevcontainersDisabledForSubAgent(t *testing.T) { + t.Parallel() + + // Create a manifest with a ParentID to make this a sub agent. + manifest := agentsdk.Manifest{ + AgentID: uuid.New(), + ParentID: uuid.New(), + } + + // Setup the agent with devcontainers enabled initially. + //nolint:dogsled + conn, _, _, _, _ := setupAgent(t, manifest, 0, func(_ *agenttest.Client, o *agent.Options) { + o.ExperimentalDevcontainersEnabled = true + }) + + // Query the containers API endpoint. This should fail because + // devcontainers have been disabled for the sub agent. + ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitMedium) + defer cancel() + + _, err := conn.ListContainers(ctx) + require.Error(t, err) + + // Verify the error message contains the expected text. + require.Contains(t, err.Error(), "The agent dev containers feature is experimental and not enabled by default.") + require.Contains(t, err.Error(), "To enable this feature, set CODER_AGENT_DEVCONTAINERS_ENABLE=true in your template.") +} + func TestAgent_Dial(t *testing.T) { t.Parallel() diff --git a/codersdk/agentsdk/agentsdk.go b/codersdk/agentsdk/agentsdk.go index e3b036dcdf00a..f44c19b998e21 100644 --- a/codersdk/agentsdk/agentsdk.go +++ b/codersdk/agentsdk/agentsdk.go @@ -102,6 +102,7 @@ type PostMetadataRequest struct { type PostMetadataRequestDeprecated = codersdk.WorkspaceAgentMetadataResult type Manifest struct { + ParentID uuid.UUID `json:"parent_id"` AgentID uuid.UUID `json:"agent_id"` AgentName string `json:"agent_name"` // OwnerUsername and WorkspaceID are used by an open-source user to identify the workspace. diff --git a/codersdk/agentsdk/convert.go b/codersdk/agentsdk/convert.go index 2b7dff950a3e7..d01c9e527fce9 100644 --- a/codersdk/agentsdk/convert.go +++ b/codersdk/agentsdk/convert.go @@ -15,6 +15,14 @@ import ( ) func ManifestFromProto(manifest *proto.Manifest) (Manifest, error) { + parentID := uuid.Nil + if pid := manifest.GetParentId(); pid != nil { + var err error + parentID, err = uuid.FromBytes(pid) + if err != nil { + return Manifest{}, xerrors.Errorf("error converting workspace agent parent ID: %w", err) + } + } apps, err := AppsFromProto(manifest.Apps) if err != nil { return Manifest{}, xerrors.Errorf("error converting workspace agent apps: %w", err) @@ -36,6 +44,7 @@ func ManifestFromProto(manifest *proto.Manifest) (Manifest, error) { return Manifest{}, xerrors.Errorf("error converting workspace agent devcontainers: %w", err) } return Manifest{ + ParentID: parentID, AgentID: agentID, AgentName: manifest.AgentName, OwnerName: manifest.OwnerUsername, @@ -62,6 +71,7 @@ func ProtoFromManifest(manifest Manifest) (*proto.Manifest, error) { return nil, xerrors.Errorf("convert workspace apps: %w", err) } return &proto.Manifest{ + ParentId: manifest.ParentID[:], AgentId: manifest.AgentID[:], AgentName: manifest.AgentName, OwnerUsername: manifest.OwnerName, diff --git a/codersdk/agentsdk/convert_test.go b/codersdk/agentsdk/convert_test.go index 09482b1694910..f324d504b838a 100644 --- a/codersdk/agentsdk/convert_test.go +++ b/codersdk/agentsdk/convert_test.go @@ -19,6 +19,7 @@ import ( func TestManifest(t *testing.T) { t.Parallel() manifest := agentsdk.Manifest{ + ParentID: uuid.New(), AgentID: uuid.New(), AgentName: "test-agent", OwnerName: "test-owner", @@ -142,6 +143,7 @@ func TestManifest(t *testing.T) { require.NoError(t, err) back, err := agentsdk.ManifestFromProto(p) require.NoError(t, err) + require.Equal(t, manifest.ParentID, back.ParentID) require.Equal(t, manifest.AgentID, back.AgentID) require.Equal(t, manifest.AgentName, back.AgentName) require.Equal(t, manifest.OwnerName, back.OwnerName) pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy