M5: Patch Deployment & Job Management
Backend: - migrations/003_jobs_scheduling.sql: retry_next_at/last_error columns, pg_notify trigger for immediate job dispatch, retry index - pm-agent-client: ApplyPatchesRequest/Response, AgentJobStatus, RollbackResponse types; apply_patches/job_status/rollback_job client methods + generic POST helper - pm-core/models: JobStatus, JobKind, PatchJob, PatchJobHost, CreateJobRequest, PatchJobSummary - pm-web/routes/jobs.rs: POST/GET /api/v1/jobs, GET /jobs/:id, POST /jobs/:id/cancel, POST /jobs/:id/rollback - pm-worker/job_executor.rs: NOTIFY listener, periodic scanner, execute_host_job, poll_running_jobs, handle_host_failure (3-retry exponential backoff 1m/5m/30m), sync_job_status, retry_pending_jobs - pm-worker/main.rs: spawn job_executor Frontend: - types/index.ts: PatchInfo, PatchJobHost, PatchJob, PatchJobSummary, CreateJobRequest interfaces - api/client.ts: jobsApi (list/get/create/cancel/rollback), patchesApi (getHostPatches) - pages/PatchDeploymentPage.tsx: 3-step MUI Stepper (host select → configure → result) - pages/JobsPage.tsx: job list table, expandable per-host detail, cancel/rollback actions with confirm dialog, load-more pagination - App.tsx: /jobs and /deployment routes wired to real pages cargo check: 0 errors | vite build: 0 errors
This commit is contained in:
@ -8,6 +8,9 @@ import HostsPage from './pages/HostsPage'
|
||||
import HostDetailPage from './pages/HostDetailPage'
|
||||
import GroupsPage from './pages/GroupsPage'
|
||||
import UsersPage from './pages/UsersPage'
|
||||
import DashboardPage from './pages/DashboardPage'
|
||||
import PatchDeploymentPage from './pages/PatchDeploymentPage'
|
||||
import JobsPage from './pages/JobsPage'
|
||||
|
||||
// Placeholder pages — implemented in later milestones
|
||||
const PlaceholderPage = ({ title }: { title: string }) => (
|
||||
@ -35,15 +38,15 @@ function App() {
|
||||
<Route path="/mfa/setup" element={<RequireAuth><MfaSetupPage /></RequireAuth>} />
|
||||
|
||||
{/* Protected — M3 */}
|
||||
<Route path="/dashboard" element={<RequireAuth><PlaceholderPage title="Dashboard" /></RequireAuth>} />
|
||||
<Route path="/dashboard" element={<RequireAuth><DashboardPage /></RequireAuth>} />
|
||||
<Route path="/hosts" element={<RequireAuth><HostsPage /></RequireAuth>} />
|
||||
<Route path="/hosts/:id" element={<RequireAuth><HostDetailPage /></RequireAuth>} />
|
||||
<Route path="/groups" element={<RequireAuth><GroupsPage /></RequireAuth>} />
|
||||
<Route path="/users" element={<RequireAuth><UsersPage /></RequireAuth>} />
|
||||
|
||||
{/* Protected — later milestones */}
|
||||
<Route path="/jobs" element={<RequireAuth><PlaceholderPage title="Jobs" /></RequireAuth>} />
|
||||
<Route path="/deployment" element={<RequireAuth><PlaceholderPage title="Patch Deployment" /></RequireAuth>} />
|
||||
<Route path="/jobs" element={<RequireAuth><JobsPage /></RequireAuth>} />
|
||||
<Route path="/deployment" element={<RequireAuth><PatchDeploymentPage /></RequireAuth>} />
|
||||
<Route path="/maintenance" element={<RequireAuth><PlaceholderPage title="Maintenance Windows" /></RequireAuth>} />
|
||||
<Route path="/reports" element={<RequireAuth><PlaceholderPage title="Reports" /></RequireAuth>} />
|
||||
<Route path="/certificates" element={<RequireAuth><PlaceholderPage title="Certificates" /></RequireAuth>} />
|
||||
|
||||
Reference in New Issue
Block a user