hive-c0re: annotate remaining dashboard routes with utoipa
This commit is contained in:
parent
8ebefeb0d5
commit
582ebe5eee
21 changed files with 738 additions and 45 deletions
|
|
@ -14,12 +14,13 @@ use axum::{
|
|||
response::{IntoResponse, Response},
|
||||
};
|
||||
use serde::Deserialize;
|
||||
use utoipa::{IntoParams, ToSchema};
|
||||
|
||||
/// Query params for `post_kill` / `post_restart`. `?graceful=1` routes to
|
||||
/// the graceful-stop/-restart orchestration (quiesce the harness, flush
|
||||
/// `/state`, then container stop/restart) instead of an immediate hard
|
||||
/// action. Defaults false → today's hard kill/restart.
|
||||
#[derive(Deserialize)]
|
||||
#[derive(Deserialize, IntoParams)]
|
||||
pub(super) struct GracefulParams {
|
||||
#[serde(default)]
|
||||
graceful: bool,
|
||||
|
|
@ -29,6 +30,18 @@ use super::{AppState, Ident, error_response, guard_agent_name, strip_container_p
|
|||
use crate::job_queue::{Source, submit};
|
||||
use crate::{actions, lifecycle};
|
||||
|
||||
/// `POST /api/rebuild/{name}` — queue a rebuild DAG for `name`.
|
||||
#[utoipa::path(
|
||||
post,
|
||||
path = "/api/rebuild/{name}",
|
||||
params(("name" = String, Path, description = "agent name")),
|
||||
responses(
|
||||
(status = 200, description = "rebuild queued", body = String),
|
||||
(status = 400, description = "bad agent name"),
|
||||
(status = 404, description = "no such agent"),
|
||||
),
|
||||
tag = "lifecycle_ops"
|
||||
)]
|
||||
pub(super) async fn post_rebuild(
|
||||
State(state): State<AppState>,
|
||||
AxumPath(name): AxumPath<String>,
|
||||
|
|
@ -46,6 +59,22 @@ pub(super) async fn post_rebuild(
|
|||
(StatusCode::OK, "ok").into_response()
|
||||
}
|
||||
|
||||
/// `POST /api/kill/{name}?graceful=1` — stop `name`, hard by default or
|
||||
/// gracefully (quiesce → drain → stop) when `graceful=1`.
|
||||
#[utoipa::path(
|
||||
post,
|
||||
path = "/api/kill/{name}",
|
||||
params(
|
||||
("name" = String, Path, description = "agent name"),
|
||||
GracefulParams,
|
||||
),
|
||||
responses(
|
||||
(status = 200, description = "stop queued/performed", body = String),
|
||||
(status = 400, description = "bad agent name"),
|
||||
(status = 404, description = "no such agent"),
|
||||
),
|
||||
tag = "lifecycle_ops"
|
||||
)]
|
||||
pub(super) async fn post_kill(
|
||||
State(state): State<AppState>,
|
||||
AxumPath(name): AxumPath<String>,
|
||||
|
|
@ -90,6 +119,22 @@ pub(super) async fn post_kill(
|
|||
(StatusCode::OK, "ok").into_response()
|
||||
}
|
||||
|
||||
/// `POST /api/restart/{name}?graceful=1` — restart `name`, hard by default
|
||||
/// or gracefully (quiesce → drain → restart) when `graceful=1`.
|
||||
#[utoipa::path(
|
||||
post,
|
||||
path = "/api/restart/{name}",
|
||||
params(
|
||||
("name" = String, Path, description = "agent name"),
|
||||
GracefulParams,
|
||||
),
|
||||
responses(
|
||||
(status = 200, description = "restart queued/performed", body = String),
|
||||
(status = 400, description = "bad agent name"),
|
||||
(status = 404, description = "no such agent"),
|
||||
),
|
||||
tag = "lifecycle_ops"
|
||||
)]
|
||||
pub(super) async fn post_restart(
|
||||
State(state): State<AppState>,
|
||||
AxumPath(name): AxumPath<String>,
|
||||
|
|
@ -119,6 +164,18 @@ pub(super) async fn post_restart(
|
|||
(StatusCode::OK, "ok").into_response()
|
||||
}
|
||||
|
||||
/// `POST /api/start/{name}` — start `name`.
|
||||
#[utoipa::path(
|
||||
post,
|
||||
path = "/api/start/{name}",
|
||||
params(("name" = String, Path, description = "agent name")),
|
||||
responses(
|
||||
(status = 200, description = "start queued", body = String),
|
||||
(status = 400, description = "bad agent name"),
|
||||
(status = 404, description = "no such agent"),
|
||||
),
|
||||
tag = "lifecycle_ops"
|
||||
)]
|
||||
pub(super) async fn post_start(
|
||||
State(state): State<AppState>,
|
||||
AxumPath(name): AxumPath<String>,
|
||||
|
|
@ -145,6 +202,18 @@ pub(super) async fn post_start(
|
|||
/// when the container next boots). Triggers an immediate rescan so the
|
||||
/// `paused` badge flips on the dashboard without waiting for the next
|
||||
/// periodic sweep.
|
||||
#[utoipa::path(
|
||||
post,
|
||||
path = "/api/pause/{name}",
|
||||
params(("name" = String, Path, description = "agent name")),
|
||||
responses(
|
||||
(status = 200, description = "pause marker written", body = String),
|
||||
(status = 400, description = "bad agent name"),
|
||||
(status = 404, description = "no such agent"),
|
||||
(status = 500, description = "marker write failed"),
|
||||
),
|
||||
tag = "lifecycle_ops"
|
||||
)]
|
||||
pub(super) async fn post_pause(
|
||||
State(state): State<AppState>,
|
||||
AxumPath(name): AxumPath<String>,
|
||||
|
|
@ -168,6 +237,18 @@ pub(super) async fn post_pause(
|
|||
///
|
||||
/// The inverse of `post_pause`. Removing a non-existent marker is a no-op
|
||||
/// (idempotent). Triggers an immediate rescan so the paused badge clears.
|
||||
#[utoipa::path(
|
||||
post,
|
||||
path = "/api/resume/{name}",
|
||||
params(("name" = String, Path, description = "agent name")),
|
||||
responses(
|
||||
(status = 200, description = "pause marker removed", body = String),
|
||||
(status = 400, description = "bad agent name"),
|
||||
(status = 404, description = "no such agent"),
|
||||
(status = 500, description = "marker removal failed"),
|
||||
),
|
||||
tag = "lifecycle_ops"
|
||||
)]
|
||||
pub(super) async fn post_resume(
|
||||
State(state): State<AppState>,
|
||||
AxumPath(name): AxumPath<String>,
|
||||
|
|
@ -190,7 +271,7 @@ pub(super) async fn post_resume(
|
|||
/// Form fields for `post_resource_limits`. Both fields are optional strings;
|
||||
/// an empty value clears the per-agent override for that field, falling back
|
||||
/// to the hive-wide default.
|
||||
#[derive(Deserialize, Default)]
|
||||
#[derive(Deserialize, Default, ToSchema)]
|
||||
pub(super) struct ResourceLimitsForm {
|
||||
#[serde(default)]
|
||||
cpu_quota: String,
|
||||
|
|
@ -207,6 +288,20 @@ pub(super) struct ResourceLimitsForm {
|
|||
/// limits take effect on the next container start or restart. Triggers an
|
||||
/// immediate rescan so `ContainerView.cpu_quota`/`memory_max` update on
|
||||
/// the dashboard via SSE without waiting for the next periodic sweep.
|
||||
#[utoipa::path(
|
||||
post,
|
||||
path = "/api/resource-limits/{name}",
|
||||
params(("name" = String, Path, description = "agent name")),
|
||||
request_body(content = ResourceLimitsForm, content_type = "application/x-www-form-urlencoded"),
|
||||
responses(
|
||||
(status = 200, description = "limits written", body = String),
|
||||
(status = 400, description = "bad agent name"),
|
||||
(status = 404, description = "no such agent"),
|
||||
(status = 422, description = "invalid cpu_quota/memory_max value"),
|
||||
(status = 500, description = "commit or drop-in write failed"),
|
||||
),
|
||||
tag = "lifecycle_ops"
|
||||
)]
|
||||
pub(super) async fn post_resource_limits(
|
||||
State(state): State<AppState>,
|
||||
AxumPath(name): AxumPath<String>,
|
||||
|
|
@ -257,6 +352,14 @@ pub(super) async fn post_resource_limits(
|
|||
(StatusCode::OK, "ok").into_response()
|
||||
}
|
||||
|
||||
/// `POST /api/update-all` — queue a rebuild DAG for every live agent
|
||||
/// container.
|
||||
#[utoipa::path(
|
||||
post,
|
||||
path = "/api/update-all",
|
||||
responses((status = 200, description = "rebuilds queued", body = String)),
|
||||
tag = "lifecycle_ops"
|
||||
)]
|
||||
pub(super) async fn post_update_all(State(state): State<AppState>) -> Response {
|
||||
let containers = lifecycle::list().await.unwrap_or_default();
|
||||
for container in containers {
|
||||
|
|
@ -276,12 +379,28 @@ pub(super) async fn post_update_all(State(state): State<AppState>) -> Response {
|
|||
(StatusCode::OK, "ok").into_response()
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Default)]
|
||||
#[derive(Deserialize, Default, ToSchema)]
|
||||
pub(super) struct DestroyForm {
|
||||
#[serde(default)]
|
||||
purge: Option<String>,
|
||||
}
|
||||
|
||||
/// `POST /api/destroy/{name}` — destroy `name`'s container. Form field
|
||||
/// `purge` (any non-empty value, e.g. `"on"`) also wipes the retained
|
||||
/// state dir instead of leaving a tombstone.
|
||||
#[utoipa::path(
|
||||
post,
|
||||
path = "/api/destroy/{name}",
|
||||
params(("name" = String, Path, description = "agent name")),
|
||||
request_body(content = DestroyForm, content_type = "application/x-www-form-urlencoded"),
|
||||
responses(
|
||||
(status = 200, description = "destroyed", body = String),
|
||||
(status = 400, description = "bad agent name"),
|
||||
(status = 404, description = "no such agent"),
|
||||
(status = 500, description = "destroy failed"),
|
||||
),
|
||||
tag = "lifecycle_ops"
|
||||
)]
|
||||
pub(super) async fn post_destroy(
|
||||
State(state): State<AppState>,
|
||||
AxumPath(name): AxumPath<String>,
|
||||
|
|
|
|||
Loading…
Reference in a new issue