Hosts: managed file, read-only system/addn-hosts, HostsFileSection UI

- Managed hosts file (zz-dnsmasq-webui.hosts): app reads/writes only this;
  addn-hosts in managed config loads it. SystemHostsPath is read-only display.
- Hosts page: editable managed file; then 'Other hosts (read-only)' (system
  hosts when configured and !no-hosts, plus addn-hosts excluding managed).
- GET api/hosts/readonly for read-only files; no-hosts hides system hosts.
- HostsFileSection.razor component; fix space before read-only badge.
- Test harness: show container /etc/hosts (default SystemHostsPath).
- Config parsing/sources, tests and client updates for new hosts model.
This commit is contained in:
2026-02-02 23:56:20 +10:00
parent 888bc980cf
commit a0863a663e
22 changed files with 249 additions and 107 deletions
@@ -179,12 +179,21 @@ public class HostsFileLineParserTests
entries.Add(HostsFileLineParser.ParseLine(lines[i], i + 1));
var dataEntries = entries.Where(e => e != null && !e.IsPassthrough).ToList();
Assert.Equal(2, dataEntries.Count);
Assert.Equal(5, dataEntries.Count);
Assert.Equal("127.0.0.1", dataEntries[0]!.Address);
Assert.Single(dataEntries[0]!.Names);
Assert.Equal("localhost", dataEntries[0]!.Names[0]);
Assert.Equal("::1", dataEntries[1]!.Address);
Assert.Single(dataEntries[1]!.Names);
Assert.Equal("localhost", dataEntries[1]!.Names[0]);
Assert.Equal("192.168.1.1", dataEntries[2]!.Address);
Assert.Single(dataEntries[2]!.Names);
Assert.Equal("router", dataEntries[2]!.Names[0]);
Assert.Equal("192.168.1.10", dataEntries[3]!.Address);
Assert.Single(dataEntries[3]!.Names);
Assert.Equal("testpc", dataEntries[3]!.Names[0]);
Assert.Equal("172.28.0.2", dataEntries[4]!.Address);
Assert.Single(dataEntries[4]!.Names);
Assert.Equal("dnsmasq-webui", dataEntries[4]!.Names[0]);
}
}