Block server destruction while linked to an active beta
Protect individual, bulk, and queued removals and rebuilds until beta closure. Recheck ownership before teardown and reject beta admission during pending or unresolved destruction. Fixes #36
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import { maintenanceAllowed } from '../maintenance/policies.js';
|
||||
import { db } from '../db/index.js';
|
||||
import { komodoConfigured, rconConfigured } from '../config.js';
|
||||
import { getServer } from '../fleet/servers.js';
|
||||
import { activeBetaRemovalBlocker, getServer } from '../fleet/servers.js';
|
||||
import { beginDeployment, deploymentStage, finishDeployment, recordDeploymentEvent } from './history.js';
|
||||
import { queueRebuildServer } from './instances.js';
|
||||
import { restartRequestInFlight } from './restarts.js';
|
||||
@@ -122,6 +122,8 @@ export function requestLifecycle(server: string, action: RuntimeAction) {
|
||||
if (!runtimeActions.includes(action)) return { ok: false as const, status: 400, error: 'Choose start, restart, rebuild, or stop.' };
|
||||
if (!komodoConfigured() || !rconConfigured()) return { ok: false as const, status: 503, error: 'Configure Komodo and RCON before provisioning.' };
|
||||
return db().transaction(() => {
|
||||
const blocker = action === 'rebuild' ? activeBetaRemovalBlocker(server) : null;
|
||||
if (blocker) return { ok: false as const, status: 409, error: blocker };
|
||||
const existing = db().prepare(`SELECT id, action FROM server_deployments WHERE server = ?
|
||||
AND server_deleted_at IS NULL
|
||||
AND state IN ('queued','waiting','running','awaiting-health') ORDER BY rowid DESC LIMIT 1`).get(server) as { id: string; action: string } | undefined;
|
||||
@@ -136,7 +138,7 @@ export function requestLifecycle(server: string, action: RuntimeAction) {
|
||||
const result = queueRebuildServer(server);
|
||||
if (result.ok) db().prepare("UPDATE servers SET desired_state = 'running' WHERE name = ?").run(server);
|
||||
return result.ok ? { ok: true as const, deploymentId: result.deploymentId }
|
||||
: { ok: false as const, status: 400, error: result.message };
|
||||
: { ok: false as const, status: result.kind === 'conflict' ? 409 : 400, error: result.message };
|
||||
}
|
||||
const id = beginDeployment(server, action);
|
||||
db().prepare('UPDATE servers SET desired_state = ? WHERE name = ?').run(action === 'stop' ? 'stopped' : 'running', server);
|
||||
@@ -170,7 +172,7 @@ function queueWatchdogAction(server: string, action: 'restart' | 'rebuild', inci
|
||||
let id: string;
|
||||
if (action === 'rebuild') {
|
||||
const result = queueRebuildServer(server, `watchdog:${incidentId}`);
|
||||
if (!result.ok) return { ok: false, status: 400, error: result.message };
|
||||
if (!result.ok) return { ok: false, status: result.kind === 'conflict' ? 409 : 400, error: result.message };
|
||||
id = result.deploymentId;
|
||||
} else {
|
||||
id = beginDeployment(server, action, `watchdog:${incidentId}`);
|
||||
|
||||
Reference in New Issue
Block a user