fix(system): render-configs rendert jetzt ALLE Dienste, nicht nur HAProxy
- SystemHandler.ExtraReloaders: neues Feld für nftables, wireguard,
squid, unbound, chrony Reloader
- WithAllReloaders(): Wire-Methode; main.go bindet alle Reloader nach
Initialisierung ein
- RenderConfigs: läuft alle Reloader durch, sammelt Fehler, antwortet
mit {ok, rendered[], errors{}} — partiell OK wird als warning gemeldet
- UI: Settings-Button-Label "Re-render all configs"; partial-error
Toast zeigt welche Dienste fehlschlugen
- Timeout: 30s statt 10s (alle Dienste brauchen mehr Zeit)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -40,6 +40,9 @@ type SystemHandler struct {
|
||||
// in main.go after generators are constructed. Read-only access —
|
||||
// no writes, no reloads.
|
||||
ConfigPreviewers map[string]func(stdcontext.Context) (string, error)
|
||||
// ExtraReloaders: additional service renderers triggered by
|
||||
// RenderConfigs. Keyed by service name (nftables, wireguard, etc.).
|
||||
ExtraReloaders map[string]func(stdcontext.Context) error
|
||||
}
|
||||
|
||||
func NewSystemHandler(version string) *SystemHandler {
|
||||
@@ -75,6 +78,14 @@ func (h *SystemHandler) WithConfigPreviewers(previewers map[string]func(stdconte
|
||||
return h
|
||||
}
|
||||
|
||||
// WithAllReloaders injectet alle Service-Reloader für RenderConfigs.
|
||||
// Reihenfolge: haproxy ist bereits in HAProxyReloader; extras sind die
|
||||
// restlichen Dienste (nftables, wireguard, squid, unbound, chrony).
|
||||
func (h *SystemHandler) WithAllReloaders(extras map[string]func(stdcontext.Context) error) *SystemHandler {
|
||||
h.ExtraReloaders = extras
|
||||
return h
|
||||
}
|
||||
|
||||
func (h *SystemHandler) Register(rg *gin.RouterGroup) {
|
||||
g := rg.Group("/system")
|
||||
g.GET("/health", h.Health)
|
||||
@@ -565,30 +576,46 @@ func (h *SystemHandler) ServiceRestart(c *gin.Context) {
|
||||
}
|
||||
|
||||
// RenderConfigs erzwingt ein Re-Render aller Service-Configs aus dem
|
||||
// aktuellen DB-State. Wenn der HAProxyReloader gesetzt ist, läuft der
|
||||
// (rendert haproxy.cfg + reload). Praktisch wenn ein Operator denkt
|
||||
// dass die generierte Config nicht mehr mit der DB übereinstimmt
|
||||
// (Drift, Manual-Edit, etc.).
|
||||
//
|
||||
// v1 macht NUR haproxy — weitere Renderer (firewall, dns, ntp, wg,
|
||||
// squid) sind per Handler an die jeweiligen Mutations-Endpoints
|
||||
// gekoppelt; für die fehlt aktuell ein generisches "render all".
|
||||
// aktuellen DB-State. Läuft haproxy + alle ExtraReloaders (nftables,
|
||||
// wireguard, squid, unbound, chrony) durch. Fehler werden gesammelt
|
||||
// und als partial-Antwort zurückgegeben — erfolgreich gerenderte
|
||||
// Dienste stehen in "rendered", fehlgeschlagene in "errors".
|
||||
func (h *SystemHandler) RenderConfigs(c *gin.Context) {
|
||||
if h.HAProxyReloader == nil {
|
||||
if h.HAProxyReloader == nil && len(h.ExtraReloaders) == 0 {
|
||||
response.Err(c, http.StatusServiceUnavailable, simpleErr("renderer not wired"))
|
||||
return
|
||||
}
|
||||
ctx, cancel := stdcontext.WithTimeout(c.Request.Context(), 10*time.Second)
|
||||
ctx, cancel := stdcontext.WithTimeout(c.Request.Context(), 30*time.Second)
|
||||
defer cancel()
|
||||
if err := h.HAProxyReloader(ctx); err != nil {
|
||||
response.Internal(c, err)
|
||||
return
|
||||
|
||||
rendered := []string{}
|
||||
errs := map[string]string{}
|
||||
|
||||
if h.HAProxyReloader != nil {
|
||||
if err := h.HAProxyReloader(ctx); err != nil {
|
||||
errs["haproxy"] = err.Error()
|
||||
} else {
|
||||
rendered = append(rendered, "haproxy")
|
||||
}
|
||||
}
|
||||
// Defined order so the audit log is deterministic.
|
||||
order := []string{"nftables", "wireguard", "squid", "unbound", "chrony"}
|
||||
for _, name := range order {
|
||||
fn, ok := h.ExtraReloaders[name]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
if err := fn(ctx); err != nil {
|
||||
errs[name] = err.Error()
|
||||
} else {
|
||||
rendered = append(rendered, name)
|
||||
}
|
||||
}
|
||||
if h.Audit != nil {
|
||||
_ = h.Audit.Log(c.Request.Context(), actorOf(c), "system.render_configs",
|
||||
"", gin.H{}, h.NodeID)
|
||||
"", gin.H{"rendered": rendered, "errors": errs}, h.NodeID)
|
||||
}
|
||||
response.OK(c, gin.H{"ok": true, "rendered": []string{"haproxy"}})
|
||||
response.OK(c, gin.H{"ok": len(errs) == 0, "rendered": rendered, "errors": errs})
|
||||
}
|
||||
|
||||
// UpgradeStatus liefert den Status des letzten Self-Upgrade-Versuchs.
|
||||
|
||||
Reference in New Issue
Block a user