1
0
Fork 0
mirror of https://codeberg.org/icewind/haze.git synced 2026-06-03 09:04:12 +02:00

default proxy to last

This commit is contained in:
Robin Appelman 2023-02-03 18:14:28 +01:00
commit 7910b9d034
2 changed files with 55 additions and 9 deletions

View file

@ -6,7 +6,6 @@ use crate::config::HazeConfig;
use crate::exec::container_logs; use crate::exec::container_logs;
use crate::git::checkout_all; use crate::git::checkout_all;
use crate::network::clear_networks; use crate::network::clear_networks;
use crate::php::PhpVersion;
use crate::proxy::proxy; use crate::proxy::proxy;
use crate::service::Service; use crate::service::Service;
use crate::service::ServiceTrait; use crate::service::ServiceTrait;

View file

@ -11,9 +11,13 @@ use std::os::unix::fs::PermissionsExt;
use std::path::PathBuf; use std::path::PathBuf;
use std::str::FromStr; use std::str::FromStr;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use std::time::Duration;
use tokio::net::UnixListener; use tokio::net::UnixListener;
use tokio::signal::ctrl_c; use tokio::signal::ctrl_c;
use tokio::spawn;
use tokio::time::sleep;
use tokio_stream::wrappers::UnixListenerStream; use tokio_stream::wrappers::UnixListenerStream;
use tracing::info;
use warp::host::Authority; use warp::host::Authority;
use warp::http::{HeaderMap, HeaderValue, Method}; use warp::http::{HeaderMap, HeaderValue, Method};
use warp::hyper::body::Bytes; use warp::hyper::body::Bytes;
@ -25,6 +29,7 @@ use warp_reverse_proxy::{
struct ActiveInstances { struct ActiveInstances {
known: Mutex<HashMap<String, SocketAddr>>, known: Mutex<HashMap<String, SocketAddr>>,
last: Mutex<Option<SocketAddr>>,
docker: Docker, docker: Docker,
config: HazeConfig, config: HazeConfig,
} }
@ -33,6 +38,7 @@ impl ActiveInstances {
pub fn new(docker: Docker, config: HazeConfig) -> Self { pub fn new(docker: Docker, config: HazeConfig) -> Self {
ActiveInstances { ActiveInstances {
known: Mutex::default(), known: Mutex::default(),
last: Mutex::default(),
docker, docker,
config, config,
} }
@ -72,6 +78,22 @@ impl ActiveInstances {
self.known.lock().unwrap().insert(name.into(), addr); self.known.lock().unwrap().insert(name.into(), addr);
Some(addr) Some(addr)
} }
pub fn last(&self) -> Option<SocketAddr> {
self.last.lock().unwrap().clone()
}
async fn update_last(&self) {
let last = Cloud::get_by_filter(&self.docker, None, &self.config)
.await
.ok()
.and_then(|cloud| Some(SocketAddr::new(cloud.ip?, 80)));
let mut old = self.last.lock().unwrap();
if old.as_ref() != last.as_ref() {
info!(instance = ?last, "Found new instance");
*old = last;
}
}
} }
pub async fn proxy(docker: Docker, config: HazeConfig) -> Result<()> { pub async fn proxy(docker: Docker, config: HazeConfig) -> Result<()> {
@ -80,30 +102,55 @@ pub async fn proxy(docker: Docker, config: HazeConfig) -> Result<()> {
} }
let listen = config.proxy.listen.clone(); let listen = config.proxy.listen.clone();
let base_address = config.proxy.address.clone();
let instances = ActiveInstances::new(docker, config); let instances = ActiveInstances::new(docker, config);
serve(instances, listen).await serve(instances, listen, base_address).await
} }
async fn serve(instances: ActiveInstances, listen: String) -> Result<()> { async fn serve(instances: ActiveInstances, listen: String, base_address: String) -> Result<()> {
let instances = Arc::new(instances); let instances = Arc::new(instances);
let base_address = Arc::new(base_address);
let last_instances = instances.clone();
let instances = warp::any().map(move || instances.clone()); let instances = warp::any().map(move || instances.clone());
let base_address = warp::any().map(move || base_address.clone());
spawn(async move {
loop {
sleep(Duration::from_secs(1)).await;
last_instances.update_last().await;
}
});
let proxy = warp::any() let proxy = warp::any()
.and(warp::filters::host::optional()) .and(warp::filters::host::optional())
.and(instances) .and(instances)
.and(base_address)
.and_then( .and_then(
move |host: Option<Authority>, instances: Arc<ActiveInstances>| async move { move |host: Option<Authority>,
instances: Arc<ActiveInstances>,
base_address: Arc<String>| async move {
let host = match host { let host = match host {
Some(host) => host, Some(host) => host,
None => return Err(warp::reject::not_found()), None => return Err(warp::reject::not_found()),
}; };
let requested_instance = host.as_str().split('.').next().unwrap(); let ip = if host.as_str() == base_address.as_str() {
if let Some(ip) = instances.get(requested_instance).await { instances
Ok((format!("http://{}", ip), host.to_string())) .last()
.ok_or_else(|| String::from("No running instance known"))
} else { } else {
eprintln!("Error {} has no known ip", requested_instance); let requested_instance = host.as_str().split('.').next().unwrap();
instances
.get(requested_instance)
.await
.ok_or_else(|| format!("Error {} has no known ip", requested_instance))
};
match ip {
Ok(ip) => Ok((format!("http://{}", ip), host.to_string())),
Err(e) => {
eprintln!("{}", e);
Err(warp::reject::not_found()) Err(warp::reject::not_found())
} }
}
}, },
) )
.untuple_one() .untuple_one()