feat: Add EnsureCentralService + improved tests

Linter-contributed improvements:
- EnsureCentralService() method: registers Central's own domain as a
  service from config, with cleanup on domain change
- Tests for EnsureCentralService: registration, idempotency, domain
  change cleanup, no-domain-is-noop
- Improved reconciliation tests with Central as a registered service
- Certbot handler cleanup

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-09 22:26:56 +00:00
parent 2e6fce54e3
commit c18217944f
6 changed files with 222 additions and 54 deletions

View File

@@ -16,6 +16,47 @@ import (
"github.com/wild-cloud/wild-central/internal/sse"
)
// EnsureCentralService registers (or updates) Central's own domain as a service
// so it participates in DNS, HAProxy routing, and TLS cert tracking like any
// other service. Called on startup and when global config changes.
func (api *API) EnsureCentralService() {
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.services.Get(centralDomain); existing != nil &&
existing.Source == "central" &&
existing.Backend.Address == backend {
return
}
}
// Clean up stale Central registrations (e.g. domain changed).
svcs, _ := api.services.List()
for _, svc := range svcs {
if svc.Source == "central" && svc.Domain != centralDomain {
_ = api.services.Deregister(svc.Domain)
}
}
if centralDomain == "" {
return
}
_ = api.services.Register(services.Service{
Domain: centralDomain,
Source: "central",
Backend: services.Backend{
Address: backend,
Type: services.BackendHTTP,
},
Reach: services.ReachInternal,
TLS: services.TLSTerminate,
})
}
// Reconcile runs networking reconciliation immediately. Called on startup
// and automatically whenever a service is registered/updated/deregistered.
func (api *API) Reconcile() {
@@ -61,17 +102,6 @@ func (api *API) reconcileNetworking() {
}
}
// Inject Central's own domain as an HTTP route (from config, not registration).
// Central is just another L7 service from HAProxy's perspective.
if d := globalCfg.Cloud.Central.Domain; d != "" {
centralPort := api.getRunningPort()
httpRoutes = append([]haproxy.HTTPRoute{{
Name: "wild-central",
Domain: d,
Backend: fmt.Sprintf("127.0.0.1:%d", centralPort),
}}, httpRoutes...)
}
// Only include L7 HTTP routes for services that have a cert.
certsDir := "/etc/haproxy/certs/"
var activeHTTPRoutes []haproxy.HTTPRoute