feat(agent/agentcontainers): implement sub agent injection (#18245)

This change adds support for sub agent creation and injection into dev
containers.

Updates coder/internal#621
This commit is contained in:
Mathias Fredriksson
2025-06-10 12:37:54 +03:00
committed by GitHub
parent 44fff54897
commit fca99174ad
15 changed files with 1218 additions and 146 deletions
+4
View File
@@ -28,6 +28,7 @@ import (
"github.com/coder/serpent"
"github.com/coder/coder/v2/agent"
"github.com/coder/coder/v2/agent/agentcontainers"
"github.com/coder/coder/v2/agent/agentexec"
"github.com/coder/coder/v2/agent/agentssh"
"github.com/coder/coder/v2/agent/reaper"
@@ -362,6 +363,9 @@ func (r *RootCmd) workspaceAgent() *serpent.Command {
BlockFileTransfer: blockFileTransfer,
Execer: execer,
ExperimentalDevcontainersEnabled: experimentalDevcontainersEnabled,
ContainerAPIOptions: []agentcontainers.Option{
agentcontainers.WithSubAgentURL(r.agentURL.String()),
},
})
promHandler := agent.PrometheusMetricsHandler(prometheusRegistry, logger)
+4
View File
@@ -9,6 +9,7 @@ import (
"github.com/ory/dockertest/v3/docker"
"github.com/coder/coder/v2/agent"
"github.com/coder/coder/v2/agent/agentcontainers"
"github.com/coder/coder/v2/agent/agenttest"
"github.com/coder/coder/v2/cli/clitest"
"github.com/coder/coder/v2/coderd/coderdtest"
@@ -111,6 +112,9 @@ func TestExpRpty(t *testing.T) {
_ = agenttest.New(t, client.URL, agentToken, func(o *agent.Options) {
o.ExperimentalDevcontainersEnabled = true
o.ContainerAPIOptions = append(o.ContainerAPIOptions,
agentcontainers.WithContainerLabelIncludeFilter("this.label.does.not.exist.ignore.devcontainers", "true"),
)
})
_ = coderdtest.NewWorkspaceAgentWaiter(t, client, workspace.ID).Wait()
+12 -6
View File
@@ -306,8 +306,8 @@ func TestOpenVSCodeDevContainer(t *testing.T) {
containerFolder := "/workspace/coder"
ctrl := gomock.NewController(t)
mcl := acmock.NewMockContainerCLI(ctrl)
mcl.EXPECT().List(gomock.Any()).Return(
mccli := acmock.NewMockContainerCLI(ctrl)
mccli.EXPECT().List(gomock.Any()).Return(
codersdk.WorkspaceAgentListContainersResponse{
Containers: []codersdk.WorkspaceAgentContainer{
{
@@ -337,7 +337,10 @@ func TestOpenVSCodeDevContainer(t *testing.T) {
_ = agenttest.New(t, client.URL, agentToken, func(o *agent.Options) {
o.ExperimentalDevcontainersEnabled = true
o.ContainerAPIOptions = append(o.ContainerAPIOptions, agentcontainers.WithContainerCLI(mcl))
o.ContainerAPIOptions = append(o.ContainerAPIOptions,
agentcontainers.WithContainerCLI(mccli),
agentcontainers.WithContainerLabelIncludeFilter("this.label.does.not.exist.ignore.devcontainers", "true"),
)
})
_ = coderdtest.NewWorkspaceAgentWaiter(t, client, workspace.ID).Wait()
@@ -481,8 +484,8 @@ func TestOpenVSCodeDevContainer_NoAgentDirectory(t *testing.T) {
containerFolder := "/workspace/coder"
ctrl := gomock.NewController(t)
mcl := acmock.NewMockContainerCLI(ctrl)
mcl.EXPECT().List(gomock.Any()).Return(
mccli := acmock.NewMockContainerCLI(ctrl)
mccli.EXPECT().List(gomock.Any()).Return(
codersdk.WorkspaceAgentListContainersResponse{
Containers: []codersdk.WorkspaceAgentContainer{
{
@@ -511,7 +514,10 @@ func TestOpenVSCodeDevContainer_NoAgentDirectory(t *testing.T) {
_ = agenttest.New(t, client.URL, agentToken, func(o *agent.Options) {
o.ExperimentalDevcontainersEnabled = true
o.ContainerAPIOptions = append(o.ContainerAPIOptions, agentcontainers.WithContainerCLI(mcl))
o.ContainerAPIOptions = append(o.ContainerAPIOptions,
agentcontainers.WithContainerCLI(mccli),
agentcontainers.WithContainerLabelIncludeFilter("this.label.does.not.exist.ignore.devcontainers", "true"),
)
})
_ = coderdtest.NewWorkspaceAgentWaiter(t, client, workspace.ID).Wait()
+7 -1
View File
@@ -2032,6 +2032,9 @@ func TestSSH_Container(t *testing.T) {
_ = agenttest.New(t, client.URL, agentToken, func(o *agent.Options) {
o.ExperimentalDevcontainersEnabled = true
o.ContainerAPIOptions = append(o.ContainerAPIOptions,
agentcontainers.WithContainerLabelIncludeFilter("this.label.does.not.exist.ignore.devcontainers", "true"),
)
})
_ = coderdtest.NewWorkspaceAgentWaiter(t, client, workspace.ID).Wait()
@@ -2069,7 +2072,10 @@ func TestSSH_Container(t *testing.T) {
}, nil).AnyTimes()
_ = agenttest.New(t, client.URL, agentToken, func(o *agent.Options) {
o.ExperimentalDevcontainersEnabled = true
o.ContainerAPIOptions = append(o.ContainerAPIOptions, agentcontainers.WithContainerCLI(mLister))
o.ContainerAPIOptions = append(o.ContainerAPIOptions,
agentcontainers.WithContainerCLI(mLister),
agentcontainers.WithContainerLabelIncludeFilter("this.label.does.not.exist.ignore.devcontainers", "true"),
)
})
_ = coderdtest.NewWorkspaceAgentWaiter(t, client, workspace.ID).Wait()