package handler import ( "context" "encoding/json" "net/http" "strings" "time" "vctp/internal/tasks" ) // SnapshotForceHourly triggers an on-demand hourly snapshot run. // @Summary Trigger hourly snapshot (manual) // @Description Manually trigger an hourly snapshot for all configured vCenters. Requires confirmation text to avoid accidental execution. // @Tags snapshots // @Accept json // @Produce json // @Param confirm query string true "Confirmation text; must be 'FORCE'" // @Success 200 {object} map[string]string "Snapshot started" // @Failure 400 {object} map[string]string "Invalid request" // @Failure 500 {object} map[string]string "Server error" // @Router /api/snapshots/hourly/force [post] func (h *Handler) SnapshotForceHourly(w http.ResponseWriter, r *http.Request) { confirm := strings.TrimSpace(r.URL.Query().Get("confirm")) if strings.ToUpper(confirm) != "FORCE" { writeJSONError(w, http.StatusBadRequest, "confirm must be 'FORCE'") return } ctx := context.Background() ct := &tasks.CronTask{ Logger: h.Logger, Database: h.Database, Settings: h.Settings, VcCreds: h.VcCreds, } started := time.Now() h.Logger.Info("Manual hourly snapshot requested") if err := ct.RunVcenterSnapshotHourly(ctx, h.Logger.With("manual", true)); err != nil { h.Logger.Error("Manual hourly snapshot failed", "error", err) writeJSONError(w, http.StatusInternalServerError, err.Error()) return } h.Logger.Info("Manual hourly snapshot completed", "duration", time.Since(started)) w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(map[string]string{ "status": "OK", }) }