kube-rs gateway (nodes, namespaces, deployments/statefulsets/daemonsets with images, PVCs; rollout restart, scale, set image via patches) using the microk8s kubeconfig by default, fake gateway for dev, /api/cluster routes, Kubernetes page with node cards, workload table with admin actions and PVC list. Also implements the streaming command runner that WP-11 relied on. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
96 lines
2.6 KiB
Rust
96 lines
2.6 KiB
Rust
//! Helpers to build a fully wired app on an in-memory database for integration tests.
|
|
use std::sync::{Arc, Mutex};
|
|
|
|
use application::{JobHandler, JobLog, JobRunner};
|
|
use async_trait::async_trait;
|
|
use axum::Router;
|
|
use domain::ports::Mailer;
|
|
use domain::settings::SmtpSettings;
|
|
use domain::DomainError;
|
|
|
|
use crate::{build_app, AppState, Config};
|
|
|
|
pub fn test_config() -> Config {
|
|
Config {
|
|
database_url: "sqlite::memory:".into(),
|
|
jwt_secret: "test-secret-test-secret-test-secret-1234".into(),
|
|
master_key: "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f".into(),
|
|
fake_host: true,
|
|
kubeconfig: None,
|
|
bind: "127.0.0.1:0".parse().unwrap(),
|
|
bootstrap_admin: None,
|
|
cookie_secure: false,
|
|
frontend_dir: "/nonexistent".into(),
|
|
}
|
|
}
|
|
|
|
/// Mails "sent" by all test apps of this process.
|
|
static SENT: Mutex<Vec<(Vec<String>, String, String)>> = Mutex::new(Vec::new());
|
|
|
|
pub struct RecordingMailer;
|
|
|
|
#[async_trait]
|
|
impl Mailer for RecordingMailer {
|
|
async fn send(
|
|
&self,
|
|
_: &SmtpSettings,
|
|
to: &[String],
|
|
subject: &str,
|
|
body: &str,
|
|
) -> Result<(), DomainError> {
|
|
SENT.lock()
|
|
.unwrap()
|
|
.push((to.to_vec(), subject.into(), body.into()));
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
pub fn sent_mails(_app: &Router) -> Vec<(Vec<String>, String, String)> {
|
|
SENT.lock().unwrap().clone()
|
|
}
|
|
|
|
/// Test handler for kinds without a real implementation yet.
|
|
pub struct TestJob;
|
|
|
|
#[async_trait]
|
|
impl JobHandler for TestJob {
|
|
async fn run(&self, _params: Option<String>, log: &dyn JobLog) -> Result<(), String> {
|
|
log.line("test handler ran").await;
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
pub fn register_test_jobs(runner: JobRunner) -> JobRunner {
|
|
runner
|
|
}
|
|
|
|
pub async fn build_test_app() -> Router {
|
|
build_test_app_with(test_config()).await
|
|
}
|
|
|
|
pub async fn build_test_app_with_admin(email: &str, password: &str) -> Router {
|
|
let cfg = Config {
|
|
bootstrap_admin: Some((email.into(), password.into())),
|
|
..test_config()
|
|
};
|
|
build_test_app_with(cfg).await
|
|
}
|
|
|
|
async fn build_test_app_with(cfg: Config) -> Router {
|
|
let pool = infrastructure::connect(&cfg.database_url)
|
|
.await
|
|
.expect("db");
|
|
let state = AppState::with_adapters(
|
|
cfg,
|
|
pool,
|
|
Arc::new(RecordingMailer),
|
|
Arc::new(infrastructure::FakeHostInspector),
|
|
Arc::new(infrastructure::FakeHostUpdater),
|
|
Arc::new(infrastructure::FakeClusterGateway),
|
|
register_test_jobs,
|
|
)
|
|
.expect("state");
|
|
state.bootstrap().await.expect("bootstrap");
|
|
build_app(state)
|
|
}
|