From 453f788e51fd5cd1194550da4dad02b910be1f71 Mon Sep 17 00:00:00 2001 From: Claas Date: Mon, 22 Dec 2025 00:43:13 +0100 Subject: [PATCH] Try to make life easier --- Cargo.lock | 48 +++++++++++++++------- bacon.toml | 7 ++++ tugboat/Cargo.toml | 2 +- tugboat/src/route/container/edit.rs | 4 +- tugboat/src/route/container/environment.rs | 8 ++-- tugboat/src/route/container/mod.rs | 34 ++++++++------- tugboat/src/route/error.rs | 32 +++++++++++++++ tugboat/src/route/mod.rs | 1 + tugboat/templates/container/index.html | 7 ++-- tugboat/templates/error.html | 22 ++++++++++ 10 files changed, 123 insertions(+), 42 deletions(-) create mode 100644 tugboat/src/route/error.rs create mode 100644 tugboat/templates/error.html diff --git a/Cargo.lock b/Cargo.lock index d337df8..04390a8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -795,10 +795,11 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.6" +version = "1.2.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d6dbb628b8f8555f86d0323c2eb39e3ec81901f4b83e091db8a6a76d316a333" +checksum = "9f50d563227a1c37cc0a263f64eca3334388c01c5e4c4861a9def205c614383c" dependencies = [ + "find-msvc-tools", "jobserver", "libc", "shlex", @@ -932,6 +933,15 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" +[[package]] +name = "cmake" +version = "0.1.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75443c44cd6b379beb8c5b45d85d0773baf31cce901fe7bb252f4eff3008ef7d" +dependencies = [ + "cc", +] + [[package]] name = "cobs" version = "0.2.3" @@ -1412,6 +1422,12 @@ version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" +[[package]] +name = "find-msvc-tools" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844" + [[package]] name = "flate2" version = "1.0.35" @@ -2377,9 +2393,9 @@ checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" [[package]] name = "libsql" -version = "0.6.0" +version = "0.9.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe18646e4ef8db446bc3e3f5fb96131483203bc5f4998ff149f79a067530c01c" +checksum = "2329faffc510cc3c6b4f00169a39177cc7099d3ed7647fc92f7cf26e53a8d976" dependencies = [ "anyhow", "async-stream", @@ -2388,6 +2404,8 @@ dependencies = [ "bincode", "bitflags 2.6.0", "bytes", + "chrono", + "crc32fast", "fallible-iterator 0.3.0", "futures", "http 0.2.12", @@ -2415,19 +2433,21 @@ dependencies = [ [[package]] name = "libsql-ffi" -version = "0.5.0" +version = "0.9.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f2a50a585a1184a43621a9133b7702ba5cb7a87ca5e704056b19d8005de6faf" +checksum = "6cd1c1662822495393327856774f6803be25d85bfdcd5b9d4af35458f5daaf75" dependencies = [ "bindgen", "cc", + "cmake", + "glob", ] [[package]] name = "libsql-hrana" -version = "0.2.0" +version = "0.9.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aeaf5d19e365465e1c23d687a28c805d7462531b3f619f0ba49d3cf369890a3e" +checksum = "646d0aa75e412769018422f0da798f72e93bd51964f0b2ddad4317aa779ae444" dependencies = [ "base64 0.21.7", "bytes", @@ -2437,9 +2457,9 @@ dependencies = [ [[package]] name = "libsql-rusqlite" -version = "0.33.0" +version = "0.9.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae65c66088dcd309abbd5617ae046abac2a2ee0a7fdada5127353bd68e0a27ea" +checksum = "5a4ce3a78c6e3c2b23b02ab6272df8340e1c53380497979d456882254f348d5f" dependencies = [ "bitflags 2.6.0", "fallible-iterator 0.2.0", @@ -2469,9 +2489,9 @@ dependencies = [ [[package]] name = "libsql-sys" -version = "0.8.0" +version = "0.9.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c05b61c226781d6f5e26e3e7364617f19c0c1d5332035802e9229d6024cec05" +checksum = "2a3c326fcfc36fe7578238d5ee6b58c529f8c76372acd61ec50267529cdaff95" dependencies = [ "bytes", "libsql-ffi", @@ -2483,9 +2503,9 @@ dependencies = [ [[package]] name = "libsql_replication" -version = "0.6.0" +version = "0.9.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf40c4c2c01462da758272976de0a23d19b4e9c714db08efecf262d896655b5" +checksum = "1d9a2e469ac8400659bd31f81a745908bcc5cb6b40be2f2ff8de90b15bec5501" dependencies = [ "aes", "async-stream", diff --git a/bacon.toml b/bacon.toml index 92d97d0..a7ca1d9 100644 --- a/bacon.toml +++ b/bacon.toml @@ -115,4 +115,11 @@ command = ["cargo", "run", "--package", "delivery-service"] need_stdout = true background = false on_change_strategy = "kill_then_restart" +watch = ["templates"] + +[jobs.tugboat] +command = ["cargo", "run", "--package", "tugboat"] +need_stdout = true +background = false +on_change_strategy = "kill_then_restart" watch = ["templates"] \ No newline at end of file diff --git a/tugboat/Cargo.toml b/tugboat/Cargo.toml index ce20c7b..93c486d 100644 --- a/tugboat/Cargo.toml +++ b/tugboat/Cargo.toml @@ -29,7 +29,7 @@ tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } uuid = "1.11.0" #TODO make this only available in development. Not needed in production. dotenvy = "0.15.7" -libsql = { version = "0.6.0", features = ["encryption"] } +libsql = { version = "0.9.29", features = ["encryption"] } nanoid = "0.4.0" getrandom = "0.2.15" hkdf = "0.12.4" diff --git a/tugboat/src/route/container/edit.rs b/tugboat/src/route/container/edit.rs index 44be036..048a7f8 100644 --- a/tugboat/src/route/container/edit.rs +++ b/tugboat/src/route/container/edit.rs @@ -9,7 +9,7 @@ use axum::{ use axum_extra::extract::Form; use serde::Deserialize; -use crate::{redirect_to, TugState}; +use crate::{redirect_to, route::error, TugState}; use super::{ get_container, @@ -132,7 +132,7 @@ pub(in crate::route) async fn create( state: State, Path(container_id): Path>, Form(request): Form, -) -> Result { +) -> Result { let new_container_id = modify( state, container_id, diff --git a/tugboat/src/route/container/environment.rs b/tugboat/src/route/container/environment.rs index 53d2766..f353c9a 100644 --- a/tugboat/src/route/container/environment.rs +++ b/tugboat/src/route/container/environment.rs @@ -12,7 +12,7 @@ use bollard::container::{self}; use serde::Deserialize; -use crate::{redirect_to, TugState}; +use crate::{redirect_to, route::error, TugState}; use super::{ get_container, @@ -56,7 +56,7 @@ impl IntoResponse for GetVariablesError { pub(in crate::route) async fn get_variables( State(state): State, Path(container_id): Path>, -) -> Result { +) -> Result { let container = get_container(&state.docker, &container_id).await?; let variables = container @@ -143,7 +143,7 @@ pub(in crate::route) async fn update( state: State, Path(container_id): Path>, Form(request): Form, -) -> Result { +) -> Result { let new_container_id = modify( state, container_id, @@ -169,7 +169,7 @@ pub(in crate::route) async fn delete( state: State, Path(container_id): Path>, Form(request): Form, -) -> Result { +) -> Result { let new_container_id = modify( state, container_id, diff --git a/tugboat/src/route/container/mod.rs b/tugboat/src/route/container/mod.rs index 96c8ed2..3e41393 100644 --- a/tugboat/src/route/container/mod.rs +++ b/tugboat/src/route/container/mod.rs @@ -24,7 +24,10 @@ use libsql::named_params; use serde::Deserialize; use tokio_stream::StreamExt; -use crate::{route::token::Token, TugState}; +use crate::{ + route::{error, token::Token}, + TugState, +}; use super::token; @@ -175,10 +178,12 @@ async fn get_images(docker: &Docker) -> Result>, bollard::errors::E pub(super) async fn get_index( State(state): State, -) -> Result { - IndexTemplate::from(&state.docker) +) -> Result { + let template = IndexTemplate::from(&state.docker) .await - .map_err(GetIndexError) + .map_err(GetIndexError)?; + + Ok(template) } #[derive(Deserialize)] @@ -218,13 +223,6 @@ pub(super) enum CreateError { GetIndexError(#[from] CreateIndexTemplateError), } -impl IntoResponse for CreateError { - fn into_response(self) -> Response { - tracing::error!("Error creating container: {:?}", self); - StatusCode::INTERNAL_SERVER_ERROR.into_response() - } -} - mod label { /// Tag to mark containers managed by tugboat pub(super) const TAG: &str = "moe.cla.tugboat.tugged"; @@ -315,7 +313,7 @@ async fn update_container_id( pub(super) async fn create( State(state): State, axum_extra::extract::Form(request): axum_extra::extract::Form, -) -> Result { +) -> Result { // Pull latest image tracing::debug!("Pulling image"); let options = Some(CreateImageOptions { @@ -422,7 +420,7 @@ pub(super) enum StatementError { pub(super) async fn create_token( State(state): State, Path(container_id): Path>, -) -> Result { +) -> Result { // Check if container exists let _container = get_container(&state.docker, &container_id).await?; @@ -431,7 +429,7 @@ pub(super) async fn create_token( let hash = token.hash()?; // Store hash in database - let mut statement = state + let statement = state .connection .prepare( "INSERT OR REPLACE INTO tokens (container_id, token_hash) VALUES (:container_id, :token_hash)", @@ -654,7 +652,7 @@ impl IntoResponse for StopError { pub(in crate::route) async fn stop_container( State(state): State, Path(container_id): Path>, -) -> Result { +) -> Result { tracing::debug!("Stopping container {container_id}"); state .docker @@ -678,7 +676,7 @@ impl IntoResponse for StartError { pub(in crate::route) async fn start_container( State(state): State, Path(container_id): Path>, -) -> Result { +) -> Result { tracing::debug!("Starting container {container_id}"); state .docker @@ -702,7 +700,7 @@ impl IntoResponse for DeleteError { pub(in crate::route) async fn delete( State(state): State, Path(container_id): Path>, -) -> Result { +) -> Result { tracing::debug!("Deleting container {container_id}"); state .docker @@ -715,7 +713,7 @@ pub(in crate::route) async fn delete( pub(in crate::route) async fn pull_update( state: State, path: Path>, -) -> Result { +) -> Result { update_image(state, path).await?; Ok(Redirect::to("/containers")) } diff --git a/tugboat/src/route/error.rs b/tugboat/src/route/error.rs new file mode 100644 index 0000000..2d8e21a --- /dev/null +++ b/tugboat/src/route/error.rs @@ -0,0 +1,32 @@ +use std::sync::Arc; + +use axum::http::StatusCode; + +#[derive(askama::Template)] +#[template(path = "error.html")] +pub(in crate::route) struct Template { + error: Arc, +} + +pub(in crate::route) struct Response { + template: Template, +} + +impl From for Response +where + E: std::error::Error + Send + Sync + 'static, +{ + fn from(error: E) -> Self { + Self { + template: Template { + error: Arc::from(format!("{error:#?}")), + }, + } + } +} + +impl axum::response::IntoResponse for Response { + fn into_response(self) -> askama_axum::Response { + (StatusCode::INTERNAL_SERVER_ERROR, self.template).into_response() + } +} diff --git a/tugboat/src/route/mod.rs b/tugboat/src/route/mod.rs index 33a5769..56ee19c 100644 --- a/tugboat/src/route/mod.rs +++ b/tugboat/src/route/mod.rs @@ -1,4 +1,5 @@ mod container; +mod error; mod middleware; mod token; diff --git a/tugboat/templates/container/index.html b/tugboat/templates/container/index.html index 19c0141..c6b4a29 100644 --- a/tugboat/templates/container/index.html +++ b/tugboat/templates/container/index.html @@ -19,20 +19,21 @@

Create Container

Ports -
diff --git a/tugboat/templates/error.html b/tugboat/templates/error.html new file mode 100644 index 0000000..b673078 --- /dev/null +++ b/tugboat/templates/error.html @@ -0,0 +1,22 @@ +{% extends "layout.html" %} + +{% block content %} + +
+ +

Error

+ +

An error occurred while processing your request.

+ +
{{ error }}
+ + Let's go home + +
+ +{% endblock %} + +{% block scripts %} +{% endblock %} + +{% call super() %} \ No newline at end of file -- 2.51.2