Retain host and server scope during investigations

This commit is contained in:
2026-10-05 19:05:07 -04:00
parent 056fbd7517
commit cd577b646c
12 changed files with 95 additions and 29 deletions
+26
View File
@@ -43,6 +43,31 @@ async function operationHistory() {
}
describe('host operation history', () => {
it('scopes counts and pages to one host or server and preserves deleted-host history', async () => {
const api = await seedHistory(90);
api.handle.prepare("UPDATE ec_host_operations SET server_name='server-one' WHERE host_id=?").run(api.first.id);
const first = api.listHostOperationHistory(1, 'all', { host: api.first.id });
const second = api.listHostOperationHistory(2, 'all', { host: api.first.id });
expect(first).toMatchObject({ total: 30, totalPages: 2 });
expect([...first.operations, ...second.operations]).toHaveLength(30);
expect(first.operations.every(operation => operation.hostId === api.first.id)).toBe(true);
expect(api.listHostOperationHistory(1, 'all', { server: 'server-one' })).toEqual(first);
expect(api.listHostOperationHistory(1, 'all', { host: api.second.id, server: 'server-one' }).total).toBe(0);
expect(api.listHostOperationHistory(1, 'all', { host: api.deleted.id }).operations.every(operation => operation.hostName === null)).toBe(true);
const { GET } = await import('../../src/routes/api/hosts/operations/+server.js');
const response = GET({ request: new Request(`https://ec.test/api/hosts/operations?filter=all&host=${api.first.id}&page=2`) });
expect(await response.json()).toEqual(second);
});
it('applies host scope to failures as well as ordinary actions', async () => {
const api = await operationHistory();
const first = api.add('instance.restart');
const other = api.queueHostOperation(api.second.id, 'instance.inspect', {});
api.reportHostOperationStatus(api.second.id, other.id, { state: 'failed', error: 'Unreachable' });
expect(api.listHostOperationHistory(1, 'important', { host: api.first.id }).operations.map(operation => operation.id)).toEqual([first]);
expect(api.listHostOperationHistory(1, 'important', { host: api.second.id }).operations.map(operation => operation.id)).toEqual([other.id]);
});
it('pages all hosts in stable newest-first order, retaining deleted-host records', async () => {
const api = await seedHistory();
const pages = [1, 2, 3].map(page => api.listHostOperationHistory(page, 'all'));
@@ -199,6 +224,7 @@ describe('host operation history', () => {
const unsafe = api.add('files.read', { payload: { path: '../private-secret' } });
api.handle.exec(`DROP INDEX ec_host_operations_routine_history;
DROP INDEX ec_host_operations_important_history;
DROP INDEX ec_host_operations_server_history;
ALTER TABLE ec_host_operations DROP COLUMN routine;
ALTER TABLE ec_host_operations DROP COLUMN server_name;
ALTER TABLE ec_host_operations DROP COLUMN target_path;