Track E: recreate, system prune, Hub search, swarm secrets/configs
CI / test (push) Successful in 10m3s

Investigate Docker/Portainer gaps and ship high-value ops: recreate
container, system prune + builder prune UI, Docker Hub search in
pull modal, Swarm secrets/configs tables. Update roadmap Track E/F.
This commit is contained in:
2026-07-10 23:48:30 -04:00
parent 869ba6a932
commit b62bcd697e
10 changed files with 490 additions and 92 deletions
+45
View File
@@ -58,6 +58,51 @@ export function registerSystemHandlers(session) {
return { type: 'systemDf', data, success: true }
})
/**
* Docker system prune (Portainer-style "clean unused data").
* @param {{ volumes?: boolean, all?: boolean }} args
*/
session.respond('systemPrune', async (args = {}) => {
const volumes = Boolean(args.volumes)
const all = Boolean(args.all)
let data = null
if (typeof docker.pruneSystem === 'function') {
data = await docker.pruneSystem({ volumes, all })
} else {
// Fallback: dial Engine /system/prune directly
data = await new Promise((resolve, reject) => {
const qs = new URLSearchParams()
if (volumes) qs.set('volumes', '1')
if (all) qs.set('all', '1')
const path = `/system/prune${qs.toString() ? `?${qs}` : ''}`
docker.modem.dial(
{
path,
method: 'POST',
statusCodes: {
200: true,
500: 'server error',
},
},
(err, result) => (err ? reject(err) : resolve(result))
)
})
}
logger.info('systemPrune completed', {
volumes,
all,
peerId: session.id?.slice?.(0, 12),
})
return {
success: true,
type: 'systemPrune',
message: volumes
? 'System pruned (including unused volumes)'
: 'System pruned (containers, networks, images; volumes kept)',
data,
}
})
session.respond('getMetrics', async () => {
return getMetricsSnapshot({ peerCount: peers.size })
})