feat(semaphore): trigger Ansible tasks at booking start/end via Semaphore

- Background scheduler checks every 30s for bookings that need setup or teardown
- Per-lab Semaphore template IDs stored on the labs table
- Booking flags track which jobs have been triggered and their Semaphore job IDs
- Immediate teardown triggered when an active booking is cancelled
- Settings UI section for Semaphore API URL, token, and project ID
- Lab template form fields for setup/teardown template IDs
- BookingDetailsModal shows live Ansible job status with manual trigger buttons
This commit is contained in:
Brückner
2026-06-05 09:39:58 +02:00
parent 11eb06c5ad
commit 70399a00ec
6 changed files with 488 additions and 24 deletions

View File

@ -89,6 +89,12 @@ function ensureColumn(table: string, column: string, ddl: string) {
ensureColumn('devices', 'checkMkUrl', "checkMkUrl TEXT NOT NULL DEFAULT ''");
ensureColumn('devices', 'cmkHostname', "cmkHostname TEXT NOT NULL DEFAULT ''");
ensureColumn('labs', 'semaphoreSetupTemplateId', "semaphoreSetupTemplateId TEXT NOT NULL DEFAULT ''");
ensureColumn('labs', 'semaphoreTeardownTemplateId', "semaphoreTeardownTemplateId TEXT NOT NULL DEFAULT ''");
ensureColumn('bookings', 'ansibleSetupTriggered', 'ansibleSetupTriggered INTEGER NOT NULL DEFAULT 0');
ensureColumn('bookings', 'ansibleTeardownTriggered', 'ansibleTeardownTriggered INTEGER NOT NULL DEFAULT 0');
ensureColumn('bookings', 'ansibleSetupJobId', "ansibleSetupJobId TEXT NOT NULL DEFAULT ''");
ensureColumn('bookings', 'ansibleTeardownJobId', "ansibleTeardownJobId TEXT NOT NULL DEFAULT ''");
// Seed default settings (INSERT OR IGNORE = only if key absent)
const _insertDefault = db.prepare('INSERT OR IGNORE INTO settings (key, value) VALUES (?, ?)');
@ -104,6 +110,10 @@ const _defaultSettings: [string, string][] = [
['checkmk_api_user', 'automation'],
['checkmk_api_secret', ''],
['checkmk_sync_interval_ms', '60000'],
['semaphore_enabled', 'false'],
['semaphore_api_url', ''],
['semaphore_api_token', ''],
['semaphore_project_id', ''],
];
for (const [k, v] of _defaultSettings) _insertDefault.run(k, v);