dragonflight/services/mam-api/src/routes/system.js

101 lines
3.4 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import express from 'express';
import http from 'node:http';
import { requireAuth } from '../middleware/auth.js';
const router = express.Router();
router.use(requireAuth);
const DOCKER_SOCKET = '/var/run/docker.sock';
const COMPOSE_PROJECT = (process.env.DOCKER_NETWORK || 'wild-dragon_wild-dragon').split('_')[0];
function dockerGet(path) {
return new Promise((resolve, reject) => {
const req = http.request(
{ socketPath: DOCKER_SOCKET, path, method: 'GET' },
(res) => {
let data = '';
res.on('data', chunk => { data += chunk; });
res.on('end', () => {
try { resolve({ status: res.statusCode, body: JSON.parse(data) }); }
catch { resolve({ status: res.statusCode, body: data }); }
});
}
);
req.on('error', reject);
req.end();
});
}
function dockerPost(path) {
return new Promise((resolve, reject) => {
const req = http.request(
{ socketPath: DOCKER_SOCKET, path, method: 'POST', headers: { 'Content-Length': '0' } },
(res) => {
res.resume();
res.on('end', () => resolve({ status: res.statusCode }));
}
);
req.on('error', reject);
req.end();
});
}
// GET /containers list containers for this compose project
router.get('/containers', async (req, res, next) => {
try {
const r = await dockerGet('/containers/json?all=1');
if (r.status !== 200) return res.status(502).json({ error: 'Docker API error', code: r.status });
const containers = r.body
.filter(c => {
const labels = c.Labels || {};
// Match by compose project label; fall back to network name
if (labels['com.docker.compose.project'] === COMPOSE_PROJECT) return true;
return Object.keys(c.NetworkSettings?.Networks || {}).some(n => n.includes(COMPOSE_PROJECT));
})
.map(c => ({
id: c.Id.slice(0, 12),
name: (c.Names[0] || '').replace(/^\//, ''),
image: c.Image,
state: c.State,
status: c.Status,
created: c.Created,
service: (c.Labels || {})['com.docker.compose.service'] || '',
ports: (c.Ports || [])
.filter(p => p.PublicPort)
.map(p => `${p.PublicPort}:${p.PrivatePort}/${p.Type}`)
.join(', '),
}));
res.json(containers);
} catch (err) { next(err); }
});
// POST /containers/:id/restart
router.post('/containers/:id/restart', async (req, res, next) => {
try {
const r = await dockerPost(`/containers/${req.params.id}/restart`);
if (r.status !== 204) return res.status(502).json({ error: 'Failed to restart', code: r.status });
res.json({ ok: true });
} catch (err) { next(err); }
});
// POST /containers/:id/stop
router.post('/containers/:id/stop', async (req, res, next) => {
try {
const r = await dockerPost(`/containers/${req.params.id}/stop`);
if (r.status !== 204 && r.status !== 304) return res.status(502).json({ error: 'Failed to stop', code: r.status });
res.json({ ok: true });
} catch (err) { next(err); }
});
// POST /containers/:id/start
router.post('/containers/:id/start', async (req, res, next) => {
try {
const r = await dockerPost(`/containers/${req.params.id}/start`);
if (r.status !== 204 && r.status !== 304) return res.status(502).json({ error: 'Failed to start', code: r.status });
res.json({ ok: true });
} catch (err) { next(err); }
});
export default router;