Add fleet action dialog with server selection

This commit is contained in:
2026-10-07 23:41:45 -04:00
parent 7e552b700a
commit 92c50e62a1
16 changed files with 284 additions and 110 deletions
+34
View File
@@ -0,0 +1,34 @@
import type { FleetServer } from '../fleet-overview.js';
import type { RuntimeAction } from '../provisioning.js';
import { applicableRuntimeActions } from './lifecycle-actions.js';
export const fleetActions = ['restart', 'start', 'stop', 'rebuild', 'destroy'] as const;
export type FleetAction = RuntimeAction | 'destroy';
export interface FleetActionFailure { server: string; error: string }
export interface FleetActionResult {
queued: { server: string; deploymentId: string }[];
failed: FleetActionFailure[];
}
export function fleetActionAvailable(server: FleetServer, action: FleetAction, now: number): boolean {
return action === 'destroy' || applicableRuntimeActions(server, now).includes(action);
}
/** Submit only the reviewed selection. Each server keeps its own durable job and result. */
export async function queueFleetAction(action: FleetAction, servers: readonly string[], request: typeof fetch = fetch): Promise<FleetActionResult> {
const result: FleetActionResult = { queued: [], failed: [] };
for (const server of new Set(servers)) {
try {
const response = action === 'destroy'
? await request(`/api/servers/${encodeURIComponent(server)}`, { method: 'DELETE' })
: await request('/api/provisioning', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ server, action }) });
const body = await response.json();
if (!response.ok || !body.deploymentId) {
result.failed.push({ server, error: body.error ?? 'Could not queue this operation.' });
} else result.queued.push({ server, deploymentId: body.deploymentId });
} catch {
result.failed.push({ server, error: 'Could not confirm whether the request was queued. Check Provisioning before trying again.' });
}
}
return result;
}