fix: apply_domain now removes all stale zone files when renaming

Previously the loop broke after processing the first zone file it found.
If dev.zone already existed (created by apply_ip_range), it would be
processed and the loop would stop — leaving any other zone files (e.g.
cell.zone from an earlier domain) in place. get_dns_records() reads all
.zone files so the stale zone appeared doubled in the UI.

Fix: collect all non-local zone files first, write the target, then
delete every file that is not the current domain's zone.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-24 04:08:37 -04:00
parent dd5244279d
commit 596b06f171
+28 -21
View File
@@ -419,30 +419,37 @@ class NetworkManager(BaseServiceManager):
except Exception as e: except Exception as e:
warnings.append(f"Corefile domain update failed: {e}") warnings.append(f"Corefile domain update failed: {e}")
# 3. Update zone file: rename and rewrite $ORIGIN / SOA # 3. Update zone file: rename and rewrite $ORIGIN / SOA, remove stale zones
try: try:
dns_data = os.path.join(self.data_dir, 'dns') dns_data = os.path.join(self.data_dir, 'dns')
if os.path.isdir(dns_data): if os.path.isdir(dns_data):
# Find existing primary zone file (anything not named 'local') dst = os.path.join(dns_data, f'{domain}.zone')
for fname in os.listdir(dns_data): # Find the best source: prefer a non-target zone (old domain) so we
if fname.endswith('.zone') and 'local' not in fname: # can migrate its content; fall back to the target zone itself.
src = os.path.join(dns_data, fname) zone_files = [
with open(src) as f: os.path.join(dns_data, f)
zone_content = f.read() for f in os.listdir(dns_data)
# Detect old domain from $ORIGIN line if f.endswith('.zone') and 'local' not in f
m = re.search(r'^\$ORIGIN\s+(\S+)', zone_content, re.MULTILINE) ]
old_origin = m.group(1).rstrip('.') if m else None src = next((p for p in zone_files if p != dst), dst)
if old_origin and old_origin != domain: if os.path.exists(src):
zone_content = zone_content.replace( with open(src) as f:
f'{old_origin}.', f'{domain}.') zone_content = f.read()
zone_content = re.sub( m = re.search(r'^\$ORIGIN\s+(\S+)', zone_content, re.MULTILINE)
r'^\$ORIGIN\s+\S+', f'$ORIGIN {domain}.', zone_content, flags=re.MULTILINE) old_origin = m.group(1).rstrip('.') if m else None
dst = os.path.join(dns_data, f'{domain}.zone') if old_origin and old_origin != domain:
with open(dst, 'w') as f: zone_content = zone_content.replace(f'{old_origin}.', f'{domain}.')
f.write(zone_content) zone_content = re.sub(
if src != dst: r'^\$ORIGIN\s+\S+', f'$ORIGIN {domain}.', zone_content, flags=re.MULTILINE)
os.remove(src) with open(dst, 'w') as f:
break 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:
os.remove(zone_path)
except OSError:
pass
except Exception as e: except Exception as e:
warnings.append(f"zone file domain update failed: {e}") warnings.append(f"zone file domain update failed: {e}")