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

Commita8ff575

Browse files
feat(agent): support deleting dev containers
1 parente7dbbcd commita8ff575

File tree

12 files changed

+523
-21
lines changed

12 files changed

+523
-21
lines changed

‎agent/agentcontainers/acmock/acmock.go‎

Lines changed: 28 additions & 0 deletions
Some generated files are not rendered by default. Learn more aboutcustomizing how changed files appear on GitHub.

‎agent/agentcontainers/api.go‎

Lines changed: 145 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import (
3232
"github.com/coder/coder/v2/agent/agentexec"
3333
"github.com/coder/coder/v2/agent/usershell"
3434
"github.com/coder/coder/v2/coderd/httpapi"
35+
"github.com/coder/coder/v2/coderd/httpapi/httperror"
3536
"github.com/coder/coder/v2/codersdk"
3637
"github.com/coder/coder/v2/codersdk/agentsdk"
3738
"github.com/coder/coder/v2/provisioner"
@@ -743,6 +744,7 @@ func (api *API) Routes() http.Handler {
743744
// /-route was dropped. We can drop the /devcontainers prefix here too.
744745
r.Route("/devcontainers/{devcontainer}",func(r chi.Router) {
745746
r.Post("/recreate",api.handleDevcontainerRecreate)
747+
r.Delete("/",api.handleDevcontainerDelete)
746748
})
747749

748750
returnr
@@ -853,26 +855,24 @@ func (api *API) updateContainers(ctx context.Context) error {
853855
listCtx,listCancel:=context.WithTimeout(ctx,defaultOperationTimeout)
854856
deferlistCancel()
855857

858+
api.mu.Lock()
859+
deferapi.mu.Unlock()
860+
856861
updated,err:=api.ccli.List(listCtx)
857862
iferr!=nil {
858863
// If the context was canceled, we hold off on clearing the
859864
// containers cache. This is to avoid clearing the cache if
860865
// the update was canceled due to a timeout. Hopefully this
861866
// will clear up on the next update.
862867
if!errors.Is(err,context.Canceled) {
863-
api.mu.Lock()
864868
api.containersErr=err
865-
api.mu.Unlock()
866869
}
867870

868871
returnxerrors.Errorf("list containers failed: %w",err)
869872
}
870873
// Clone to avoid test flakes due to data manipulation.
871874
updated.Containers=slices.Clone(updated.Containers)
872875

873-
api.mu.Lock()
874-
deferapi.mu.Unlock()
875-
876876
varpreviouslyKnownDevcontainersmap[string]codersdk.WorkspaceAgentDevcontainer
877877
iflen(api.updateChans)>0 {
878878
previouslyKnownDevcontainers=maps.Clone(api.knownDevcontainers)
@@ -1019,6 +1019,9 @@ func (api *API) processUpdatedContainersLocked(ctx context.Context, updated code
10191019
casedc.Status==codersdk.WorkspaceAgentDevcontainerStatusStarting:
10201020
continue// This state is handled by the recreation routine.
10211021

1022+
casedc.Status==codersdk.WorkspaceAgentDevcontainerStatusStopping:
1023+
continue// This state is handled by the delete routine.
1024+
10221025
casedc.Status==codersdk.WorkspaceAgentDevcontainerStatusError&& (dc.Container==nil||dc.Container.CreatedAt.Before(api.recreateErrorTimes[dc.WorkspaceFolder])):
10231026
continue// The devcontainer needs to be recreated.
10241027

@@ -1220,6 +1223,140 @@ func (api *API) getContainers() (codersdk.WorkspaceAgentListContainersResponse,
12201223
},nil
12211224
}
12221225

1226+
func (api*API)devcontainerByIDLocked(devcontainerIDstring) (codersdk.WorkspaceAgentDevcontainer,error) {
1227+
for_,knownDC:=rangeapi.knownDevcontainers {
1228+
ifknownDC.ID.String()==devcontainerID {
1229+
returnknownDC,nil
1230+
}
1231+
}
1232+
1233+
return codersdk.WorkspaceAgentDevcontainer{},httperror.NewResponseError(http.StatusNotFound, codersdk.Response{
1234+
Message:"Devcontainer not found.",
1235+
Detail:fmt.Sprintf("Could not find devcontainer with ID: %q",devcontainerID),
1236+
})
1237+
}
1238+
1239+
func (api*API)handleDevcontainerDelete(w http.ResponseWriter,r*http.Request) {
1240+
var (
1241+
ctx=r.Context()
1242+
devcontainerID=chi.URLParam(r,"devcontainer")
1243+
)
1244+
1245+
ifdevcontainerID=="" {
1246+
httpapi.Write(ctx,w,http.StatusBadRequest, codersdk.Response{
1247+
Message:"Missing devcontainer ID",
1248+
Detail:"Devcontainer ID is required to delete a devcontainer.",
1249+
})
1250+
return
1251+
}
1252+
1253+
api.mu.Lock()
1254+
1255+
dc,err:=api.devcontainerByIDLocked(devcontainerID)
1256+
iferr!=nil {
1257+
api.mu.Unlock()
1258+
httperror.WriteResponseError(ctx,w,err)
1259+
return
1260+
}
1261+
1262+
// Check if the devcontainer is currently starting - if so, we can't delete it.
1263+
ifdc.Status==codersdk.WorkspaceAgentDevcontainerStatusStarting {
1264+
api.mu.Unlock()
1265+
httpapi.Write(ctx,w,http.StatusConflict, codersdk.Response{
1266+
Message:"Devcontainer is starting",
1267+
Detail:fmt.Sprintf("Devcontainer %q is currently starting and cannot be deleted.",dc.Name),
1268+
})
1269+
return
1270+
}
1271+
1272+
// Similarly, if already stopping, don't allow another delete.
1273+
ifdc.Status==codersdk.WorkspaceAgentDevcontainerStatusStopping {
1274+
api.mu.Unlock()
1275+
httpapi.Write(ctx,w,http.StatusConflict, codersdk.Response{
1276+
Message:"Devcontainer is stopping",
1277+
Detail:fmt.Sprintf("Devcontainer %q is currently stopping.",dc.Name),
1278+
})
1279+
return
1280+
}
1281+
1282+
dc.Status=codersdk.WorkspaceAgentDevcontainerStatusStopping
1283+
api.knownDevcontainers[dc.WorkspaceFolder]=dc
1284+
api.broadcastUpdatesLocked()
1285+
1286+
// Gather the information we need before unlocking.
1287+
workspaceFolder:=dc.WorkspaceFolder
1288+
dcName:=dc.Name
1289+
varcontainerIDstring
1290+
ifdc.Container!=nil {
1291+
containerID=dc.Container.ID
1292+
}
1293+
proc,hasSubAgent:=api.injectedSubAgentProcs[workspaceFolder]
1294+
varsubAgentID uuid.UUID
1295+
ifhasSubAgent&&proc.agent.ID!=uuid.Nil {
1296+
subAgentID=proc.agent.ID
1297+
// Stop the subagent process context to ensure it stops.
1298+
proc.stop()
1299+
}
1300+
1301+
// Unlock the mutex while we perform potentially slow operations
1302+
// (network calls, docker commands) to avoid blocking other operations.
1303+
api.mu.Unlock()
1304+
1305+
// Delete the subagent if it exists.
1306+
ifsubAgentID!=uuid.Nil {
1307+
client:=*api.subAgentClient.Load()
1308+
iferr:=client.Delete(ctx,subAgentID);err!=nil {
1309+
api.logger.Error(ctx,"unable to delete agent",slog.Error(err))
1310+
1311+
httpapi.Write(ctx,w,http.StatusInternalServerError, codersdk.Response{
1312+
Message:"An internal error occurred deleting the agent",
1313+
Detail:err.Error(),
1314+
})
1315+
return
1316+
}
1317+
}
1318+
1319+
// Stop and remove the container if it exists.
1320+
ifcontainerID!="" {
1321+
iferr:=api.ccli.Stop(ctx,containerID);err!=nil {
1322+
api.logger.Error(ctx,"unable to stop container",slog.Error(err))
1323+
1324+
httpapi.Write(ctx,w,http.StatusInternalServerError, codersdk.Response{
1325+
Message:"An internal error occurred stopping the container",
1326+
Detail:err.Error(),
1327+
})
1328+
return
1329+
}
1330+
1331+
iferr:=api.ccli.Remove(ctx,containerID);err!=nil {
1332+
api.logger.Error(ctx,"unable to remove container",slog.Error(err))
1333+
1334+
httpapi.Write(ctx,w,http.StatusInternalServerError, codersdk.Response{
1335+
Message:"An internal error occurred removing the container",
1336+
Detail:err.Error(),
1337+
})
1338+
return
1339+
}
1340+
}
1341+
1342+
// Re-lock to clean up the state.
1343+
api.mu.Lock()
1344+
delete(api.devcontainerNames,dcName)
1345+
delete(api.knownDevcontainers,workspaceFolder)
1346+
delete(api.devcontainerLogSourceIDs,workspaceFolder)
1347+
delete(api.recreateSuccessTimes,workspaceFolder)
1348+
delete(api.recreateErrorTimes,workspaceFolder)
1349+
delete(api.injectedSubAgentProcs,workspaceFolder)
1350+
delete(api.usingWorkspaceFolderName,workspaceFolder)
1351+
api.broadcastUpdatesLocked()
1352+
api.mu.Unlock()
1353+
1354+
httpapi.Write(ctx,w,http.StatusInternalServerError, codersdk.Response{
1355+
Message:"An internal error occurred",
1356+
Detail:err.Error(),
1357+
})
1358+
}
1359+
12231360
// handleDevcontainerRecreate handles the HTTP request to recreate a
12241361
// devcontainer by referencing the container.
12251362
func (api*API)handleDevcontainerRecreate(w http.ResponseWriter,r*http.Request) {
@@ -1236,20 +1373,10 @@ func (api *API) handleDevcontainerRecreate(w http.ResponseWriter, r *http.Reques
12361373

12371374
api.mu.Lock()
12381375

1239-
vardc codersdk.WorkspaceAgentDevcontainer
1240-
for_,knownDC:=rangeapi.knownDevcontainers {
1241-
ifknownDC.ID.String()==devcontainerID {
1242-
dc=knownDC
1243-
break
1244-
}
1245-
}
1246-
ifdc.ID==uuid.Nil {
1376+
dc,err:=api.devcontainerByIDLocked(devcontainerID)
1377+
iferr!=nil {
12471378
api.mu.Unlock()
1248-
1249-
httpapi.Write(ctx,w,http.StatusNotFound, codersdk.Response{
1250-
Message:"Devcontainer not found.",
1251-
Detail:fmt.Sprintf("Could not find devcontainer with ID: %q",devcontainerID),
1252-
})
1379+
httperror.WriteResponseError(ctx,w,err)
12531380
return
12541381
}
12551382
ifdc.Status==codersdk.WorkspaceAgentDevcontainerStatusStarting {

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp