fix(backup): send host backup notifications over HTTPS when the Monitor uses it

This commit is contained in:
MacRimi
2026-10-06 17:26:55 +02:00
parent c6b2b74bf0
commit b4f4d98e85
3 changed files with 70 additions and 3 deletions
@@ -0,0 +1,58 @@
"""A host backup and a finished restore tell the Monitor on its own port,
over HTTPS once the Monitor has a certificate."""
from pathlib import Path
import subprocess
import tempfile
from unittest import TestCase
ROOT = Path(__file__).resolve().parents[3]
LIBRARY = ROOT / 'scripts/backup_restore/lib_host_backup_common.sh'
POSTBOOT = ROOT / 'scripts/backup_restore/apply_cluster_postboot.sh'
SETTING = '/etc/proxmenux/ssl_config.json'
def function(text, name):
start = text.index(name + '() {')
return text[start:text.index('\n}\n', start) + 3]
class BackupNotifyHttps(TestCase):
def address(self, setting):
with tempfile.TemporaryDirectory() as folder:
path = Path(folder) / 'ssl_config.json'
if setting is not None:
path.write_text(setting)
body = function(LIBRARY.read_text(), 'hb_notify_lifecycle').replace(SETTING, str(path))
# The function silences curl, so the stub writes the address it was given.
called = Path(folder) / 'called'
script = (f'curl() {{ printf "%s" "${{@: -1}}" > {called}; }}\n' + body
+ 'HB_NOTIFY_JOB_ID=job1 hb_notify_lifecycle complete\n')
result = subprocess.run(['/bin/bash', '--noprofile', '--norc', '-c', script],
capture_output=True, text=True, timeout=10)
self.assertEqual(result.returncode, 0, result.stderr)
return called.read_text()
def test_plain_http_while_the_monitor_has_no_certificate(self):
expected = 'http://127.0.0.1:8008/api/notifications/webhook'
self.assertEqual(self.address(None), expected)
self.assertEqual(self.address('{"enabled": false}'), expected)
def test_https_once_the_monitor_has_a_certificate(self):
self.assertEqual(self.address('{"enabled": true, "source": "proxmox"}'),
'https://127.0.0.1:8008/api/notifications/webhook')
def test_the_finished_restore_follows_the_same_setting(self):
source = POSTBOOT.read_text()
self.assertIn('"${NOTIFY_SCHEME}://127.0.0.1:8008/api/internal/restore-event"', source)
self.assertNotIn('"http://127.0.0.1:8008/api/internal/restore-event"', source)
check = source[source.index('NOTIFY_SCHEME="http"'):source.index('NOTIFY_HTTP=$(curl')]
with tempfile.TemporaryDirectory() as folder:
path = Path(folder) / 'ssl_config.json'
for setting, expected in (('{"enabled": true}', 'https'), ('{"enabled":false}', 'http'), (None, 'http')):
path.unlink(missing_ok=True)
if setting is not None:
path.write_text(setting)
result = subprocess.run(['/bin/bash', '--noprofile', '--norc', '-c',
check.replace(SETTING, str(path)) + '\necho "$NOTIFY_SCHEME"'],
capture_output=True, text=True, timeout=10)
self.assertEqual(result.stdout.strip(), expected, setting)