package v1 import ( "fmt" "time" "github.com/wild-cloud/wild-central/internal/domains" "github.com/wild-cloud/wild-central/internal/sse" ) // EnsureCentralDomain registers (or updates) Central's own domain as a domain // so it participates in DNS, HAProxy routing, and TLS cert tracking like any // other domain. Called on startup and when global config changes. func (api *API) EnsureCentralDomain() { centralDomain := api.getCentralDomain() port := api.getRunningPort() backend := fmt.Sprintf("127.0.0.1:%d", port) // Check if the current registration already matches — skip if so. if centralDomain != "" { if existing, _ := api.domains.Get(centralDomain); existing != nil && existing.Source == "central" && existing.Backend.Address == backend { return } } // Clean up stale Central registrations (e.g. domain changed). doms, _ := api.domains.List() for _, dom := range doms { if dom.Source == "central" && dom.DomainName != centralDomain { _ = api.domains.Deregister(dom.DomainName) } } if centralDomain == "" { return } _ = api.domains.Register(domains.Domain{ DomainName: centralDomain, Source: "central", Backend: domains.Backend{ Address: backend, Type: domains.BackendHTTP, }, TLS: domains.TLSTerminate, }) } // Reconcile runs networking reconciliation immediately. Called on startup // and automatically whenever a domain is registered/updated/deregistered. func (api *API) Reconcile() { api.reconciler.Reconcile() } // broadcastDnsmasqEvent broadcasts SSE events for dnsmasq status changes func (api *API) broadcastDnsmasqEvent(eventType string, message string) { if api.sseManager == nil { return } // Get current dnsmasq status status, err := api.dnsmasq.GetStatus() if err != nil { status = nil } event := &sse.Event{ ID: fmt.Sprintf("dnsmasq-%d", time.Now().UnixNano()), Type: eventType, InstanceName: "global", Timestamp: time.Now(), Data: map[string]any{ "message": message, "status": status, }, } api.sseManager.Broadcast(event) } // broadcastHaproxyEvent broadcasts SSE events for HAProxy status changes func (api *API) broadcastHaproxyEvent(eventType string, message string) { if api.sseManager == nil { return } event := &sse.Event{ ID: fmt.Sprintf("haproxy-%d", time.Now().UnixNano()), Type: eventType, InstanceName: "global", Timestamp: time.Now(), Data: map[string]any{ "message": message, }, } api.sseManager.Broadcast(event) } // broadcastAutheliaEvent broadcasts SSE events for Authelia status changes func (api *API) broadcastAutheliaEvent(eventType string, message string) { if api.sseManager == nil { return } event := &sse.Event{ ID: fmt.Sprintf("authelia-%d", time.Now().UnixNano()), Type: eventType, InstanceName: "global", Timestamp: time.Now(), Data: map[string]any{ "message": message, }, } api.sseManager.Broadcast(event) } // broadcastCentralStatusEvent broadcasts SSE events for central status changes func (api *API) broadcastCentralStatusEvent(startTime time.Time) { if api.sseManager == nil { return } uptime := time.Since(startTime) event := &sse.Event{ ID: fmt.Sprintf("central-%d", time.Now().UnixNano()), Type: "central:status", InstanceName: "global", Timestamp: time.Now(), Data: map[string]any{ "status": "running", "version": api.version, "uptime": uptime.String(), "uptimeSeconds": int(uptime.Seconds()), }, } api.sseManager.Broadcast(event) } // broadcastDNSFilterEvent broadcasts SSE events for DNS filter changes func (api *API) broadcastDNSFilterEvent(eventType string, message string) { if api.sseManager == nil { return } event := &sse.Event{ ID: fmt.Sprintf("dns-filter-%d", time.Now().UnixNano()), Type: eventType, InstanceName: "global", Timestamp: time.Now(), Data: map[string]any{ "message": message, }, } api.sseManager.Broadcast(event) }