Two bugs fixed:
1. calendar_manager and wireguard_manager (port-only) called
_restart_container immediately in apply_config, bypassing the pending
restart banner and restarting the container before the docker port
binding in .env was updated — leaving the service broken until the
banner was applied manually. apply_config now only updates the config
file (radicale.conf / wg0.conf); the docker compose restart happens
via the banner as intended.
2. Port change detection in update_config used `if old_val is not None`
to guard against triggering on unchanged values. When a service's port
was never explicitly saved (first time), old_val was None, so the
pending restart was never queued. Fix: fall back to PORT_DEFAULTS[key]
so the comparison is always against the effective current value.
Add TestPortChangeDetection (5 tests) covering first-save and multi-service
accumulation cases.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Covers _set_pending_restart (accumulation, wildcard merge, no duplicates),
_clear_pending_restart, _collect_service_ports (all service port mappings),
GET /api/config/pending (containers field), and DELETE /api/config/pending
(cancel — clears state, idempotent, verified via follow-up GET).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>