708d983429
- internal/daemon/server.go: HTTP Server with lifecycle, logging middleware
- internal/daemon/health.go: /healthz (liveness), /readyz (db+ready), /v1/status
- internal/daemon/jobs_handler.go: GET /v1/jobs, /v1/jobs/{id}, /v1/jobs/{id}/tasks
- internal/daemon/nodes_handler.go: GET /v1/nodes
- internal/daemon/tasks_handler.go: GET /v1/tasks (with ?job_id and ?limit)
- internal/daemon/validate.go: input validation for path IDs
- internal/daemon/version.go: ldflags-friendly version var
- internal/store: added TaskRepo.ListRecent for unfiltered task listing
- internal/cli/daemon.go: CLI wiring with signal.NotifyContext shutdown
Personas: backend-engineer (handlers), cli-engineer (CLI wiring),
security-engineer (input validation, no secrets in access logs, slog JSON).
---ci---
project: orca
phase: 5
milestone: v0.1
status: execute
requirements:
covered: [REQ-006, REQ-017, REQ-019]
partial: []
---/ci---
32 lines
849 B
Go
32 lines
849 B
Go
package daemon
|
|
|
|
import (
|
|
"context"
|
|
"net/http"
|
|
"time"
|
|
|
|
"git.cloudinit.dev/coreci/orca/internal/model"
|
|
"git.cloudinit.dev/coreci/orca/internal/store"
|
|
)
|
|
|
|
// handleNodesCollection handles /v1/nodes (GET only in v0.1).
|
|
// Node registration is CLI-only; the API is read-only for observability.
|
|
func (s *Server) handleNodesCollection(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method != http.MethodGet {
|
|
writeError(w, http.StatusMethodNotAllowed, "method not allowed")
|
|
return
|
|
}
|
|
ctx, cancel := context.WithTimeout(r.Context(), 5*time.Second)
|
|
defer cancel()
|
|
|
|
nodes, err := store.NewNodeRepo(s.db).List(ctx)
|
|
if err != nil {
|
|
writeError(w, http.StatusInternalServerError, "failed to list nodes")
|
|
return
|
|
}
|
|
if nodes == nil {
|
|
nodes = []*model.Node{}
|
|
}
|
|
writeJSON(w, http.StatusOK, map[string]any{"nodes": nodes, "count": len(nodes)})
|
|
}
|