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:
@ -1,6 +1,7 @@
|
||||
import axios, { type AxiosError } from 'axios'
|
||||
import type { InternalAxiosRequestConfig } from 'axios'
|
||||
import { useAuthStore } from '../store/authStore'
|
||||
import type { FleetStatus, CreateJobRequest } from '../types'
|
||||
|
||||
const BASE_URL = '/api/v1'
|
||||
|
||||
@ -93,3 +94,32 @@ export const authApi = {
|
||||
verifyMfa: (secretBase32: string, code: string) =>
|
||||
apiClient.post('/auth/mfa/verify', { secret_base32: secretBase32, code }),
|
||||
}
|
||||
|
||||
// ── Fleet API functions ──────────────────────────────────────────────────────
|
||||
export const fleetApi = {
|
||||
getStatus: () => apiClient.get<FleetStatus>('/status/fleet'),
|
||||
}
|
||||
|
||||
// ── Hosts API functions ──────────────────────────────────────────────────────
|
||||
export const hostsApi = {
|
||||
list: (params?: Record<string, unknown>) => apiClient.get('/hosts', { params }),
|
||||
get: (id: string) => apiClient.get(`/hosts/${id}`),
|
||||
delete: (id: string) => apiClient.delete(`/hosts/${id}`),
|
||||
refresh: (id: string) => apiClient.post(`/hosts/${id}/refresh`),
|
||||
}
|
||||
|
||||
// ── Jobs API ─────────────────────────────────────────────────────────────────
|
||||
export const jobsApi = {
|
||||
list: (params?: Record<string, unknown>) => apiClient.get('/jobs', { params }),
|
||||
get: (id: string) => apiClient.get(`/jobs/${id}`),
|
||||
create: (body: CreateJobRequest) => apiClient.post('/jobs', body),
|
||||
cancel: (id: string) => apiClient.post(`/jobs/${id}/cancel`),
|
||||
rollback: (id: string) => apiClient.post(`/jobs/${id}/rollback`),
|
||||
}
|
||||
|
||||
// ── Patches API (per-host patch listing) ──────────────────────────────────────
|
||||
export const patchesApi = {
|
||||
// Returns patches available on a specific host via the manager's proxy
|
||||
// The backend reads from host_patch_data table (cached from agent poll)
|
||||
getHostPatches: (hostId: string) => apiClient.get(`/hosts/${hostId}/patches`),
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user