64 lines
1.7 KiB
TypeScript
64 lines
1.7 KiB
TypeScript
import http from 'node:http';
|
|
import { RESTARTABLE_SERVICE_CONTAINERS } from '@/lib/ops-stack';
|
|
|
|
const DOCKER_SOCKET_PATH = '/var/run/docker.sock';
|
|
|
|
function dockerRequest(
|
|
method: string,
|
|
path: string,
|
|
body?: string
|
|
): Promise<{ statusCode: number; body: string }> {
|
|
return new Promise((resolve, reject) => {
|
|
const req = http.request(
|
|
{
|
|
socketPath: DOCKER_SOCKET_PATH,
|
|
path,
|
|
method,
|
|
headers: body
|
|
? {
|
|
'Content-Type': 'application/json',
|
|
'Content-Length': Buffer.byteLength(body),
|
|
}
|
|
: undefined,
|
|
},
|
|
res => {
|
|
let data = '';
|
|
res.setEncoding('utf8');
|
|
res.on('data', chunk => {
|
|
data += chunk;
|
|
});
|
|
res.on('end', () => {
|
|
resolve({
|
|
statusCode: res.statusCode ?? 500,
|
|
body: data,
|
|
});
|
|
});
|
|
}
|
|
);
|
|
|
|
req.on('error', reject);
|
|
if (body) {
|
|
req.write(body);
|
|
}
|
|
req.end();
|
|
});
|
|
}
|
|
|
|
export function isRestartableService(serviceId: string): boolean {
|
|
return Boolean(RESTARTABLE_SERVICE_CONTAINERS[serviceId]);
|
|
}
|
|
|
|
export async function restartServiceContainer(serviceId: string): Promise<{ container: string }> {
|
|
const container = RESTARTABLE_SERVICE_CONTAINERS[serviceId];
|
|
if (!container) {
|
|
throw new Error('Service is not restartable from admin ops');
|
|
}
|
|
|
|
const response = await dockerRequest('POST', `/containers/${encodeURIComponent(container)}/restart?t=10`);
|
|
if (![204, 304].includes(response.statusCode)) {
|
|
throw new Error(response.body || `Docker restart failed with status ${response.statusCode}`);
|
|
}
|
|
|
|
return { container };
|
|
}
|