59 lines
2.1 KiB
TypeScript
59 lines
2.1 KiB
TypeScript
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;
|
|
}
|