@@ -72,16 +72,17 @@ type API struct {
72
72
configFileModifiedTimes map [string ]time.Time // By config file path.
73
73
recreateSuccessTimes map [string ]time.Time // By workspace folder.
74
74
recreateErrorTimes map [string ]time.Time // By workspace folder.
75
- injectedSubAgentProcs map [string ]subAgentProcess // Bycontainer ID .
75
+ injectedSubAgentProcs map [string ]subAgentProcess // Byworkspace folder .
76
76
asyncWg sync.WaitGroup
77
77
78
78
devcontainerLogSourceIDs map [string ]uuid.UUID // By workspace folder.
79
79
}
80
80
81
81
type subAgentProcess struct {
82
- agent SubAgent
83
- ctx context.Context
84
- stop context.CancelFunc
82
+ agent SubAgent
83
+ containerID string
84
+ ctx context.Context
85
+ stop context.CancelFunc
85
86
}
86
87
87
88
// Option is a functional option for API.
@@ -586,7 +587,11 @@ func (api *API) processUpdatedContainersLocked(ctx context.Context, updated code
586
587
dc .Dirty = true
587
588
}
588
589
589
- if _ ,injected := api .injectedSubAgentProcs [dc .Container .ID ];! injected && dc .Status == codersdk .WorkspaceAgentDevcontainerStatusRunning {
590
+ proc ,injected := api .injectedSubAgentProcs [dc .WorkspaceFolder ]
591
+ if injected && proc .containerID != dc .Container .ID {
592
+ injected = false // The container ID changed, we need to re-inject.
593
+ }
594
+ if ! injected && dc .Status == codersdk .WorkspaceAgentDevcontainerStatusRunning {
590
595
err := api .injectSubAgentIntoContainerLocked (ctx ,dc )
591
596
if err != nil {
592
597
logger .Error (ctx ,"inject subagent into container failed" ,slog .Error (err ))
@@ -660,10 +665,22 @@ func (api *API) getContainers() (codersdk.WorkspaceAgentListContainersResponse,
660
665
if len (api .knownDevcontainers )> 0 {
661
666
devcontainers = make ([]codersdk.WorkspaceAgentDevcontainer ,0 ,len (api .knownDevcontainers ))
662
667
for _ ,dc := range api .knownDevcontainers {
668
+ // Include the agent if it's been created (we're iterating over
669
+ // copies, so mutating is fine).
670
+ if dc .Container != nil {
671
+ if proc := api .injectedSubAgentProcs [dc .WorkspaceFolder ];proc .agent .ID != uuid .Nil && proc .containerID == dc .Container .ID {
672
+ dc .Agent = & codersdk.WorkspaceAgentDevcontainerAgent {
673
+ ID :proc .agent .ID ,
674
+ Name :proc .agent .Name ,
675
+ Directory :proc .agent .Directory ,
676
+ }
677
+ }
678
+ }
679
+
663
680
devcontainers = append (devcontainers ,dc )
664
681
}
665
682
slices .SortFunc (devcontainers ,func (a ,b codersdk.WorkspaceAgentDevcontainer )int {
666
- return strings .Compare (a .ID . String () ,b .ID . String () )
683
+ return strings .Compare (a .Name ,b .Name )
667
684
})
668
685
}
669
686
@@ -975,9 +992,25 @@ func (api *API) injectSubAgentIntoContainerLocked(ctx context.Context, dc coders
975
992
return xerrors .New ("container is nil, cannot inject subagent" )
976
993
}
977
994
995
+ logger := api .logger .With (
996
+ slog .F ("devcontainer_id" ,dc .ID ),
997
+ slog .F ("devcontainer_name" ,dc .Name ),
998
+ slog .F ("workspace_folder" ,dc .WorkspaceFolder ),
999
+ slog .F ("config_path" ,dc .ConfigPath ),
1000
+ slog .F ("container_id" ,container .ID ),
1001
+ slog .F ("container_name" ,container .FriendlyName ),
1002
+ )
1003
+
978
1004
// Skip if subagent already exists for this container.
979
- if _ ,injected := api .injectedSubAgentProcs [container .ID ];injected || api .closed {
980
- return nil
1005
+ if proc ,injected := api .injectedSubAgentProcs [dc .WorkspaceFolder ];injected || api .closed {
1006
+ if proc .containerID == container .ID {
1007
+ return nil
1008
+ }
1009
+
1010
+ // If the subagent is already injected but the container ID has
1011
+ // changed, we need to inject it into the new container.
1012
+ logger .Debug (ctx ,"injecting subagent into new container" )
1013
+ proc .stop ()
981
1014
}
982
1015
983
1016
// Mark subagent as being injected immediately with a placeholder.
@@ -1010,13 +1043,6 @@ func (api *API) injectSubAgentIntoContainerLocked(ctx context.Context, dc coders
1010
1043
api .mu .Unlock ()
1011
1044
defer api .mu .Lock ()// Re-lock.
1012
1045
1013
- logger := api .logger .With (
1014
- slog .F ("devcontainer_id" ,dc .ID ),
1015
- slog .F ("devcontainer_name" ,dc .Name ),
1016
- slog .F ("workspace_folder" ,dc .WorkspaceFolder ),
1017
- slog .F ("config_path" ,dc .ConfigPath ),
1018
- )
1019
-
1020
1046
arch ,err := api .ccli .DetectArchitecture (ctx ,container .ID )
1021
1047
if err != nil {
1022
1048
return xerrors .Errorf ("detect architecture: %w" ,err )
@@ -1145,7 +1171,9 @@ func (api *API) runSubAgentInContainer(ctx context.Context, dc codersdk.Workspac
1145
1171
}
1146
1172
1147
1173
api .mu .Lock ()
1148
- delete (api .injectedSubAgentProcs ,container .ID )
1174
+ if api .injectedSubAgentProcs [dc .WorkspaceFolder ].containerID == container .ID {
1175
+ delete (api .injectedSubAgentProcs ,dc .WorkspaceFolder )
1176
+ }
1149
1177
api .mu .Unlock ()
1150
1178
1151
1179
logger .Debug (ctx ,"agent process cleanup complete" )
@@ -1160,10 +1188,11 @@ func (api *API) runSubAgentInContainer(ctx context.Context, dc codersdk.Workspac
1160
1188
return
1161
1189
}
1162
1190
// Update the placeholder with a valid subagent, context and stop.
1163
- api .injectedSubAgentProcs [container .ID ]= subAgentProcess {
1164
- agent :agent ,
1165
- ctx :agentCtx ,
1166
- stop :agentStop ,
1191
+ api .injectedSubAgentProcs [dc .WorkspaceFolder ]= subAgentProcess {
1192
+ agent :agent ,
1193
+ containerID :container .ID ,
1194
+ ctx :agentCtx ,
1195
+ stop :agentStop ,
1167
1196
}
1168
1197
api .mu .Unlock ()
1169
1198
@@ -1195,7 +1224,11 @@ func (api *API) Close() error {
1195
1224
api .closed = true
1196
1225
1197
1226
for _ ,proc := range api .injectedSubAgentProcs {
1198
- api .logger .Debug (api .ctx ,"canceling subagent process" ,slog .F ("agent_name" ,proc .agent .Name ),slog .F ("agent_id" ,proc .agent .ID ))
1227
+ api .logger .Debug (api .ctx ,"canceling subagent process" ,
1228
+ slog .F ("agent_name" ,proc .agent .Name ),
1229
+ slog .F ("agent_id" ,proc .agent .ID ),
1230
+ slog .F ("container_id" ,proc .containerID ),
1231
+ )
1199
1232
proc .stop ()
1200
1233
}
1201
1234