Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit7fa1ad8

Browse files
authored
fix(agent/agentcontainers): reduce need to recreate sub agents (#18402)
1 parent7e9a9e0 commit7fa1ad8

File tree

5 files changed

+192
-99
lines changed

5 files changed

+192
-99
lines changed

‎agent/agent_test.go

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2080,6 +2080,10 @@ func TestAgent_DevcontainerAutostart(t *testing.T) {
20802080
subAgentConnected:=make(chansubAgentRequestPayload,1)
20812081
subAgentReady:=make(chanstruct{},1)
20822082
srv:=httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter,r*http.Request) {
2083+
ifr.Method==http.MethodGet&&strings.HasPrefix(r.URL.Path,"/api/v2/workspaceagents/me/") {
2084+
return
2085+
}
2086+
20832087
t.Logf("Sub-agent request received: %s %s",r.Method,r.URL.Path)
20842088

20852089
ifr.Method!=http.MethodPost {
@@ -2226,11 +2230,22 @@ func TestAgent_DevcontainerAutostart(t *testing.T) {
22262230
// Ensure the container update routine runs.
22272231
tickerFuncTrap.MustWait(ctx).MustRelease(ctx)
22282232
tickerFuncTrap.Close()
2229-
_,next:=mClock.AdvanceNext()
2230-
next.MustWait(ctx)
22312233

2232-
// Verify that a subagent was created.
2233-
subAgents:=agentClient.GetSubAgents()
2234+
// Since the agent does RefreshContainers, and the ticker function
2235+
// is set to skip instead of queue, we must advance the clock
2236+
// multiple times to ensure that the sub-agent is created.
2237+
varsubAgents []*proto.SubAgent
2238+
for {
2239+
_,next:=mClock.AdvanceNext()
2240+
next.MustWait(ctx)
2241+
2242+
// Verify that a subagent was created.
2243+
subAgents=agentClient.GetSubAgents()
2244+
iflen(subAgents)>0 {
2245+
t.Logf("Found sub-agents: %d",len(subAgents))
2246+
break
2247+
}
2248+
}
22342249
require.Len(t,subAgents,1,"expected one sub agent")
22352250

22362251
subAgent:=subAgents[0]

‎agent/agentcontainers/api.go

Lines changed: 58 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -671,9 +671,9 @@ func (api *API) getContainers() (codersdk.WorkspaceAgentListContainersResponse,
671671
iflen(api.knownDevcontainers)>0 {
672672
devcontainers=make([]codersdk.WorkspaceAgentDevcontainer,0,len(api.knownDevcontainers))
673673
for_,dc:=rangeapi.knownDevcontainers {
674-
// Include the agent if it'sbeen created (we're iterating over
674+
// Include the agent if it'srunning (we're iterating over
675675
// copies, so mutating is fine).
676-
ifproc:=api.injectedSubAgentProcs[dc.WorkspaceFolder];proc.agent.ID!=uuid.Nil&&dc.Container!=nil&&proc.containerID==dc.Container.ID{
676+
ifproc:=api.injectedSubAgentProcs[dc.WorkspaceFolder];proc.agent.ID!=uuid.Nil {
677677
dc.Agent=&codersdk.WorkspaceAgentDevcontainerAgent{
678678
ID:proc.agent.ID,
679679
Name:proc.agent.Name,
@@ -977,7 +977,7 @@ func (api *API) maybeInjectSubAgentIntoContainerLocked(ctx context.Context, dc c
977977
)
978978

979979
// Check if subagent already exists for this devcontainer.
980-
recreateSubAgent:=false
980+
maybeRecreateSubAgent:=false
981981
proc,injected:=api.injectedSubAgentProcs[dc.WorkspaceFolder]
982982
ifinjected {
983983
ifproc.containerID==container.ID&&proc.ctx.Err()==nil {
@@ -992,12 +992,15 @@ func (api *API) maybeInjectSubAgentIntoContainerLocked(ctx context.Context, dc c
992992
logger.Debug(ctx,"container ID changed, injecting subagent into new container",
993993
slog.F("old_container_id",proc.containerID),
994994
)
995-
recreateSubAgent=true
995+
maybeRecreateSubAgent=proc.agent.ID!=uuid.Nil
996996
}
997997

998998
// Container ID changed or the subagent process is not running,
999999
// stop the existing subagent context to replace it.
10001000
proc.stop()
1001+
}else {
1002+
// Set SubAgent defaults.
1003+
proc.agent.OperatingSystem="linux"// Assuming Linux for devcontainers.
10011004
}
10021005

10031006
// Prepare the subAgentProcess to be used when running the subagent.
@@ -1090,36 +1093,29 @@ func (api *API) maybeInjectSubAgentIntoContainerLocked(ctx context.Context, dc c
10901093
// logger.Warn(ctx, "set CAP_NET_ADMIN on agent binary failed", slog.Error(err))
10911094
// }
10921095

1093-
// Detect workspace folder by executing `pwd` in the container.
1094-
// NOTE(mafredri): This is a quick and dirty way to detect the
1095-
// workspace folder inside the container. In the future we will
1096-
// rely more on `devcontainer read-configuration`.
1097-
varpwdBuf bytes.Buffer
1098-
err=api.dccli.Exec(ctx,dc.WorkspaceFolder,dc.ConfigPath,"pwd", []string{},
1099-
WithExecOutput(&pwdBuf,io.Discard),
1100-
WithExecContainerID(container.ID),
1101-
)
1102-
iferr!=nil {
1103-
returnxerrors.Errorf("check workspace folder in container: %w",err)
1104-
}
1105-
directory:=strings.TrimSpace(pwdBuf.String())
1106-
ifdirectory=="" {
1107-
logger.Warn(ctx,"detected workspace folder is empty, using default workspace folder",
1108-
slog.F("default_workspace_folder",DevcontainerDefaultContainerWorkspaceFolder),
1096+
subAgentConfig:=proc.agent.CloneConfig(dc)
1097+
ifproc.agent.ID==uuid.Nil||maybeRecreateSubAgent {
1098+
// Detect workspace folder by executing `pwd` in the container.
1099+
// NOTE(mafredri): This is a quick and dirty way to detect the
1100+
// workspace folder inside the container. In the future we will
1101+
// rely more on `devcontainer read-configuration`.
1102+
varpwdBuf bytes.Buffer
1103+
err=api.dccli.Exec(ctx,dc.WorkspaceFolder,dc.ConfigPath,"pwd", []string{},
1104+
WithExecOutput(&pwdBuf,io.Discard),
1105+
WithExecContainerID(container.ID),
11091106
)
1110-
directory=DevcontainerDefaultContainerWorkspaceFolder
1111-
}
1112-
1113-
ifproc.agent.ID!=uuid.Nil&&recreateSubAgent {
1114-
logger.Debug(ctx,"deleting existing subagent for recreation",slog.F("agent_id",proc.agent.ID))
1115-
client:=*api.subAgentClient.Load()
1116-
err=client.Delete(ctx,proc.agent.ID)
11171107
iferr!=nil {
1118-
returnxerrors.Errorf("delete existing subagent failed: %w",err)
1108+
returnxerrors.Errorf("check workspace folder in container: %w",err)
11191109
}
1120-
proc.agent=SubAgent{}
1121-
}
1122-
ifproc.agent.ID==uuid.Nil {
1110+
directory:=strings.TrimSpace(pwdBuf.String())
1111+
ifdirectory=="" {
1112+
logger.Warn(ctx,"detected workspace folder is empty, using default workspace folder",
1113+
slog.F("default_workspace_folder",DevcontainerDefaultContainerWorkspaceFolder),
1114+
)
1115+
directory=DevcontainerDefaultContainerWorkspaceFolder
1116+
}
1117+
subAgentConfig.Directory=directory
1118+
11231119
displayAppsMap:=map[codersdk.DisplayApp]bool{
11241120
// NOTE(DanielleMaywood):
11251121
// We use the same defaults here as set in terraform-provider-coder.
@@ -1138,6 +1134,13 @@ func (api *API) maybeInjectSubAgentIntoContainerLocked(ctx context.Context, dc c
11381134

11391135
for_,customization:=rangecoderCustomization {
11401136
forapp,enabled:=rangecustomization.DisplayApps {
1137+
if_,ok:=displayAppsMap[app];!ok {
1138+
logger.Warn(ctx,"unknown display app in devcontainer customization, ignoring",
1139+
slog.F("app",app),
1140+
slog.F("enabled",enabled),
1141+
)
1142+
continue
1143+
}
11411144
displayAppsMap[app]=enabled
11421145
}
11431146
}
@@ -1149,26 +1152,41 @@ func (api *API) maybeInjectSubAgentIntoContainerLocked(ctx context.Context, dc c
11491152
displayApps=append(displayApps,app)
11501153
}
11511154
}
1155+
slices.Sort(displayApps)
11521156

1157+
subAgentConfig.DisplayApps=displayApps
1158+
}
1159+
1160+
deleteSubAgent:=proc.agent.ID!=uuid.Nil&&maybeRecreateSubAgent&&!proc.agent.EqualConfig(subAgentConfig)
1161+
ifdeleteSubAgent {
1162+
logger.Debug(ctx,"deleting existing subagent for recreation",slog.F("agent_id",proc.agent.ID))
1163+
client:=*api.subAgentClient.Load()
1164+
err=client.Delete(ctx,proc.agent.ID)
1165+
iferr!=nil {
1166+
returnxerrors.Errorf("delete existing subagent failed: %w",err)
1167+
}
1168+
proc.agent=SubAgent{}// Clear agent to signal that we need to create a new one.
1169+
}
1170+
1171+
ifproc.agent.ID==uuid.Nil {
11531172
logger.Debug(ctx,"creating new subagent",
1154-
slog.F("directory",directory),
1155-
slog.F("display_apps",displayApps),
1173+
slog.F("directory",subAgentConfig.Directory),
1174+
slog.F("display_apps",subAgentConfig.DisplayApps),
11561175
)
11571176

11581177
// Create new subagent record in the database to receive the auth token.
11591178
client:=*api.subAgentClient.Load()
1160-
proc.agent,err=client.Create(ctx,SubAgent{
1161-
Name:dc.Name,
1162-
Directory:directory,
1163-
OperatingSystem:"linux",// Assuming Linux for devcontainers.
1164-
Architecture:arch,
1165-
DisplayApps:displayApps,
1166-
})
1179+
newSubAgent,err:=client.Create(ctx,subAgentConfig)
11671180
iferr!=nil {
11681181
returnxerrors.Errorf("create subagent failed: %w",err)
11691182
}
1183+
proc.agent=newSubAgent
11701184

11711185
logger.Info(ctx,"created new subagent",slog.F("agent_id",proc.agent.ID))
1186+
}else {
1187+
logger.Debug(ctx,"subagent already exists, skipping recreation",
1188+
slog.F("agent_id",proc.agent.ID),
1189+
)
11721190
}
11731191

11741192
api.mu.Lock()// Re-lock to update the agent.

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp