Update archipelago: API, auth, container, parmanode, performance, security
- API handler, RPC, and server updates - Auth and coding rules - Container data manager, dev orchestrator, health monitor, podman client - Parmanode script runner - Performance resource manager - Security container policies and secrets manager - Add build scripts and documentation
This commit is contained in:
@@ -1,15 +1,12 @@
|
||||
use crate::api::rpc::RpcHandler;
|
||||
use crate::config::Config;
|
||||
use anyhow::Result;
|
||||
use http_body_util::{BodyExt, Full};
|
||||
use hyper::body::Bytes;
|
||||
use hyper::{Method, Request, Response, StatusCode};
|
||||
use hyper_util::rt::TokioIo;
|
||||
use std::sync::Arc;
|
||||
use tracing::debug;
|
||||
|
||||
pub struct ApiHandler {
|
||||
config: Config,
|
||||
_config: Config,
|
||||
rpc_handler: Arc<RpcHandler>,
|
||||
// Add other handlers here (websocket, static files, etc.)
|
||||
}
|
||||
@@ -19,28 +16,26 @@ impl ApiHandler {
|
||||
let rpc_handler = Arc::new(RpcHandler::new(config.clone()).await?);
|
||||
|
||||
Ok(Self {
|
||||
config,
|
||||
_config: config,
|
||||
rpc_handler,
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn handle_request(
|
||||
&self,
|
||||
req: Request<http_body_util::Incoming>,
|
||||
) -> Result<Response<Full<Bytes>>> {
|
||||
req: Request<hyper::Body>,
|
||||
) -> Result<Response<hyper::Body>> {
|
||||
// Extract path and method before consuming req
|
||||
let path = req.uri().path().to_string();
|
||||
let method = req.method().clone();
|
||||
|
||||
// Convert body to bytes using http_body_util::BodyExt
|
||||
// Convert body to bytes
|
||||
let (parts, body) = req.into_parts();
|
||||
use http_body_util::BodyExt;
|
||||
let collected: http_body_util::Collected<Bytes> = body.collect().await
|
||||
.map_err(|_e| anyhow::anyhow!("Failed to read body"))?;
|
||||
let body_bytes = collected.to_bytes();
|
||||
let body_bytes = hyper::body::to_bytes(body).await
|
||||
.map_err(|e| anyhow::anyhow!("Failed to read body: {}", e))?;
|
||||
|
||||
// Reconstruct request with Full<Bytes> body for RPC handler
|
||||
let req_with_bytes = Request::from_parts(parts, Full::new(body_bytes));
|
||||
// Reconstruct request with body as Bytes for RPC handler
|
||||
let req_with_bytes = Request::from_parts(parts, hyper::Body::from(body_bytes));
|
||||
|
||||
debug!("{} {}", method, path);
|
||||
|
||||
@@ -52,13 +47,13 @@ impl ApiHandler {
|
||||
(Method::GET, "/health") => {
|
||||
Ok(Response::builder()
|
||||
.status(StatusCode::OK)
|
||||
.body(Full::new(Bytes::from("OK")))
|
||||
.body(hyper::Body::from("OK"))
|
||||
.unwrap())
|
||||
}
|
||||
_ => {
|
||||
Ok(Response::builder()
|
||||
.status(StatusCode::NOT_FOUND)
|
||||
.body(Full::new(Bytes::from("Not Found")))
|
||||
.body(hyper::Body::from("Not Found"))
|
||||
.unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,4 +2,3 @@ mod handler;
|
||||
mod rpc;
|
||||
|
||||
pub use handler::ApiHandler;
|
||||
pub use rpc::RpcHandler;
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
use crate::config::Config;
|
||||
use crate::container::DevContainerOrchestrator;
|
||||
use anyhow::{Context, Result};
|
||||
use http_body_util::{BodyExt, Full};
|
||||
use hyper::body::Bytes;
|
||||
use hyper::{Request, Response, StatusCode};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::RwLock;
|
||||
use tracing::{debug, error};
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
@@ -29,7 +26,7 @@ struct RpcError {
|
||||
}
|
||||
|
||||
pub struct RpcHandler {
|
||||
config: Config,
|
||||
_config: Config,
|
||||
orchestrator: Option<Arc<DevContainerOrchestrator>>,
|
||||
}
|
||||
|
||||
@@ -44,22 +41,19 @@ impl RpcHandler {
|
||||
};
|
||||
|
||||
Ok(Self {
|
||||
config,
|
||||
_config: config,
|
||||
orchestrator,
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn handle(
|
||||
&self,
|
||||
req: Request<Full<Bytes>>,
|
||||
) -> Result<Response<Full<Bytes>>> {
|
||||
// Read request body - Full<Bytes> is already collected
|
||||
req: Request<hyper::Body>,
|
||||
) -> Result<Response<hyper::Body>> {
|
||||
// Read request body
|
||||
let (_, body) = req.into_parts();
|
||||
// Full<Bytes> implements Body, collect it to get the bytes
|
||||
use http_body_util::BodyExt;
|
||||
let collected = body.collect().await
|
||||
.context("Failed to collect body")?;
|
||||
let body_bytes = collected.to_bytes();
|
||||
let body_bytes = hyper::body::to_bytes(body).await
|
||||
.context("Failed to read body")?;
|
||||
|
||||
let rpc_req: RpcRequest = serde_json::from_slice(&body_bytes)
|
||||
.context("Invalid RPC request")?;
|
||||
@@ -108,7 +102,7 @@ impl RpcHandler {
|
||||
Ok(Response::builder()
|
||||
.status(StatusCode::OK)
|
||||
.header("Content-Type", "application/json")
|
||||
.body(Full::new(Bytes::from(body)))
|
||||
.body(hyper::Body::from(body))
|
||||
.unwrap())
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ use serde::{Deserialize, Serialize};
|
||||
use std::path::PathBuf;
|
||||
use tokio::fs;
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct User {
|
||||
pub password_hash: String,
|
||||
@@ -13,10 +14,12 @@ pub struct User {
|
||||
pub onboarding_complete: bool,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub struct AuthManager {
|
||||
data_dir: PathBuf,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
impl AuthManager {
|
||||
pub fn new(data_dir: PathBuf) -> Self {
|
||||
Self { data_dir }
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use anyhow::{Context, Result};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::path::PathBuf;
|
||||
use tokio::fs;
|
||||
|
||||
pub struct DevDataManager {
|
||||
@@ -66,6 +66,7 @@ impl DevDataManager {
|
||||
}
|
||||
|
||||
/// Get all app data directories
|
||||
#[allow(dead_code)]
|
||||
pub async fn list_app_data_dirs(&self) -> Result<Vec<String>> {
|
||||
if !self.dev_data_dir.exists() {
|
||||
return Ok(vec![]);
|
||||
|
||||
@@ -3,9 +3,7 @@ use archipelago_container::{
|
||||
ContainerStatus, PortManager,
|
||||
};
|
||||
use anyhow::{Context, Result};
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
use crate::config::{Config, ContainerRuntime, BitcoinSimulation};
|
||||
use crate::container::data_manager::DevDataManager;
|
||||
@@ -65,7 +63,7 @@ impl DevContainerOrchestrator {
|
||||
pub async fn install_container(
|
||||
&self,
|
||||
manifest: &AppManifest,
|
||||
manifest_path: &str,
|
||||
_manifest_path: &str,
|
||||
) -> Result<String> {
|
||||
let app_id = &manifest.app.id;
|
||||
let container_name = format!("archipelago-{}-dev", app_id);
|
||||
@@ -251,11 +249,13 @@ impl DevContainerOrchestrator {
|
||||
}
|
||||
|
||||
/// Get port mapping for an app
|
||||
#[allow(dead_code)]
|
||||
pub fn get_port_mapping(&self, app_id: &str) -> Option<Vec<u16>> {
|
||||
self.port_manager.get_port_mapping(app_id)
|
||||
}
|
||||
|
||||
/// Get Bitcoin simulator
|
||||
#[allow(dead_code)]
|
||||
pub fn bitcoin_simulator(&self) -> &Arc<BitcoinSimulator> {
|
||||
&self.bitcoin_simulator
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
pub mod data_manager;
|
||||
pub mod dev_orchestrator;
|
||||
|
||||
pub use data_manager::DevDataManager;
|
||||
pub use dev_orchestrator::DevContainerOrchestrator;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
use anyhow::Result;
|
||||
use std::net::SocketAddr;
|
||||
use tracing::{info, error};
|
||||
use tracing::info;
|
||||
|
||||
mod api;
|
||||
mod auth;
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
use crate::api::ApiHandler;
|
||||
use crate::config::Config;
|
||||
use anyhow::Result;
|
||||
use hyper_util::rt::TokioIo;
|
||||
use hyper_util::server::conn::auto::Builder as AutoBuilder;
|
||||
use hyper::server::conn::Http;
|
||||
use hyper::service::service_fn;
|
||||
use std::net::SocketAddr;
|
||||
use std::sync::Arc;
|
||||
use tokio::net::TcpListener;
|
||||
use hyper::service::service_fn;
|
||||
use tracing::{error, info};
|
||||
use tracing::error;
|
||||
|
||||
pub struct Server {
|
||||
config: Config,
|
||||
_config: Config,
|
||||
api_handler: Arc<ApiHandler>,
|
||||
}
|
||||
|
||||
@@ -19,7 +18,7 @@ impl Server {
|
||||
let api_handler = Arc::new(ApiHandler::new(config.clone()).await?);
|
||||
|
||||
Ok(Self {
|
||||
config,
|
||||
_config: config,
|
||||
api_handler,
|
||||
})
|
||||
}
|
||||
@@ -36,7 +35,6 @@ impl Server {
|
||||
}
|
||||
};
|
||||
|
||||
let io = TokioIo::new(stream);
|
||||
let handler = self.api_handler.clone();
|
||||
|
||||
tokio::spawn(async move {
|
||||
@@ -48,14 +46,8 @@ impl Server {
|
||||
}
|
||||
});
|
||||
|
||||
let mut builder = AutoBuilder::new(
|
||||
hyper_util::rt::TokioExecutor::new()
|
||||
);
|
||||
// Use HTTP/1.1 only for now
|
||||
builder = builder.http1_only();
|
||||
|
||||
if let Err(e) = builder
|
||||
.serve_connection(io, service)
|
||||
if let Err(e) = Http::new()
|
||||
.serve_connection(stream, service)
|
||||
.await
|
||||
{
|
||||
error!("Error serving connection from {}: {}", peer_addr, e);
|
||||
|
||||
Reference in New Issue
Block a user