diff --git a/cmd/inventory/main.go b/cmd/inventory/main.go index dd8e6df..0d2ec8a 100644 --- a/cmd/inventory/main.go +++ b/cmd/inventory/main.go @@ -92,6 +92,7 @@ func main() { }) mux.HandleFunc("GET /admin/chaos", c.HandleGetConfig) mux.HandleFunc("PUT /admin/chaos", c.HandleSetConfig) + mux.HandleFunc("POST /admin/chaos/clear-disk", c.HandleClearDisk) mux.Handle("/", svc.Mux) handler := c.Middleware(middleware.Wrap(mux, cfg.ServiceName)) diff --git a/internal/chaos/chaos.go b/internal/chaos/chaos.go index 9a924ba..3643e96 100644 --- a/internal/chaos/chaos.go +++ b/internal/chaos/chaos.go @@ -125,3 +125,14 @@ func (c *Chaos) HandleSetConfig(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(c.GetConfig()) } + +func (c *Chaos) HandleClearDisk(w http.ResponseWriter, r *http.Request) { + if err := c.DiskFiller.Clear(); err != nil { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusInternalServerError) + json.NewEncoder(w).Encode(map[string]string{"error": err.Error()}) + return + } + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(map[string]string{"status": "cleared"}) +} diff --git a/internal/chaos/disk_filler.go b/internal/chaos/disk_filler.go index e165538..1c85654 100644 --- a/internal/chaos/disk_filler.go +++ b/internal/chaos/disk_filler.go @@ -54,6 +54,17 @@ func (d *DiskFiller) GetConfig() (enabled bool, path string, rateMB int) { return d.enabled, d.path, d.rateMB } +func (d *DiskFiller) Clear() error { + d.mu.Lock() + defer d.mu.Unlock() + if d.path == "" { + return nil + } + fillDir := filepath.Join(d.path, "chaos-fill") + slog.Info("chaos: clearing disk fill data", "path", fillDir) + return os.RemoveAll(fillDir) +} + func (d *DiskFiller) startLocked() { if d.parentCtx == nil || !d.enabled || d.rateMB <= 0 || d.path == "" { return diff --git a/services/dashboard/handler.go b/services/dashboard/handler.go index 8e008e6..63ae83a 100644 --- a/services/dashboard/handler.go +++ b/services/dashboard/handler.go @@ -80,6 +80,32 @@ func (h *Handler) SetServiceChaos(w http.ResponseWriter, r *http.Request) { io.Copy(w, resp.Body) } +func (h *Handler) ClearServiceDisk(w http.ResponseWriter, r *http.Request) { + name := r.PathValue("name") + svc := h.findService(name) + if svc == nil { + http.Error(w, `{"error":"service not found"}`, http.StatusNotFound) + return + } + + req, err := http.NewRequestWithContext(r.Context(), http.MethodPost, svc.URL+"/admin/chaos/clear-disk", nil) + if err != nil { + http.Error(w, `{"error":"failed to create request"}`, http.StatusInternalServerError) + return + } + + resp, err := h.httpClient.Do(req) + if err != nil { + http.Error(w, `{"error":"service unreachable: `+err.Error()+`"}`, http.StatusBadGateway) + return + } + defer resp.Body.Close() + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(resp.StatusCode) + io.Copy(w, resp.Body) +} + func (h *Handler) findService(name string) *ServiceInfo { for i := range h.services { if h.services[i].Name == name { diff --git a/services/dashboard/routes.go b/services/dashboard/routes.go index ab1f065..d9eb4a3 100644 --- a/services/dashboard/routes.go +++ b/services/dashboard/routes.go @@ -6,5 +6,6 @@ func RegisterRoutes(mux *http.ServeMux, h *Handler, staticFS http.Handler) { mux.HandleFunc("GET /api/services", h.ListServices) mux.HandleFunc("GET /api/services/{name}/chaos", h.GetServiceChaos) mux.HandleFunc("PUT /api/services/{name}/chaos", h.SetServiceChaos) + mux.HandleFunc("POST /api/services/{name}/chaos/clear-disk", h.ClearServiceDisk) mux.Handle("/", staticFS) } diff --git a/services/dashboard/static/index.html b/services/dashboard/static/index.html index 1720cd8..7d1aa34 100644 --- a/services/dashboard/static/index.html +++ b/services/dashboard/static/index.html @@ -209,11 +209,11 @@