fix: silent autosave, pending dedup, domain/cell_name pending, containers access
- Settings: remove Save buttons; autosave is silent (no toast on success, error only) - Settings: loadAll() resets dirty flags to prevent stale autosave after discard - app.py: fix domain/ip_range "actually changed" check — full identity is always sent on save so these were triggering pending on every keystroke regardless - app.py: _dedup_changes handles port-change format "service field: old → new" (split on ':' not ' changed') so dns_port changed twice shows one entry - app.py: domain + cell_name changes now go through pending restart banner; apply_domain/apply_cell_name write files immediately (reload=False) and set pending; Discard restores zone files + Caddyfile to pre-change state - app.py: _set_pending_restart captures pre-change snapshot BEFORE config writes (was snapshotting after, making Discard a no-op) - app.py: is_local_request reads /proc/net/route to allow the actual Docker bridge subnet (172.0.0.0/24) which is not RFC-1918; fixes Containers page 403 - container_manager: get_container_logs raises instead of swallowing exceptions so nonexistent container returns 500+error not 200+empty Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+24
-19
@@ -5,6 +5,7 @@ Handles DNS, DHCP, and NTP functionality
|
||||
"""
|
||||
|
||||
import os
|
||||
import re
|
||||
import json
|
||||
import subprocess
|
||||
import logging
|
||||
@@ -383,8 +384,11 @@ class NetworkManager(BaseServiceManager):
|
||||
|
||||
return {'restarted': restarted, 'warnings': warnings}
|
||||
|
||||
def apply_domain(self, domain: str) -> Dict[str, Any]:
|
||||
"""Update domain across dnsmasq, Corefile, and zone file; reload DNS + DHCP."""
|
||||
def apply_domain(self, domain: str, reload: bool = True) -> Dict[str, Any]:
|
||||
"""Update domain across dnsmasq, Corefile, and zone file; reload DNS + DHCP.
|
||||
|
||||
reload=False writes config files only — use when deferring container restart.
|
||||
"""
|
||||
restarted = []
|
||||
warnings = []
|
||||
|
||||
@@ -400,8 +404,9 @@ class NetworkManager(BaseServiceManager):
|
||||
]
|
||||
with open(dhcp_conf, 'w') as f:
|
||||
f.writelines(lines)
|
||||
self._reload_dhcp_service()
|
||||
restarted.append('cell-dhcp (reloaded)')
|
||||
if reload:
|
||||
self._reload_dhcp_service()
|
||||
restarted.append('cell-dhcp (reloaded)')
|
||||
except Exception as e:
|
||||
warnings.append(f"dnsmasq domain update failed: {e}")
|
||||
|
||||
@@ -424,8 +429,6 @@ class NetworkManager(BaseServiceManager):
|
||||
dns_data = os.path.join(self.data_dir, 'dns')
|
||||
if os.path.isdir(dns_data):
|
||||
dst = os.path.join(dns_data, f'{domain}.zone')
|
||||
# Find the best source: prefer a non-target zone (old domain) so we
|
||||
# can migrate its content; fall back to the target zone itself.
|
||||
zone_files = [
|
||||
os.path.join(dns_data, f)
|
||||
for f in os.listdir(dns_data)
|
||||
@@ -443,7 +446,6 @@ class NetworkManager(BaseServiceManager):
|
||||
r'^\$ORIGIN\s+\S+', f'$ORIGIN {domain}.', zone_content, flags=re.MULTILINE)
|
||||
with open(dst, 'w') as f:
|
||||
f.write(zone_content)
|
||||
# Remove every zone file that is not the current domain's file
|
||||
for zone_path in zone_files:
|
||||
if zone_path != dst:
|
||||
try:
|
||||
@@ -453,17 +455,21 @@ class NetworkManager(BaseServiceManager):
|
||||
except Exception as e:
|
||||
warnings.append(f"zone file domain update failed: {e}")
|
||||
|
||||
# 4. Reload CoreDNS
|
||||
try:
|
||||
self._reload_dns_service()
|
||||
restarted.append('cell-dns (reloaded)')
|
||||
except Exception as e:
|
||||
warnings.append(f"CoreDNS reload failed: {e}")
|
||||
# 4. Reload CoreDNS (only when not deferring to Apply)
|
||||
if reload:
|
||||
try:
|
||||
self._reload_dns_service()
|
||||
restarted.append('cell-dns (reloaded)')
|
||||
except Exception as e:
|
||||
warnings.append(f"CoreDNS reload failed: {e}")
|
||||
|
||||
return {'restarted': restarted, 'warnings': warnings}
|
||||
|
||||
def apply_cell_name(self, old_name: str, new_name: str) -> Dict[str, Any]:
|
||||
"""Update the cell hostname record in the primary DNS zone file."""
|
||||
def apply_cell_name(self, old_name: str, new_name: str, reload: bool = True) -> Dict[str, Any]:
|
||||
"""Update the cell hostname record in the primary DNS zone file.
|
||||
|
||||
reload=False writes the zone file only — use when deferring container restart.
|
||||
"""
|
||||
restarted = []
|
||||
warnings = []
|
||||
if not old_name or not new_name or old_name == new_name:
|
||||
@@ -476,8 +482,6 @@ class NetworkManager(BaseServiceManager):
|
||||
zone_file = os.path.join(dns_data, fname)
|
||||
with open(zone_file) as f:
|
||||
content = f.read()
|
||||
# Replace hostname record: old_name IN A ...
|
||||
import re
|
||||
content = re.sub(
|
||||
rf'^{re.escape(old_name)}(\s+IN\s+A\s+)',
|
||||
f'{new_name}\\1',
|
||||
@@ -486,8 +490,9 @@ class NetworkManager(BaseServiceManager):
|
||||
with open(zone_file, 'w') as f:
|
||||
f.write(content)
|
||||
break
|
||||
self._reload_dns_service()
|
||||
restarted.append('cell-dns (reloaded)')
|
||||
if reload:
|
||||
self._reload_dns_service()
|
||||
restarted.append('cell-dns (reloaded)')
|
||||
except Exception as e:
|
||||
warnings.append(f"cell_name DNS update failed: {e}")
|
||||
return {'restarted': restarted, 'warnings': warnings}
|
||||
|
||||
Reference in New Issue
Block a user