dashboard: return problem details directly from client-error handlers
This commit is contained in:
parent
2b0c51badf
commit
65ad994c85
8 changed files with 102 additions and 100 deletions
|
|
@ -15,7 +15,7 @@ use serde::Deserialize;
|
|||
|
||||
use problem_details::ProblemDetails;
|
||||
|
||||
use super::{error_response, strip_container_prefix, validate_agent_name};
|
||||
use super::{error_problem, strip_container_prefix, validate_agent_name};
|
||||
use crate::lifecycle;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
|
|
@ -36,13 +36,14 @@ pub(super) struct JournalQuery {
|
|||
pub(super) async fn get_journal(
|
||||
AxumPath(name): AxumPath<String>,
|
||||
axum::extract::Query(q): axum::extract::Query<JournalQuery>,
|
||||
) -> Response {
|
||||
) -> Result<Response, ProblemDetails> {
|
||||
// Defense-in-depth format check so weird chars never reach the
|
||||
// shellout below — the `lifecycle::list()` existence check would
|
||||
// catch them anyway, but rejecting at the boundary keeps the
|
||||
// failure mode crisp.
|
||||
if let Some(reason) = validate_agent_name(&name) {
|
||||
return (StatusCode::BAD_REQUEST, format!("bad agent name: {reason}")).into_response();
|
||||
return Err(ProblemDetails::from_status_code(StatusCode::BAD_REQUEST)
|
||||
.with_detail(format!("bad agent name: {reason}")));
|
||||
}
|
||||
// Validate the container name against the list of managed
|
||||
// containers so we don't shell out with arbitrary input.
|
||||
|
|
@ -50,9 +51,8 @@ pub(super) async fn get_journal(
|
|||
let prefixed = format!("{}{container}", lifecycle::AGENT_PREFIX);
|
||||
let live = lifecycle::list().await.unwrap_or_default();
|
||||
if !live.iter().any(|c| c == &prefixed) {
|
||||
return ProblemDetails::from_status_code(StatusCode::NOT_FOUND)
|
||||
.with_detail(format!("journal: no managed container {prefixed:?}"))
|
||||
.into_response();
|
||||
return Err(ProblemDetails::from_status_code(StatusCode::NOT_FOUND)
|
||||
.with_detail(format!("journal: no managed container {prefixed:?}")));
|
||||
}
|
||||
let lines = q.lines.unwrap_or(500).min(5000);
|
||||
let unit = match q.unit.as_deref().filter(|s| !s.is_empty()) {
|
||||
|
|
@ -65,9 +65,8 @@ pub(super) async fn get_journal(
|
|||
format!("{u}.service")
|
||||
};
|
||||
if !allowed.contains(&unit.as_str()) {
|
||||
return ProblemDetails::from_status_code(StatusCode::BAD_REQUEST)
|
||||
.with_detail(format!("journal: unknown unit {unit:?}"))
|
||||
.into_response();
|
||||
return Err(ProblemDetails::from_status_code(StatusCode::BAD_REQUEST)
|
||||
.with_detail(format!("journal: unknown unit {unit:?}")));
|
||||
}
|
||||
Some(unit)
|
||||
}
|
||||
|
|
@ -92,9 +91,9 @@ pub(super) async fn get_journal(
|
|||
body.push_str("\n--- stderr ---\n");
|
||||
body.push_str(&stderr);
|
||||
}
|
||||
([("content-type", "text/plain; charset=utf-8")], body).into_response()
|
||||
Ok(([("content-type", "text/plain; charset=utf-8")], body).into_response())
|
||||
}
|
||||
Err(e) => error_response(&format!("journal read: {e:#}")),
|
||||
Err(e) => Err(error_problem(&format!("journal read: {e:#}"))),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -114,7 +113,7 @@ pub(super) struct JournalHostQuery {
|
|||
/// dashboard binding to a host-only port.
|
||||
pub(super) async fn get_journal_host(
|
||||
axum::extract::Query(q): axum::extract::Query<JournalHostQuery>,
|
||||
) -> Response {
|
||||
) -> Result<Response, ProblemDetails> {
|
||||
let lines = q.lines.unwrap_or(500).min(5000);
|
||||
let allowed = ["hive-c0re.service"];
|
||||
let mut cmd = tokio::process::Command::new("journalctl");
|
||||
|
|
@ -127,9 +126,8 @@ pub(super) async fn get_journal_host(
|
|||
format!("{u}.service")
|
||||
};
|
||||
if !allowed.contains(&unit.as_str()) {
|
||||
return ProblemDetails::from_status_code(StatusCode::BAD_REQUEST)
|
||||
.with_detail(format!("journal-host: unknown unit {unit:?}"))
|
||||
.into_response();
|
||||
return Err(ProblemDetails::from_status_code(StatusCode::BAD_REQUEST)
|
||||
.with_detail(format!("journal-host: unknown unit {unit:?}")));
|
||||
}
|
||||
cmd.args(["-u", &unit]);
|
||||
}
|
||||
|
|
@ -140,8 +138,8 @@ pub(super) async fn get_journal_host(
|
|||
body.push_str("\n--- stderr ---\n");
|
||||
body.push_str(&String::from_utf8_lossy(&out.stderr));
|
||||
}
|
||||
([("content-type", "text/plain; charset=utf-8")], body).into_response()
|
||||
Ok(([("content-type", "text/plain; charset=utf-8")], body).into_response())
|
||||
}
|
||||
Err(e) => error_response(&format!("journalctl spawn: {e}")),
|
||||
Err(e) => Err(error_problem(&format!("journalctl spawn: {e}"))),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue