feat: Tailscale sync jobs
Adds a background job system that polls the Tailscale API on a configurable interval and syncs tailscale status and IPs to instances by hostname match. - New config table (key/value) in SQLite for persistent server-side settings - New server/jobs.js: runTailscaleSync + restartJobs scheduler - GET/PUT /api/config — read and write Tailscale settings; API key masked as **REDACTED** on GET - POST /api/jobs/tailscale/run — immediate manual sync - Settings modal: new Tailscale Sync section with enable toggle, tailnet, API key, poll interval, Save + Run Now buttons, last-run status Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
17
server/db.js
17
server/db.js
@@ -53,6 +53,11 @@ function createSchema() {
|
||||
changed_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_history_vmid ON instance_history(vmid);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS config (
|
||||
key TEXT PRIMARY KEY,
|
||||
value TEXT NOT NULL DEFAULT ''
|
||||
);
|
||||
`);
|
||||
}
|
||||
|
||||
@@ -187,6 +192,18 @@ export function getAllHistory() {
|
||||
return db.prepare('SELECT * FROM instance_history ORDER BY vmid, changed_at').all();
|
||||
}
|
||||
|
||||
export function getConfig(key, defaultVal = '') {
|
||||
const row = db.prepare('SELECT value FROM config WHERE key = ?').get(key);
|
||||
return row ? row.value : defaultVal;
|
||||
}
|
||||
|
||||
export function setConfig(key, value) {
|
||||
db.prepare(
|
||||
`INSERT INTO config (key, value) VALUES (?, ?)
|
||||
ON CONFLICT(key) DO UPDATE SET value = excluded.value`
|
||||
).run(key, String(value));
|
||||
}
|
||||
|
||||
// ── Test helpers ──────────────────────────────────────────────────────────────
|
||||
|
||||
export function _resetForTest() {
|
||||
|
||||
Reference in New Issue
Block a user