74 lines
1.7 KiB
Rust
74 lines
1.7 KiB
Rust
use async_std::path::PathBuf;
|
|
use async_std::stream::StreamExt;
|
|
use axum::extract::State;
|
|
use axum::{routing::get, Router};
|
|
use std::net::SocketAddr;
|
|
use tokio::task::JoinSet;
|
|
|
|
mod dokku;
|
|
mod utils;
|
|
|
|
use dokku::DokkuApp;
|
|
|
|
#[derive(Clone)]
|
|
struct AppState {
|
|
dokku_root: PathBuf,
|
|
}
|
|
|
|
async fn hosts(State(state): State<AppState>) -> axum::Json<Vec<DokkuApp>> {
|
|
let mut dir_entries = state.dokku_root.read_dir().await.unwrap();
|
|
|
|
let mut join_set = JoinSet::new();
|
|
|
|
while let Some(Ok(dir_entry)) = dir_entries.next().await {
|
|
// Skip hidden folders / files
|
|
if utils::osstring_starts_with(dir_entry.file_name(), '.') {
|
|
continue;
|
|
}
|
|
|
|
let path = dir_entry.path();
|
|
|
|
if !path.is_dir().await {
|
|
continue;
|
|
}
|
|
|
|
join_set.spawn(DokkuApp::try_from_path(path));
|
|
}
|
|
|
|
let mut apps: Vec<DokkuApp> = Vec::new();
|
|
|
|
while let Some(res) = join_set.join_next().await {
|
|
if let Some(app) = res.unwrap() {
|
|
apps.push(app)
|
|
}
|
|
}
|
|
|
|
axum::Json(apps)
|
|
}
|
|
|
|
#[tokio::main]
|
|
async fn main() {
|
|
let dokku_root = match dokku::get_dokku_root() {
|
|
Some(path) => path,
|
|
None => {
|
|
println!("Failed to find dokku root");
|
|
std::process::exit(1);
|
|
}
|
|
};
|
|
|
|
println!("Using dokku root: {}", dokku_root.display());
|
|
|
|
let state = AppState {
|
|
dokku_root: PathBuf::from(dokku_root),
|
|
};
|
|
|
|
let app = Router::new().route("/hosts", get(hosts)).with_state(state);
|
|
|
|
let addr = &SocketAddr::new(utils::get_bind_host(), utils::get_port());
|
|
println!("Listening on {addr}");
|
|
axum::Server::bind(addr)
|
|
.serve(app.into_make_service())
|
|
.await
|
|
.unwrap();
|
|
}
|