hivectl/dashboard: add --paused / ?paused=1 to agent start
This commit is contained in:
parent
c0f59089d4
commit
af3976a76a
4 changed files with 118 additions and 16 deletions
|
|
@ -164,26 +164,64 @@ pub(super) async fn post_restart(
|
|||
(StatusCode::OK, "ok").into_response()
|
||||
}
|
||||
|
||||
/// `POST /api/start/{name}` — start `name`.
|
||||
/// Query params for `post_start`. `?paused=1` writes the pause marker
|
||||
/// before (or instead of) starting — see `post_start`'s doc.
|
||||
#[derive(Deserialize, IntoParams)]
|
||||
pub(super) struct StartParams {
|
||||
#[serde(default)]
|
||||
paused: bool,
|
||||
}
|
||||
|
||||
/// `POST /api/start/{name}?paused=1` — start `name`, optionally paused.
|
||||
///
|
||||
/// Plain `?paused=1` mirrors `hivectl agent <name> start --paused`: if
|
||||
/// `name` is already running, this just writes the pause marker in place
|
||||
/// and returns without submitting a start DAG (nothing to start). If it's
|
||||
/// down, the marker is written *before* the start DAG is submitted, so
|
||||
/// the container comes up paused rather than racing the harness's own
|
||||
/// pause-gate poll against an already-in-flight start.
|
||||
#[utoipa::path(
|
||||
post,
|
||||
path = "/api/start/{name}",
|
||||
params(("name" = String, Path, description = "agent name")),
|
||||
params(
|
||||
("name" = String, Path, description = "agent name"),
|
||||
StartParams,
|
||||
),
|
||||
responses(
|
||||
(status = 200, description = "start queued", body = String),
|
||||
(status = 200, description = "start queued (or paused in place)", body = String),
|
||||
(status = 400, description = "bad agent name"),
|
||||
(status = 404, description = "no such agent"),
|
||||
(status = 500, description = "pause marker write failed"),
|
||||
),
|
||||
tag = "lifecycle_ops"
|
||||
)]
|
||||
pub(super) async fn post_start(
|
||||
State(state): State<AppState>,
|
||||
AxumPath(name): AxumPath<String>,
|
||||
Query(params): Query<StartParams>,
|
||||
) -> Response {
|
||||
let logical = strip_container_prefix(&name);
|
||||
if let Some(reject) = guard_agent_name(&state, &logical).await {
|
||||
return reject;
|
||||
}
|
||||
if params.paused {
|
||||
let ident = match Ident::parse(&logical) {
|
||||
Ok(i) => i,
|
||||
Err(e) => {
|
||||
return (StatusCode::BAD_REQUEST, format!("bad agent name: {e}")).into_response();
|
||||
}
|
||||
};
|
||||
let already_running = lifecycle::is_running(&logical).await;
|
||||
if let Err(e) = crate::coordinator::Coordinator::set_paused(&ident, true).await {
|
||||
return error_response(&format!("pause {logical}: {e}"));
|
||||
}
|
||||
state.coord.rescan_containers_and_emit().await;
|
||||
if already_running {
|
||||
// Already up — pausing in place is the whole request, no DAG
|
||||
// to submit.
|
||||
return (StatusCode::OK, "ok").into_response();
|
||||
}
|
||||
}
|
||||
submit::start(
|
||||
&state.coord,
|
||||
&logical,
|
||||
|
|
|
|||
Loading…
Reference in a new issue