Admin: Spieldateien auf allen Hosts per SteamCMD aktualisieren, mit Prozentanzeige

Ein kurzlebiger Container je Host aktualisiert CS2 im Spieldateien-Volume. Hosts mit
laufenden Servern werden ausgelassen (erzwingbar), während des Updates startet dort
kein neuer Server. Fertig nur, wenn Steam die App als vollständig installiert meldet.
This commit is contained in:
mregosar committed 2026-11-01 18:22:23 +01:00
1 parent 2c57b8c170
commit 3c5a9b4162
7 files changed
+281 -5

No files matched your search

+30
View File
@@ -104,6 +104,7 @@ export function createAdminRouter({ service, manager, config, settings, knife, p
editable: !!manager.adapter.setHosts,
image: config.docker.image,
pull: manager.adapter.pullStatus?.() ?? null,
files: manager.adapter.filesStatus?.() ?? null,
});
router.get('/docker-hosts', requireAdmin, wrap(() => hostView()));
router.put('/docker-hosts', requireAdmin, wrap((req) => {
@@ -119,6 +120,35 @@ export function createAdminRouter({ service, manager, config, settings, knife, p
return hostView();
}));
// Image auf allen Hosts neu laden. Läuft im Hintergrund, Stand über GET /docker-hosts.
// Spieldateien auf allen Hosts per SteamCMD aktualisieren. Hosts mit laufenden Servern werden ausgelassen,
// außer mit { force: true }. Läuft im Hintergrund, Stand über GET /docker-hosts.
router.post('/docker-hosts/update-files', requireAdmin, wrap((req) => {
if (!manager.adapter.updateGameFiles) throw new HttpError(409, 'Nur mit dem Docker-Adapter möglich', 'unsupported');
if (manager.adapter.filesStatus().running) throw new HttpError(409, 'Die Spieldateien werden bereits aktualisiert', 'busy');
const skip = new Map();
if (!req.body?.force) {
const byAddress = new Map(manager.adapter.hosts.map((h) => [h.publicHost, h.name]));
const busy = new Map();
for (const s of manager.activeServers()) {
const name = s.hostName ?? byAddress.get(s.host);
if (name) busy.set(name, (busy.get(name) ?? 0) + 1);
}
for (const k of knife.rows()) {
if (!k.handle) continue;
let name = byAddress.get(k.host);
try {
name = JSON.parse(k.handle).hostName ?? name;
} catch {
// kaputter Handle: Adresse reicht
}
if (name) busy.set(name, (busy.get(name) ?? 0) + 1);
}
for (const [name, n] of busy) skip.set(name, `ausgelassen: ${n} laufende${n === 1 ? 'r' : ''} Server`);
}
manager.adapter.updateGameFiles({ skip }).catch(() => {});
return hostView();
}));
router.post('/docker-hosts/pull', requireAdmin, wrap(() => {
if (!manager.adapter.pullImage) throw new HttpError(409, 'Nur mit dem Docker-Adapter möglich', 'unsupported');
if (manager.adapter.pullStatus().running) throw new HttpError(409, 'Das Image wird bereits aktualisiert', 'busy');