fix: Prevent broken dnsmasq entries for services without internal domain

Services registered via the service API have a domain but no internal
domain (that's a Wild Cloud instance concept). The dnsmasq generator
was producing broken entries like `local=//` and `address=//`.

Fix: skip internal domain entries when InternalDomain is empty, in
both config.go and config_modular.go. Also fix DNS entries to point
to Central's IP (where HAProxy listens) rather than the backend
address — all traffic flows through Central.

Added 3 tests covering: service-only, mixed services+instances.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-09 14:11:24 +00:00
parent c7a0227e03
commit e4e1a15f92
4 changed files with 95 additions and 13 deletions

View File

@@ -310,3 +310,71 @@ func TestNewConfigGenerator_DefaultPath(t *testing.T) {
t.Errorf("got %q, want /etc/dnsmasq.d/wild-cloud.conf", g.GetConfigPath())
}
}
// Test: Service registration — domain set but no internal domain
func TestGenerate_ServiceWithoutInternalDomain(t *testing.T) {
g := NewConfigGenerator("/tmp/test-dnsmasq.conf")
globalCfg := &config.GlobalConfig{}
// Service registration: only domain + backend IP, no internal domain
inst := instanceWith("my-api.payne.io", "", "192.168.8.151")
out := g.Generate(globalCfg, []config.InstanceConfig{inst})
// Should have address entry for the domain
if !strings.Contains(out, "address=/my-api.payne.io/192.168.8.151") {
t.Errorf("expected address entry for service domain, got:\n%s", out)
}
// Must NOT have empty local=// entry
if strings.Contains(out, "local=//") {
t.Errorf("unexpected empty local=// in output:\n%s", out)
}
// Must NOT have empty address=// entry
if strings.Contains(out, "address=//") {
t.Errorf("unexpected empty address=// in output:\n%s", out)
}
}
// Test: GenerateInstanceConfig — service without internal domain
func TestGenerateInstanceConfig_ServiceWithoutInternalDomain(t *testing.T) {
g := NewConfigGenerator("/tmp/test-dnsmasq.conf")
inst := instanceWith("central.payne.io", "", "192.168.8.151")
out := g.GenerateInstanceConfig(inst)
if !strings.Contains(out, "address=/central.payne.io/192.168.8.151") {
t.Errorf("expected address entry, got:\n%s", out)
}
if strings.Contains(out, "local=//") {
t.Errorf("unexpected empty local=// in output:\n%s", out)
}
if strings.Contains(out, "address=//") {
t.Errorf("unexpected empty address=// in output:\n%s", out)
}
}
// Test: Mix of instances with and without internal domains
func TestGenerate_MixedServicesAndInstances(t *testing.T) {
g := NewConfigGenerator("/tmp/test-dnsmasq.conf")
globalCfg := &config.GlobalConfig{}
instances := []config.InstanceConfig{
instanceWith("cloud.payne.io", "internal.cloud.payne.io", "192.168.8.240"), // k8s instance
instanceWith("central.payne.io", "", "192.168.8.151"), // service (no internal domain)
instanceWith("wild-cloud.payne.io", "", "192.168.8.151"), // service (no internal domain)
}
out := g.Generate(globalCfg, instances)
// k8s instance should have both local= and address= for internal domain
if !strings.Contains(out, "local=/internal.cloud.payne.io/") {
t.Errorf("expected local=/ for k8s internal domain, got:\n%s", out)
}
// Services should have address= entries
if !strings.Contains(out, "address=/central.payne.io/192.168.8.151") {
t.Errorf("expected address for central, got:\n%s", out)
}
// No broken empty entries
if strings.Contains(out, "local=//") {
t.Errorf("unexpected empty local=// in output:\n%s", out)
}
}