Implement /api/runner/status
This commit is contained in:
parent
5c8c037417
commit
c713abc5d3
11 changed files with 296 additions and 29 deletions
91
src/server/web/api.rs
Normal file
91
src/server/web/api.rs
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
mod auth;
|
||||
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use askama_axum::{IntoResponse, Response};
|
||||
use axum::{
|
||||
extract::State,
|
||||
headers::{authorization::Basic, Authorization},
|
||||
http::StatusCode,
|
||||
routing::post,
|
||||
Json, Router, TypedHeader,
|
||||
};
|
||||
use sqlx::SqlitePool;
|
||||
use time::OffsetDateTime;
|
||||
|
||||
use crate::{
|
||||
config::Config,
|
||||
server::{
|
||||
runners::{RunnerInfo, Runners},
|
||||
BenchRepo, Server,
|
||||
},
|
||||
shared::{BenchMethod, RunnerRequest, ServerResponse, Work},
|
||||
somehow,
|
||||
};
|
||||
|
||||
async fn post_status(
|
||||
TypedHeader(auth): TypedHeader<Authorization<Basic>>,
|
||||
State(config): State<&'static Config>,
|
||||
State(db): State<SqlitePool>,
|
||||
State(bench_repo): State<Option<BenchRepo>>,
|
||||
State(runners): State<Arc<Mutex<Runners>>>,
|
||||
Json(request): Json<RunnerRequest>,
|
||||
) -> somehow::Result<Response> {
|
||||
let name = match auth::authenticate(config, auth) {
|
||||
Ok(name) => name,
|
||||
Err(response) => return Ok(response),
|
||||
};
|
||||
|
||||
let now = OffsetDateTime::now_utc();
|
||||
let queue = sqlx::query_scalar!(
|
||||
"\
|
||||
SELECT hash FROM queue \
|
||||
ORDER BY priority DESC, unixepoch(date) DESC, hash ASC \
|
||||
"
|
||||
)
|
||||
.fetch_all(&db)
|
||||
.await?;
|
||||
|
||||
let mut guard = runners.lock().unwrap();
|
||||
guard.clean(now);
|
||||
if !guard.verify(&name, &request.secret) {
|
||||
return Ok((StatusCode::UNAUTHORIZED, "invalid secret").into_response());
|
||||
}
|
||||
guard.update(
|
||||
name.clone(),
|
||||
RunnerInfo::new(request.secret, now, request.status),
|
||||
);
|
||||
let work = match request.request_work {
|
||||
true => guard.find_free_work(&queue),
|
||||
false => None,
|
||||
};
|
||||
let abort_work = guard.should_abort_work(&name);
|
||||
drop(guard);
|
||||
|
||||
// Find new work
|
||||
let work = if let Some(hash) = work {
|
||||
let bench = match bench_repo {
|
||||
Some(bench_repo) => BenchMethod::BenchRepo {
|
||||
hash: bench_repo.0.to_thread_local().head_id()?.to_string(),
|
||||
},
|
||||
None => BenchMethod::Internal,
|
||||
};
|
||||
Some(Work {
|
||||
hash: hash.to_string(),
|
||||
bench,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
Ok(Json(ServerResponse { work, abort_work }).into_response())
|
||||
}
|
||||
|
||||
pub fn router(server: &Server) -> Router<Server> {
|
||||
if server.repo.is_none() {
|
||||
return Router::new().route("/api/runner/status", post(post_status));
|
||||
}
|
||||
|
||||
// TODO Add routes
|
||||
Router::new()
|
||||
}
|
||||
41
src/server/web/api/auth.rs
Normal file
41
src/server/web/api/auth.rs
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
use askama_axum::IntoResponse;
|
||||
use axum::{
|
||||
headers::{authorization::Basic, Authorization},
|
||||
http::{header, HeaderValue, StatusCode},
|
||||
response::Response,
|
||||
};
|
||||
|
||||
use crate::config::Config;
|
||||
|
||||
fn is_username_valid(username: &str) -> bool {
|
||||
if username.is_empty() {
|
||||
return false;
|
||||
}
|
||||
|
||||
username
|
||||
.chars()
|
||||
.all(|c| c.is_ascii_alphanumeric() || c == '-' || c == '_' || c == '.')
|
||||
}
|
||||
|
||||
fn is_password_valid(password: &str, config: &'static Config) -> bool {
|
||||
password == config.web_runner_token
|
||||
}
|
||||
|
||||
pub fn authenticate(
|
||||
config: &'static Config,
|
||||
auth: Authorization<Basic>,
|
||||
) -> Result<String, Response> {
|
||||
if is_username_valid(auth.username()) && is_password_valid(auth.password(), config) {
|
||||
return Ok(auth.username().to_string());
|
||||
}
|
||||
|
||||
Err((
|
||||
StatusCode::UNAUTHORIZED,
|
||||
[(
|
||||
header::WWW_AUTHENTICATE,
|
||||
HeaderValue::from_str("Basic realm=\"runner api\"").unwrap(),
|
||||
)],
|
||||
"invalid credentials",
|
||||
)
|
||||
.into_response())
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue