services -> domains

This commit is contained in:
2026-07-10 20:46:22 +00:00
parent 3c99d26830
commit 79c0c32b98
45 changed files with 1447 additions and 1270 deletions

View File

@@ -35,7 +35,7 @@ func (g *ConfigGenerator) GetConfigPath() string {
// Generate creates a dnsmasq configuration from the app config
// It auto-detects the Wild Central server's IP address
func (g *ConfigGenerator) Generate(cfg *config.GlobalConfig, clouds []config.InstanceConfig) string {
func (g *ConfigGenerator) Generate(cfg *config.State, clouds []config.InstanceConfig) string {
// Use configured dnsmasq IP (bound to eth0), falling back to auto-detect.
// Auto-detect can pick wlan0 if that's the default route, which is wrong
// when dnsmasq is only listening on eth0.
@@ -104,7 +104,7 @@ log-dhcp
}
// WriteConfig writes the dnsmasq configuration to the specified path
func (g *ConfigGenerator) WriteConfig(cfg *config.GlobalConfig, clouds []config.InstanceConfig, configPath string) error {
func (g *ConfigGenerator) WriteConfig(cfg *config.State, clouds []config.InstanceConfig, configPath string) error {
configContent := g.Generate(cfg, clouds)
slog.Info("writing dnsmasq config", "component", "dnsmasq", "path", configPath)
@@ -212,7 +212,7 @@ func (g *ConfigGenerator) ReadConfig() (string, error) {
}
// UpdateConfig regenerates and writes the dnsmasq configuration for all instances
func (g *ConfigGenerator) UpdateConfig(cfg *config.GlobalConfig, instances []config.InstanceConfig, restart bool) error {
func (g *ConfigGenerator) UpdateConfig(cfg *config.State, instances []config.InstanceConfig, restart bool) error {
// Generate fresh config from scratch
configContent := g.Generate(cfg, instances)

View File

@@ -18,7 +18,7 @@ const (
// GenerateMainConfig creates the main dnsmasq configuration with global settings
// and a conf-dir directive to include per-instance configs
func (g *ConfigGenerator) GenerateMainConfig(cfg *config.GlobalConfig) string {
func (g *ConfigGenerator) GenerateMainConfig(cfg *config.State) string {
// Get the Wild Central IP address
dnsIP, err := network.GetWildCentralIP()
if err != nil {
@@ -264,7 +264,7 @@ func (g *ConfigGenerator) ReloadService() error {
}
// UpdateToModularConfig migrates from monolithic to modular configuration
func (g *ConfigGenerator) UpdateToModularConfig(cfg *config.GlobalConfig, instanceNames []string, instances []config.InstanceConfig) error {
func (g *ConfigGenerator) UpdateToModularConfig(cfg *config.State, instanceNames []string, instances []config.InstanceConfig) error {
slog.Info("migrating to modular configuration", "component", "dnsmasq")
// Ensure instance directory exists

View File

@@ -191,7 +191,7 @@ func TestGenerateMainConfig(t *testing.T) {
// Test: GenerateMainConfig with DHCP disabled does not include dhcp-range
func TestGenerateMainConfig_DHCPDisabled(t *testing.T) {
g := NewConfigGenerator("/tmp/test-dnsmasq.conf")
cfg := &config.GlobalConfig{}
cfg := &config.State{}
cfg.Cloud.Dnsmasq.DHCP.Enabled = false
out := g.GenerateMainConfig(cfg)
@@ -204,7 +204,7 @@ func TestGenerateMainConfig_DHCPDisabled(t *testing.T) {
// Test: GenerateMainConfig with DHCP enabled includes dhcp-range
func TestGenerateMainConfig_DHCPEnabled(t *testing.T) {
g := NewConfigGenerator("/tmp/test-dnsmasq.conf")
cfg := &config.GlobalConfig{}
cfg := &config.State{}
cfg.Cloud.Dnsmasq.DHCP.Enabled = true
cfg.Cloud.Dnsmasq.DHCP.RangeStart = "192.168.8.100"
cfg.Cloud.Dnsmasq.DHCP.RangeEnd = "192.168.8.200"
@@ -224,7 +224,7 @@ func TestGenerateMainConfig_DHCPEnabled(t *testing.T) {
// Test: DHCP without gateway omits dhcp-option=3
func TestGenerateMainConfig_DHCPNoGateway(t *testing.T) {
g := NewConfigGenerator("/tmp/test-dnsmasq.conf")
cfg := &config.GlobalConfig{}
cfg := &config.State{}
cfg.Cloud.Dnsmasq.DHCP.Enabled = true
cfg.Cloud.Dnsmasq.DHCP.RangeStart = "192.168.8.100"
cfg.Cloud.Dnsmasq.DHCP.RangeEnd = "192.168.8.200"
@@ -240,7 +240,7 @@ func TestGenerateMainConfig_DHCPNoGateway(t *testing.T) {
// Test: DHCP explicit gateway is used
func TestGenerateMainConfig_DHCPExplicitGateway(t *testing.T) {
g := NewConfigGenerator("/tmp/test-dnsmasq.conf")
cfg := &config.GlobalConfig{}
cfg := &config.State{}
cfg.Cloud.Dnsmasq.DHCP.Enabled = true
cfg.Cloud.Dnsmasq.DHCP.RangeStart = "192.168.8.100"
cfg.Cloud.Dnsmasq.DHCP.RangeEnd = "192.168.8.200"
@@ -256,7 +256,7 @@ func TestGenerateMainConfig_DHCPExplicitGateway(t *testing.T) {
// Test: DHCP static leases appear in output
func TestGenerateMainConfig_DHCPStaticLeases(t *testing.T) {
g := NewConfigGenerator("/tmp/test-dnsmasq.conf")
cfg := &config.GlobalConfig{}
cfg := &config.State{}
cfg.Cloud.Dnsmasq.DHCP.Enabled = true
cfg.Cloud.Dnsmasq.DHCP.RangeStart = "192.168.8.100"
cfg.Cloud.Dnsmasq.DHCP.RangeEnd = "192.168.8.200"
@@ -278,7 +278,7 @@ func TestGenerateMainConfig_DHCPStaticLeases(t *testing.T) {
// Test: DHCP lease time defaults to 24h when not specified
func TestGenerateMainConfig_DHCPLeaseTimeDefault(t *testing.T) {
g := NewConfigGenerator("/tmp/test-dnsmasq.conf")
cfg := &config.GlobalConfig{}
cfg := &config.State{}
cfg.Cloud.Dnsmasq.DHCP.Enabled = true
cfg.Cloud.Dnsmasq.DHCP.RangeStart = "192.168.8.100"
cfg.Cloud.Dnsmasq.DHCP.RangeEnd = "192.168.8.200"
@@ -310,7 +310,7 @@ func TestNewConfigGenerator_DefaultPath(t *testing.T) {
// Test: Service registration — domain set but no internal domain
func TestGenerate_ServiceWithoutInternalDomain(t *testing.T) {
g := NewConfigGenerator("/tmp/test-dnsmasq.conf")
globalCfg := &config.GlobalConfig{}
globalCfg := &config.State{}
// Service registration: only domain + backend IP, no internal domain
inst := instanceWith("my-api.payne.io", "", "192.168.8.151")
@@ -351,7 +351,7 @@ func TestGenerateInstanceConfig_ServiceWithoutInternalDomain(t *testing.T) {
// Test: reach:internal → local=/ directive present (prevents upstream DNS forwarding)
func TestGenerate_ReachInternal_HasLocal(t *testing.T) {
g := NewConfigGenerator("/tmp/test-dnsmasq.conf")
globalCfg := &config.GlobalConfig{}
globalCfg := &config.State{}
// Simulate reconciliation for an internal-reach service:
// InternalDomain is set (reach:internal), Domain is empty (reach:public)
@@ -370,7 +370,7 @@ func TestGenerate_ReachInternal_HasLocal(t *testing.T) {
// Test: reach:public → no local=/ directive (allows upstream DNS forwarding)
func TestGenerate_ReachPublic_NoLocal(t *testing.T) {
g := NewConfigGenerator("/tmp/test-dnsmasq.conf")
globalCfg := &config.GlobalConfig{}
globalCfg := &config.State{}
// Simulate reconciliation for a public-reach service:
// Domain is set (reach:public), InternalDomain is empty
@@ -389,7 +389,7 @@ func TestGenerate_ReachPublic_NoLocal(t *testing.T) {
// Test: InternalDomain field → local=/ entry for LAN-only resolution
func TestGenerate_InternalDomainOnly_HasLocal(t *testing.T) {
g := NewConfigGenerator("/tmp/test-dnsmasq.conf")
globalCfg := &config.GlobalConfig{}
globalCfg := &config.State{}
// Instance with only an internal domain (no external domain)
inst := instanceWith("", "internal.cloud.payne.io", "192.168.8.240")
@@ -411,7 +411,7 @@ func TestGenerate_InternalDomainOnly_HasLocal(t *testing.T) {
// Test: Mix of instances with and without internal domains
func TestGenerate_MixedServicesAndInstances(t *testing.T) {
g := NewConfigGenerator("/tmp/test-dnsmasq.conf")
globalCfg := &config.GlobalConfig{}
globalCfg := &config.State{}
instances := []config.InstanceConfig{
instanceWith("cloud.payne.io", "internal.cloud.payne.io", "192.168.8.240"), // k8s instance
@@ -438,7 +438,7 @@ func TestGenerate_MixedServicesAndInstances(t *testing.T) {
// Test: empty instances list produces base config with no address= entries
func TestGenerate_EmptyInstances(t *testing.T) {
g := NewConfigGenerator("/tmp/test-dnsmasq.conf")
globalCfg := &config.GlobalConfig{}
globalCfg := &config.State{}
out := g.Generate(globalCfg, []config.InstanceConfig{})
@@ -462,7 +462,7 @@ func TestGenerate_EmptyInstances(t *testing.T) {
// Test: multiple instances each get their own entries
func TestGenerate_MultipleInstances(t *testing.T) {
g := NewConfigGenerator("/tmp/test-dnsmasq.conf")
globalCfg := &config.GlobalConfig{}
globalCfg := &config.State{}
instances := []config.InstanceConfig{
instanceWith("cloud1.example.com", "internal1.example.com", "10.0.0.1"),
@@ -504,7 +504,7 @@ func TestGenerate_NilConfig(t *testing.T) {
// Test: when cfg.Cloud.Dnsmasq.IP is set, uses that instead of auto-detect
func TestGenerate_ConfiguredDnsmasqIP(t *testing.T) {
g := NewConfigGenerator("/tmp/test-dnsmasq.conf")
cfg := &config.GlobalConfig{}
cfg := &config.State{}
cfg.Cloud.Dnsmasq.IP = "192.168.8.100"
out := g.Generate(cfg, []config.InstanceConfig{})
@@ -517,7 +517,7 @@ func TestGenerate_ConfiguredDnsmasqIP(t *testing.T) {
// Test: verify no address=// or local=// entries appear in any test output
func TestGenerate_NoLeakedEmptyEntries(t *testing.T) {
g := NewConfigGenerator("/tmp/test-dnsmasq.conf")
cfg := &config.GlobalConfig{}
cfg := &config.State{}
cases := []struct {
name string