// Package handlers provides HTTP handlers for the rdev API. package handlers import ( "context" "log/slog" "net/http" "github.com/go-chi/chi/v5" "github.com/orchard9/rdev/internal/auth" "github.com/orchard9/rdev/internal/domain" "github.com/orchard9/rdev/internal/port" "github.com/orchard9/rdev/pkg/api" ) // DiagnosticsGetter retrieves project diagnostics. type DiagnosticsGetter interface { GetDiagnostics(ctx context.Context, projectID string) (*domain.ProjectDiagnostics, error) } // DiagnosticsHandler handles project diagnostics requests. type DiagnosticsHandler struct { diagnostics DiagnosticsGetter projects port.ProjectRepository logger *slog.Logger } // NewDiagnosticsHandler creates a new diagnostics handler. func NewDiagnosticsHandler( diagnostics DiagnosticsGetter, projects port.ProjectRepository, logger *slog.Logger, ) *DiagnosticsHandler { if logger == nil { logger = slog.Default() } return &DiagnosticsHandler{ diagnostics: diagnostics, projects: projects, logger: logger, } } // Mount registers the diagnostics routes. func (h *DiagnosticsHandler) Mount(r api.Router) { r.Route("/projects/{projectId}/diagnostics", func(r chi.Router) { r.With(auth.RequireScope(auth.ScopeProjectsRead, auth.ScopeAdmin)).Get("/", h.GetDiagnostics) }) } // GetDiagnostics returns comprehensive health information for a project. // GET /projects/{projectId}/diagnostics func (h *DiagnosticsHandler) GetDiagnostics(w http.ResponseWriter, r *http.Request) { ctx, cancel := context.WithTimeout(r.Context(), TimeoutStandard) defer cancel() projectID := chi.URLParam(r, "projectId") if projectID == "" { api.WriteBadRequest(w, r, "project ID is required") return } // Verify project exists (optional - diagnostics can still be useful for non-k8s projects) if h.projects != nil { if _, err := h.projects.Get(ctx, domain.ProjectID(projectID)); err != nil { if err == domain.ErrProjectNotFound { // Log but continue - the project might exist in git/CI but not as a k8s pod h.logger.Debug("project not found in k8s, continuing with diagnostics", "project_id", projectID, ) } } } diag, err := h.diagnostics.GetDiagnostics(ctx, projectID) if err != nil { h.logger.Error("failed to get diagnostics", "error", err, "project_id", projectID, ) api.WriteInternalError(w, r, "failed to retrieve diagnostics") return } api.WriteSuccess(w, r, diag) }