mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
feat(agent): populate subagent ID for terraform-defined devcontainers (#21942)
Completes the final piece of the puzzle. Support the pre-creation flow from the agent side.
This commit is contained in:
@@ -425,11 +425,20 @@ func DevcontainerFromProto(pdc *proto.WorkspaceAgentDevcontainer) (codersdk.Work
|
||||
if err != nil {
|
||||
return codersdk.WorkspaceAgentDevcontainer{}, xerrors.Errorf("parse id: %w", err)
|
||||
}
|
||||
var subagentID uuid.NullUUID
|
||||
if pdc.SubagentId != nil {
|
||||
subagentID.Valid = true
|
||||
subagentID.UUID, err = uuid.FromBytes(pdc.SubagentId)
|
||||
if err != nil {
|
||||
return codersdk.WorkspaceAgentDevcontainer{}, xerrors.Errorf("parse subagent id: %w", err)
|
||||
}
|
||||
}
|
||||
return codersdk.WorkspaceAgentDevcontainer{
|
||||
ID: id,
|
||||
Name: pdc.Name,
|
||||
WorkspaceFolder: pdc.WorkspaceFolder,
|
||||
ConfigPath: pdc.ConfigPath,
|
||||
SubagentID: subagentID,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -442,10 +451,16 @@ func ProtoFromDevcontainers(dcs []codersdk.WorkspaceAgentDevcontainer) []*proto.
|
||||
}
|
||||
|
||||
func ProtoFromDevcontainer(dc codersdk.WorkspaceAgentDevcontainer) *proto.WorkspaceAgentDevcontainer {
|
||||
var subagentID []byte
|
||||
if dc.SubagentID.Valid {
|
||||
subagentID = dc.SubagentID.UUID[:]
|
||||
}
|
||||
|
||||
return &proto.WorkspaceAgentDevcontainer{
|
||||
Id: dc.ID[:],
|
||||
Name: dc.Name,
|
||||
WorkspaceFolder: dc.WorkspaceFolder,
|
||||
ConfigPath: dc.ConfigPath,
|
||||
SubagentId: subagentID,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,6 +136,7 @@ func TestManifest(t *testing.T) {
|
||||
ID: uuid.New(),
|
||||
WorkspaceFolder: "/home/coder/coder",
|
||||
ConfigPath: "/home/coder/coder/.devcontainer/devcontainer.json",
|
||||
SubagentID: uuid.NullUUID{Valid: true, UUID: uuid.New()},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -440,10 +440,11 @@ func (s WorkspaceAgentDevcontainerStatus) Transitioning() bool {
|
||||
// WorkspaceAgentDevcontainer defines the location of a devcontainer
|
||||
// configuration in a workspace that is visible to the workspace agent.
|
||||
type WorkspaceAgentDevcontainer struct {
|
||||
ID uuid.UUID `json:"id" format:"uuid"`
|
||||
Name string `json:"name"`
|
||||
WorkspaceFolder string `json:"workspace_folder"`
|
||||
ConfigPath string `json:"config_path,omitempty"`
|
||||
ID uuid.UUID `json:"id" format:"uuid"`
|
||||
Name string `json:"name"`
|
||||
WorkspaceFolder string `json:"workspace_folder"`
|
||||
ConfigPath string `json:"config_path,omitempty"`
|
||||
SubagentID uuid.NullUUID `json:"subagent_id,omitempty" format:"uuid"`
|
||||
|
||||
// Additional runtime fields.
|
||||
Status WorkspaceAgentDevcontainerStatus `json:"status"`
|
||||
@@ -458,6 +459,7 @@ func (d WorkspaceAgentDevcontainer) Equals(other WorkspaceAgentDevcontainer) boo
|
||||
return d.ID == other.ID &&
|
||||
d.Name == other.Name &&
|
||||
d.WorkspaceFolder == other.WorkspaceFolder &&
|
||||
d.SubagentID == other.SubagentID &&
|
||||
d.Status == other.Status &&
|
||||
d.Dirty == other.Dirty &&
|
||||
(d.Container == nil && other.Container == nil ||
|
||||
@@ -467,6 +469,12 @@ func (d WorkspaceAgentDevcontainer) Equals(other WorkspaceAgentDevcontainer) boo
|
||||
d.Error == other.Error
|
||||
}
|
||||
|
||||
// IsTerraformDefined returns true if this devcontainer has resources defined
|
||||
// in Terraform.
|
||||
func (d WorkspaceAgentDevcontainer) IsTerraformDefined() bool {
|
||||
return d.SubagentID.Valid
|
||||
}
|
||||
|
||||
// WorkspaceAgentDevcontainerAgent represents the sub agent for a
|
||||
// devcontainer.
|
||||
type WorkspaceAgentDevcontainerAgent struct {
|
||||
|
||||
@@ -110,3 +110,142 @@ func TestWorkspaceAgentLogTextSpecialChars(t *testing.T) {
|
||||
result := log.Text("main", "startup_script")
|
||||
require.Equal(t, "2024-01-28T10:30:00Z [debug] [agent.main|startup_script] \033[31mError!\033[0m 🚀 Unicode: 日本語", result)
|
||||
}
|
||||
|
||||
func TestWorkspaceAgentDevcontainerEquals(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
agentID := uuid.New()
|
||||
|
||||
base := codersdk.WorkspaceAgentDevcontainer{
|
||||
ID: uuid.New(),
|
||||
Name: "test-dc",
|
||||
WorkspaceFolder: "/workspace",
|
||||
Status: codersdk.WorkspaceAgentDevcontainerStatusRunning,
|
||||
Dirty: false,
|
||||
Container: &codersdk.WorkspaceAgentContainer{ID: "container-123"},
|
||||
Agent: &codersdk.WorkspaceAgentDevcontainerAgent{ID: agentID, Name: "agent-1"},
|
||||
Error: "",
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
modify func(*codersdk.WorkspaceAgentDevcontainer)
|
||||
wantEqual bool
|
||||
}{
|
||||
{
|
||||
name: "identical",
|
||||
modify: func(d *codersdk.WorkspaceAgentDevcontainer) {},
|
||||
wantEqual: true,
|
||||
},
|
||||
{
|
||||
name: "different ID",
|
||||
modify: func(d *codersdk.WorkspaceAgentDevcontainer) { d.ID = uuid.New() },
|
||||
wantEqual: false,
|
||||
},
|
||||
{
|
||||
name: "different Name",
|
||||
modify: func(d *codersdk.WorkspaceAgentDevcontainer) { d.Name = "other-dc" },
|
||||
wantEqual: false,
|
||||
},
|
||||
{
|
||||
name: "different WorkspaceFolder",
|
||||
modify: func(d *codersdk.WorkspaceAgentDevcontainer) { d.WorkspaceFolder = "/other" },
|
||||
wantEqual: false,
|
||||
},
|
||||
{
|
||||
name: "different SubagentID (one valid, one nil)",
|
||||
modify: func(d *codersdk.WorkspaceAgentDevcontainer) {
|
||||
d.SubagentID = uuid.NullUUID{Valid: true, UUID: uuid.New()}
|
||||
},
|
||||
wantEqual: false,
|
||||
},
|
||||
{
|
||||
name: "different SubagentID UUIDs",
|
||||
modify: func(d *codersdk.WorkspaceAgentDevcontainer) {
|
||||
d.SubagentID = uuid.NullUUID{Valid: true, UUID: uuid.New()}
|
||||
},
|
||||
wantEqual: false,
|
||||
},
|
||||
{
|
||||
name: "different Status",
|
||||
modify: func(d *codersdk.WorkspaceAgentDevcontainer) {
|
||||
d.Status = codersdk.WorkspaceAgentDevcontainerStatusStopped
|
||||
},
|
||||
wantEqual: false,
|
||||
},
|
||||
{
|
||||
name: "different Dirty",
|
||||
modify: func(d *codersdk.WorkspaceAgentDevcontainer) { d.Dirty = true },
|
||||
wantEqual: false,
|
||||
},
|
||||
{
|
||||
name: "different Container (one nil)",
|
||||
modify: func(d *codersdk.WorkspaceAgentDevcontainer) { d.Container = nil },
|
||||
wantEqual: false,
|
||||
},
|
||||
{
|
||||
name: "different Container IDs",
|
||||
modify: func(d *codersdk.WorkspaceAgentDevcontainer) {
|
||||
d.Container = &codersdk.WorkspaceAgentContainer{ID: "different-container"}
|
||||
},
|
||||
wantEqual: false,
|
||||
},
|
||||
{
|
||||
name: "different Agent (one nil)",
|
||||
modify: func(d *codersdk.WorkspaceAgentDevcontainer) { d.Agent = nil },
|
||||
wantEqual: false,
|
||||
},
|
||||
{
|
||||
name: "different Agent values",
|
||||
modify: func(d *codersdk.WorkspaceAgentDevcontainer) {
|
||||
d.Agent = &codersdk.WorkspaceAgentDevcontainerAgent{ID: agentID, Name: "agent-2"}
|
||||
},
|
||||
wantEqual: false,
|
||||
},
|
||||
{
|
||||
name: "different Error",
|
||||
modify: func(d *codersdk.WorkspaceAgentDevcontainer) { d.Error = "some error" },
|
||||
wantEqual: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
modified := base
|
||||
tt.modify(&modified)
|
||||
require.Equal(t, tt.wantEqual, base.Equals(modified))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestWorkspaceAgentDevcontainerIsTerraformDefined(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
t.Run("SubagentID Valid", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
dc := codersdk.WorkspaceAgentDevcontainer{
|
||||
ID: uuid.New(),
|
||||
Name: "test-dc",
|
||||
WorkspaceFolder: "/workspace",
|
||||
SubagentID: uuid.NullUUID{Valid: true, UUID: uuid.New()},
|
||||
}
|
||||
|
||||
require.True(t, dc.IsTerraformDefined())
|
||||
})
|
||||
|
||||
t.Run("SubagentID Null", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
dc := codersdk.WorkspaceAgentDevcontainer{
|
||||
ID: uuid.New(),
|
||||
Name: "test-dc",
|
||||
WorkspaceFolder: "/workspace",
|
||||
SubagentID: uuid.NullUUID{Valid: false},
|
||||
}
|
||||
|
||||
require.False(t, dc.IsTerraformDefined())
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user