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::path::PathBuf;
|
||||||
use async_std::stream::StreamExt;
|
use async_std::stream::StreamExt;
|
||||||
use axum::extract::State;
|
use axum::extract::State;
|
||||||
use axum::{routing::get, Router};
|
use axum::{routing::get, Router};
|
||||||
use serde::Serialize;
|
|
||||||
use std::collections::HashSet;
|
|
||||||
use std::net::{IpAddr, Ipv6Addr, SocketAddr};
|
use std::net::{IpAddr, Ipv6Addr, SocketAddr};
|
||||||
use tokio::task::JoinSet;
|
use tokio::task::JoinSet;
|
||||||
|
|
||||||
|
mod dokku;
|
||||||
|
mod utils;
|
||||||
|
|
||||||
|
use dokku::DokkuApp;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct AppState {
|
struct AppState {
|
||||||
dokku_root: PathBuf,
|
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>> {
|
async fn hosts(State(state): State<AppState>) -> axum::Json<Vec<DokkuApp>> {
|
||||||
let mut dir_entries = state.dokku_root.read_dir().await.unwrap();
|
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 {
|
while let Some(Ok(dir_entry)) = dir_entries.next().await {
|
||||||
// Skip hidden folders / files
|
// Skip hidden folders / files
|
||||||
if osstring_starts_with(dir_entry.file_name(), '.') {
|
if utils::osstring_starts_with(dir_entry.file_name(), '.') {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,7 +48,7 @@ async fn hosts(State(state): State<AppState>) -> axum::Json<Vec<DokkuApp>> {
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
let dokku_root = match get_dokku_root() {
|
let dokku_root = match dokku::get_dokku_root() {
|
||||||
Some(path) => path,
|
Some(path) => path,
|
||||||
None => {
|
None => {
|
||||||
println!("Failed to find dokku root");
|
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