fix(monitoring): repair silent-false-positive update badge + auto-update scheduling
Customer container status checks looked up containers by an exact expected name. When a docker compose recreate got interrupted (e.g. a hung command previously killed the whole update-all batch on timeout), Compose could leave the old container renamed with a random hash prefix instead of removed. The exact-name lookup then found nothing, returned None, and that silently counted as "up to date" (green "Aktuell") instead of surfacing as unknown — affecting 5 customers on the appliance whose containers were actually still running under orphaned names. - _run_cmd no longer raises on subprocess timeout, so one stuck customer can't abort the rest of a batch update - repair_container_naming() self-heals orphaned hash-renamed containers by renaming them back before every status check and before recreate - update-all loop now catches per-customer exceptions instead of aborting - status responses expose "unknown" separately from "needs_update" so the UI shows a distinct grey badge instead of a false-positive green one - new settings: automatic daily update check (on/off + time), with an independent toggle for whether it also auto-recreates customer containers
This commit is contained in:
@@ -641,6 +641,33 @@
|
||||
<i class="bi bi-cloud-download me-1"></i><span data-i18n="settings.pullImages">Pull from Docker Hub</span>
|
||||
</button>
|
||||
<span id="pull-images-settings-status" class="ms-2 text-muted small"></span>
|
||||
<hr>
|
||||
<h6 data-i18n="monitoring.autoUpdateTitle">Automatic Updates</h6>
|
||||
<p class="text-muted small" data-i18n="monitoring.autoUpdateHint">Automatically checks for new NetBird images daily at the chosen time.</p>
|
||||
<form id="settings-auto-update-form">
|
||||
<div class="form-check mb-3">
|
||||
<input class="form-check-input" type="checkbox" id="cfg-auto-update-check-enabled">
|
||||
<label class="form-check-label" for="cfg-auto-update-check-enabled" data-i18n="monitoring.autoUpdateCheckEnabled">Enable automatic update check</label>
|
||||
</div>
|
||||
<div class="row g-3 align-items-end">
|
||||
<div class="col-md-3">
|
||||
<label class="form-label" data-i18n="monitoring.autoUpdateCheckTime">Daily check time</label>
|
||||
<input type="time" class="form-control" id="cfg-auto-update-check-time" value="03:00">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-check mt-3">
|
||||
<input class="form-check-input" type="checkbox" id="cfg-auto-update-apply-enabled">
|
||||
<label class="form-check-label" for="cfg-auto-update-apply-enabled" data-i18n="monitoring.autoUpdateApplyEnabled">Automatically update customer containers after check</label>
|
||||
<div class="form-text" data-i18n="monitoring.autoUpdateApplyHint">When enabled, all customer containers are automatically recreated after a new image is found (services briefly restart). When disabled, only the images are pulled — updating customers stays a manual step.</div>
|
||||
</div>
|
||||
<div class="mt-3 small text-muted">
|
||||
<span data-i18n="monitoring.autoUpdateLastRun">Last automatic check</span>:
|
||||
<span id="auto-update-last-run">-</span>
|
||||
</div>
|
||||
<div class="mt-3">
|
||||
<button type="submit" class="btn btn-primary btn-sm"><i class="bi bi-save me-1"></i><span data-i18n="monitoring.saveAutoUpdateSettings">Save Automation</span></button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+25
-1
@@ -940,6 +940,13 @@ async function loadSettings() {
|
||||
document.getElementById('cfg-relay-image').value = cfg.netbird_relay_image || '';
|
||||
document.getElementById('cfg-dashboard-image').value = cfg.netbird_dashboard_image || '';
|
||||
|
||||
document.getElementById('cfg-auto-update-check-enabled').checked = cfg.auto_update_check_enabled || false;
|
||||
document.getElementById('cfg-auto-update-check-time').value = cfg.auto_update_check_time || '03:00';
|
||||
document.getElementById('cfg-auto-update-apply-enabled').checked = cfg.auto_update_apply_enabled || false;
|
||||
document.getElementById('auto-update-last-run').textContent = cfg.auto_update_last_run_at
|
||||
? new Date(cfg.auto_update_last_run_at).toLocaleString()
|
||||
: t('monitoring.autoUpdateNever');
|
||||
|
||||
// Branding tab
|
||||
document.getElementById('cfg-branding-name').value = cfg.branding_name || '';
|
||||
document.getElementById('cfg-branding-subtitle').value = cfg.branding_subtitle || '';
|
||||
@@ -1058,6 +1065,21 @@ document.getElementById('settings-images-form').addEventListener('submit', async
|
||||
}
|
||||
});
|
||||
|
||||
// Automatic update settings form
|
||||
document.getElementById('settings-auto-update-form').addEventListener('submit', async (e) => {
|
||||
e.preventDefault();
|
||||
try {
|
||||
await api('PUT', '/settings/system', {
|
||||
auto_update_check_enabled: document.getElementById('cfg-auto-update-check-enabled').checked,
|
||||
auto_update_check_time: document.getElementById('cfg-auto-update-check-time').value || '03:00',
|
||||
auto_update_apply_enabled: document.getElementById('cfg-auto-update-apply-enabled').checked,
|
||||
});
|
||||
showSettingsAlert('success', t('messages.imageSettingsSaved'));
|
||||
} catch (err) {
|
||||
showSettingsAlert('danger', t('errors.failed', { error: err.message }));
|
||||
}
|
||||
});
|
||||
|
||||
// Test NPM connection
|
||||
async function testNpmConnection() {
|
||||
const spinner = document.getElementById('npm-test-spinner');
|
||||
@@ -1807,7 +1829,9 @@ async function checkImageUpdates() {
|
||||
: data.customer_status.map(c => {
|
||||
const badge = c.needs_update
|
||||
? `<span class="badge bg-warning text-dark">${t('monitoring.needsUpdate')}</span>`
|
||||
: `<span class="badge bg-success">${t('monitoring.upToDate')}</span>`;
|
||||
: c.unknown
|
||||
? `<span class="badge bg-secondary" title="${t('monitoring.statusUnknownHint')}">${t('monitoring.statusUnknown')}</span>`
|
||||
: `<span class="badge bg-success">${t('monitoring.upToDate')}</span>`;
|
||||
const updateBtn = c.needs_update
|
||||
? `<button class="btn btn-sm btn-outline-warning ms-2 btn-update-customer" onclick="updateCustomerImages(${c.customer_id})"
|
||||
title="${t('monitoring.updateCustomer')}"><i class="bi bi-arrow-repeat"></i></button>`
|
||||
|
||||
+12
-1
@@ -420,6 +420,17 @@
|
||||
"updating": "Wird aktualisiert…",
|
||||
"updateAllProgress": "Kunden-Container werden nacheinander aktualisiert — bitte warten…",
|
||||
"pulling": "Wird geladen…",
|
||||
"pullStartedShort": "Download im Hintergrund gestartet."
|
||||
"pullStartedShort": "Download im Hintergrund gestartet.",
|
||||
"statusUnknown": "Unbekannt",
|
||||
"statusUnknownHint": "Container konnte nicht eindeutig zugeordnet werden (z. B. nicht gestartet). Kein verifiziertes \"Aktuell\".",
|
||||
"autoUpdateTitle": "Automatische Aktualisierung",
|
||||
"autoUpdateHint": "Prüft täglich zur gewählten Uhrzeit automatisch auf neue NetBird-Images.",
|
||||
"autoUpdateCheckEnabled": "Automatische Update-Prüfung aktivieren",
|
||||
"autoUpdateCheckTime": "Uhrzeit der täglichen Prüfung",
|
||||
"autoUpdateApplyEnabled": "Kunden-Container nach Prüfung automatisch aktualisieren",
|
||||
"autoUpdateApplyHint": "Wenn aktiviert, werden nach einer gefundenen Aktualisierung automatisch alle Kunden-Container neu erstellt (kurzer Neustart der Dienste). Wenn deaktiviert, werden nur die Images geladen — die Aktualisierung der Kunden erfolgt weiterhin manuell.",
|
||||
"autoUpdateLastRun": "Letzte automatische Prüfung",
|
||||
"autoUpdateNever": "Noch nie ausgeführt",
|
||||
"saveAutoUpdateSettings": "Automatisierung speichern"
|
||||
}
|
||||
}
|
||||
+12
-1
@@ -327,7 +327,18 @@
|
||||
"updating": "Updating…",
|
||||
"updateAllProgress": "Updating customer containers one by one — please wait…",
|
||||
"pulling": "Pulling…",
|
||||
"pullStartedShort": "Pull started in background."
|
||||
"pullStartedShort": "Pull started in background.",
|
||||
"statusUnknown": "Unknown",
|
||||
"statusUnknownHint": "Container could not be matched reliably (e.g. not running). Not a verified \"up to date\".",
|
||||
"autoUpdateTitle": "Automatic Updates",
|
||||
"autoUpdateHint": "Automatically checks for new NetBird images daily at the chosen time.",
|
||||
"autoUpdateCheckEnabled": "Enable automatic update check",
|
||||
"autoUpdateCheckTime": "Daily check time",
|
||||
"autoUpdateApplyEnabled": "Automatically update customer containers after check",
|
||||
"autoUpdateApplyHint": "When enabled, all customer containers are automatically recreated after a new image is found (services briefly restart). When disabled, only the images are pulled — updating customers stays a manual step.",
|
||||
"autoUpdateLastRun": "Last automatic check",
|
||||
"autoUpdateNever": "Never run",
|
||||
"saveAutoUpdateSettings": "Save Automation"
|
||||
},
|
||||
"userModal": {
|
||||
"title": "New User",
|
||||
|
||||
Reference in New Issue
Block a user