1
0
Fork 0
mirror of https://codeberg.org/icewind/haze.git synced 2026-06-03 17:14:08 +02:00

allow bare-service proxy hosts

This commit is contained in:
Robin Appelman 2026-03-09 17:35:47 +01:00
commit fdc821cb93
2 changed files with 58 additions and 24 deletions

View file

@ -218,7 +218,7 @@ fn test_option_parse() {
); );
} }
#[derive(Debug)] #[derive(Debug, Clone)]
pub struct Cloud { pub struct Cloud {
pub id: String, pub id: String,
pub network: String, pub network: String,
@ -851,3 +851,9 @@ impl Cloud {
None None
} }
} }
impl PartialEq for Cloud {
fn eq(&self, other: &Self) -> bool {
self.id == other.id
}
}

View file

@ -1,4 +1,4 @@
use crate::service::ServiceTrait; use crate::service::{ServiceTrait, ServiceType};
use crate::Result; use crate::Result;
use crate::{Cloud, HazeConfig}; use crate::{Cloud, HazeConfig};
use axum::http::header::HOST; use axum::http::header::HOST;
@ -18,6 +18,7 @@ use std::fs::{create_dir_all, set_permissions};
use std::net::{IpAddr, Ipv4Addr, SocketAddr}; use std::net::{IpAddr, Ipv4Addr, SocketAddr};
use std::os::unix::fs::PermissionsExt; use std::os::unix::fs::PermissionsExt;
use std::path::PathBuf; use std::path::PathBuf;
use std::str::FromStr;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use std::time::Duration; use std::time::Duration;
use tokio::net::UnixListener; use tokio::net::UnixListener;
@ -28,7 +29,7 @@ use tracing::{debug, error, info};
struct ActiveInstances { struct ActiveInstances {
known: Mutex<HashMap<String, SocketAddr>>, known: Mutex<HashMap<String, SocketAddr>>,
last: Mutex<Option<SocketAddr>>, last: Mutex<Option<Cloud>>,
docker: Docker, docker: Docker,
config: HazeConfig, config: HazeConfig,
} }
@ -48,15 +49,9 @@ impl ActiveInstances {
return Some(ip); return Some(ip);
} }
// service proxy let addr = if ServiceType::from_str(name).is_ok() {
let addr = if name.matches('-').count() == 2 { let cloud = self.last()?;
let (name, service_name) = name.rsplit_once('-').unwrap(); let service = cloud.services().find(|service| service.name() == name)?;
let cloud = Cloud::get_by_filter(&self.docker, Some(name.into()), &self.config)
.await
.ok()?;
let service = cloud
.services()
.find(|service| service.name() == service_name)?;
let ip = service let ip = service
.get_ips(&self.docker, &cloud.id) .get_ips(&self.docker, &cloud.id)
.await .await
@ -64,13 +59,33 @@ impl ActiveInstances {
.next()?; .next()?;
SocketAddr::new(ip, service.proxy_port()) SocketAddr::new(ip, service.proxy_port())
} else { } else {
SocketAddr::new( match name.matches('-').count() {
Cloud::get_by_filter(&self.docker, Some(name.into()), &self.config) // instance
.await 1 => SocketAddr::new(
.ok()? Cloud::get_by_filter(&self.docker, Some(name.into()), &self.config)
.ip?, .await
80, .ok()?
) .ip?,
80,
),
// service with instance
2 => {
let (name, service_name) = name.rsplit_once('-').unwrap();
let cloud = Cloud::get_by_filter(&self.docker, Some(name.into()), &self.config)
.await
.ok()?;
let service = cloud
.services()
.find(|service| service.name() == service_name)?;
let ip = service
.get_ips(&self.docker, &cloud.id)
.await
.ok()?
.next()?;
SocketAddr::new(ip, service.proxy_port())
}
_ => return None,
}
}; };
println!("{name} => {addr}"); println!("{name} => {addr}");
@ -79,18 +94,31 @@ impl ActiveInstances {
Some(addr) Some(addr)
} }
pub fn last(&self) -> Option<SocketAddr> { pub fn last_addr(&self) -> Option<SocketAddr> {
*self.last.lock().unwrap() self.last
.lock()
.unwrap()
.as_ref()
.and_then(|cloud| Some(SocketAddr::new(cloud.ip?, 80)))
}
pub fn last(&self) -> Option<Cloud> {
self.last.lock().unwrap().clone()
} }
async fn update_last(&self) { async fn update_last(&self) {
let last = Cloud::get_by_filter(&self.docker, None, &self.config) let last = Cloud::get_by_filter(&self.docker, None, &self.config)
.await .await
.ok() .ok();
.and_then(|cloud| Some(SocketAddr::new(cloud.ip?, 80)));
let mut old = self.last.lock().unwrap(); let mut old = self.last.lock().unwrap();
if old.as_ref() != last.as_ref() { if old.as_ref() != last.as_ref() {
info!(instance = ?last, "Found new instance"); info!(instance = ?last, "Found new instance");
// remove cached base-service mappings
self.known
.lock()
.unwrap()
.retain(|key, _| ServiceType::from_str(key).is_err());
*old = last; *old = last;
} }
} }
@ -181,7 +209,7 @@ async fn get_remote(
}; };
let ip = if host == base_address { let ip = if host == base_address {
instances instances
.last() .last_addr()
.ok_or_else(|| String::from("No running instance known")) .ok_or_else(|| String::from("No running instance known"))
} else { } else {
let requested_instance = host.split('.').next().unwrap(); let requested_instance = host.split('.').next().unwrap();