Extract methods to separate files
This commit is contained in:
parent
38fe58ea9b
commit
1d7b09f92a
3 changed files with 74 additions and 66 deletions
58
src/dokku.rs
Normal file
58
src/dokku.rs
Normal file
|
@ -0,0 +1,58 @@
|
|||
use async_std::fs::read_to_string;
|
||||
use async_std::path::PathBuf;
|
||||
use serde::Serialize;
|
||||
use std::collections::HashSet;
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct DokkuApp {
|
||||
name: String,
|
||||
hosts: HashSet<String>,
|
||||
}
|
||||
|
||||
impl DokkuApp {
|
||||
pub async fn try_from_path(path: PathBuf) -> Option<Self> {
|
||||
let vhost_path = path.join("VHOST");
|
||||
|
||||
if !vhost_path.is_file().await {
|
||||
return None;
|
||||
}
|
||||
|
||||
let current_vhosts = read_to_string(&vhost_path).await.ok()?;
|
||||
|
||||
if current_vhosts.is_empty() {
|
||||
return None;
|
||||
}
|
||||
|
||||
Some(DokkuApp {
|
||||
name: String::from(path.file_name()?.to_str()?),
|
||||
hosts: current_vhosts.lines().map(String::from).collect(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_dokku_root() -> Option<std::path::PathBuf> {
|
||||
// First, check if we have a custom directory
|
||||
if let Some(dokku_root) = std::env::var_os("DOKKU_ROOT") {
|
||||
return Some(std::path::PathBuf::from(dokku_root));
|
||||
}
|
||||
|
||||
// Next, check for a dokku user and its home directory
|
||||
match nix::unistd::User::from_name("dokku") {
|
||||
Ok(Some(user)) => return Some(user.dir),
|
||||
|
||||
// If the user doesn't exist, do nothing
|
||||
Ok(None) => return None,
|
||||
|
||||
// If there was an error, give up
|
||||
_ => {}
|
||||
}
|
||||
|
||||
// Finally, try a hard-coded path
|
||||
let dokku_home_guess = std::path::PathBuf::from("/home/dokku");
|
||||
if dokku_home_guess.is_dir() {
|
||||
return Some(dokku_home_guess);
|
||||
}
|
||||
|
||||
// If there's nothing else, give up
|
||||
None
|
||||
}
|
73
src/main.rs
73
src/main.rs
|
@ -1,79 +1,20 @@
|
|||
use async_std::fs::read_to_string;
|
||||
use async_std::path::PathBuf;
|
||||
use async_std::stream::StreamExt;
|
||||
use axum::extract::State;
|
||||
use axum::{routing::get, Router};
|
||||
use serde::Serialize;
|
||||
use std::collections::HashSet;
|
||||
use std::net::{IpAddr, Ipv6Addr, SocketAddr};
|
||||
use tokio::task::JoinSet;
|
||||
|
||||
mod dokku;
|
||||
mod utils;
|
||||
|
||||
use dokku::DokkuApp;
|
||||
|
||||
#[derive(Clone)]
|
||||
struct AppState {
|
||||
dokku_root: PathBuf,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
struct DokkuApp {
|
||||
name: String,
|
||||
hosts: HashSet<String>,
|
||||
}
|
||||
|
||||
impl DokkuApp {
|
||||
async fn try_from_path(path: PathBuf) -> Option<Self> {
|
||||
let vhost_path = path.join("VHOST");
|
||||
|
||||
if !vhost_path.is_file().await {
|
||||
return None;
|
||||
}
|
||||
|
||||
let current_vhosts = read_to_string(&vhost_path).await.ok()?;
|
||||
|
||||
if current_vhosts.is_empty() {
|
||||
return None;
|
||||
}
|
||||
|
||||
Some(DokkuApp {
|
||||
name: String::from(path.file_name()?.to_str()?),
|
||||
hosts: current_vhosts.lines().map(String::from).collect(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn get_dokku_root() -> Option<std::path::PathBuf> {
|
||||
// First, check if we have a custom directory
|
||||
if let Some(dokku_root) = std::env::var_os("DOKKU_ROOT") {
|
||||
return Some(std::path::PathBuf::from(dokku_root));
|
||||
}
|
||||
|
||||
// Next, check for a dokku user and its home directory
|
||||
match nix::unistd::User::from_name("dokku") {
|
||||
Ok(Some(user)) => return Some(user.dir),
|
||||
|
||||
// If the user doesn't exist, do nothing
|
||||
Ok(None) => return None,
|
||||
|
||||
// If there was an error, give up
|
||||
_ => {}
|
||||
}
|
||||
|
||||
// Finally, try a hard-coded path
|
||||
let dokku_home_guess = std::path::PathBuf::from("/home/dokku");
|
||||
if dokku_home_guess.is_dir() {
|
||||
return Some(dokku_home_guess);
|
||||
}
|
||||
|
||||
// If there's nothing else, give up
|
||||
None
|
||||
}
|
||||
|
||||
fn osstring_starts_with(data: std::ffi::OsString, prefix: char) -> bool {
|
||||
match data.into_string() {
|
||||
Ok(s) => matches!(s.chars().next(), Some(c) if c == prefix),
|
||||
Err(_) => false,
|
||||
}
|
||||
}
|
||||
|
||||
async fn hosts(State(state): State<AppState>) -> axum::Json<Vec<DokkuApp>> {
|
||||
let mut dir_entries = state.dokku_root.read_dir().await.unwrap();
|
||||
|
||||
|
@ -81,7 +22,7 @@ async fn hosts(State(state): State<AppState>) -> axum::Json<Vec<DokkuApp>> {
|
|||
|
||||
while let Some(Ok(dir_entry)) = dir_entries.next().await {
|
||||
// Skip hidden folders / files
|
||||
if osstring_starts_with(dir_entry.file_name(), '.') {
|
||||
if utils::osstring_starts_with(dir_entry.file_name(), '.') {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -107,7 +48,7 @@ async fn hosts(State(state): State<AppState>) -> axum::Json<Vec<DokkuApp>> {
|
|||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
let dokku_root = match get_dokku_root() {
|
||||
let dokku_root = match dokku::get_dokku_root() {
|
||||
Some(path) => path,
|
||||
None => {
|
||||
println!("Failed to find dokku root");
|
||||
|
|
9
src/utils.rs
Normal file
9
src/utils.rs
Normal file
|
@ -0,0 +1,9 @@
|
|||
use std::ffi::OsString;
|
||||
|
||||
#[inline]
|
||||
pub fn osstring_starts_with(data: OsString, prefix: char) -> bool {
|
||||
match data.into_string() {
|
||||
Ok(s) => matches!(s.chars().next(), Some(c) if c == prefix),
|
||||
Err(_) => false,
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue