Architecture: - Extract reconcileNetworking into internal/reconcile package with 7 consumer-side interfaces - Add locked modifyState helper to fix state.yaml read-modify-write race condition - Extract CrowdSec and VPN handler groups with interfaces documenting dependency surface - Replace raw map[string]any YAML manipulation with typed AddDHCPStaticLease/RemoveDHCPStaticLease - Extract Cloudflare API functions into cfClient struct, eliminating repeated auth boilerplate Complexity reduction: - haproxy.GenerateWithOpts: 50 → 6 (extracted 8 focused helpers) - reconcile.Reconcile: 42 → 11 (extracted buildRoutes, buildDNSEntries, writeHAProxyConfig) - AutheliaUpdateConfig: 25 → 10 (extracted enableAuthelia/disableAuthelia) Test coverage improvements: - reconcile: 4.5% → 56.8% (stub-based tests for route building, DNS entries, orchestration) - dnsfilter: 10.7% → 45.6% (Manager.Compile, AddList, ToggleList, custom entries) - config: 67.3% → 89.8% (DHCP static lease mutation tests)
71 lines
2.3 KiB
Go
71 lines
2.3 KiB
Go
package v1
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
)
|
|
|
|
// HaproxyStatus returns the status of the HAProxy service and current instance routes.
|
|
func (api *API) HaproxyStatus(w http.ResponseWriter, r *http.Request) {
|
|
status, err := api.haproxy.GetStatus()
|
|
if err != nil {
|
|
respondError(w, http.StatusInternalServerError, fmt.Sprintf("Failed to get HAProxy status: %v", err))
|
|
return
|
|
}
|
|
respondJSON(w, http.StatusOK, map[string]any{
|
|
"status": status.Status,
|
|
"pid": status.PID,
|
|
"configFile": status.ConfigFile,
|
|
})
|
|
}
|
|
|
|
// HaproxyGetConfig returns the current HAProxy configuration file contents
|
|
func (api *API) HaproxyGetConfig(w http.ResponseWriter, r *http.Request) {
|
|
content, err := api.haproxy.ReadConfig()
|
|
if err != nil {
|
|
respondError(w, http.StatusInternalServerError, fmt.Sprintf("Failed to read HAProxy config: %v", err))
|
|
return
|
|
}
|
|
respondJSON(w, http.StatusOK, map[string]any{
|
|
"configFile": api.haproxy.GetConfigPath(),
|
|
"content": content,
|
|
})
|
|
}
|
|
|
|
// HaproxyRestart restarts the HAProxy service
|
|
func (api *API) HaproxyRestart(w http.ResponseWriter, r *http.Request) {
|
|
if err := api.haproxy.RestartService(); err != nil {
|
|
respondError(w, http.StatusInternalServerError, fmt.Sprintf("Failed to restart HAProxy: %v", err))
|
|
return
|
|
}
|
|
api.broadcastHaproxyEvent("haproxy:restart", "HAProxy service restarted")
|
|
respondJSON(w, http.StatusOK, map[string]string{
|
|
"message": "HAProxy service restarted successfully",
|
|
})
|
|
}
|
|
|
|
// HaproxyGenerate regenerates HAProxy config from all WC instance data and custom routes,
|
|
// then updates nftables to match. Both operations happen together so ports stay in sync.
|
|
func (api *API) HaproxyGenerate(w http.ResponseWriter, r *http.Request) {
|
|
api.reconciler.Reconcile()
|
|
|
|
content, err := api.haproxy.ReadConfig()
|
|
if err != nil {
|
|
content = ""
|
|
}
|
|
respondJSON(w, http.StatusOK, map[string]any{
|
|
"message": "HAProxy configuration regenerated from registered domains",
|
|
"config": content,
|
|
})
|
|
}
|
|
|
|
// HaproxyStats returns live per-backend connection stats from the HAProxy stats socket
|
|
func (api *API) HaproxyStats(w http.ResponseWriter, r *http.Request) {
|
|
stats, err := api.haproxy.GetStats()
|
|
if err != nil {
|
|
respondError(w, http.StatusInternalServerError, fmt.Sprintf("Failed to get HAProxy stats: %v", err))
|
|
return
|
|
}
|
|
respondJSON(w, http.StatusOK, map[string]any{"backends": stats})
|
|
}
|