1
0
Fork 0
mirror of https://codeberg.org/icewind/haze.git synced 2026-06-03 09:04:12 +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 id: String,
pub network: String,
@ -851,3 +851,9 @@ impl Cloud {
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::{Cloud, HazeConfig};
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::os::unix::fs::PermissionsExt;
use std::path::PathBuf;
use std::str::FromStr;
use std::sync::{Arc, Mutex};
use std::time::Duration;
use tokio::net::UnixListener;
@ -28,7 +29,7 @@ use tracing::{debug, error, info};
struct ActiveInstances {
known: Mutex<HashMap<String, SocketAddr>>,
last: Mutex<Option<SocketAddr>>,
last: Mutex<Option<Cloud>>,
docker: Docker,
config: HazeConfig,
}
@ -48,15 +49,9 @@ impl ActiveInstances {
return Some(ip);
}
// service proxy
let addr = if name.matches('-').count() == 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 addr = if ServiceType::from_str(name).is_ok() {
let cloud = self.last()?;
let service = cloud.services().find(|service| service.name() == name)?;
let ip = service
.get_ips(&self.docker, &cloud.id)
.await
@ -64,13 +59,33 @@ impl ActiveInstances {
.next()?;
SocketAddr::new(ip, service.proxy_port())
} else {
SocketAddr::new(
Cloud::get_by_filter(&self.docker, Some(name.into()), &self.config)
.await
.ok()?
.ip?,
80,
)
match name.matches('-').count() {
// instance
1 => SocketAddr::new(
Cloud::get_by_filter(&self.docker, Some(name.into()), &self.config)
.await
.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}");
@ -79,18 +94,31 @@ impl ActiveInstances {
Some(addr)
}
pub fn last(&self) -> Option<SocketAddr> {
*self.last.lock().unwrap()
pub fn last_addr(&self) -> Option<SocketAddr> {
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) {
let last = Cloud::get_by_filter(&self.docker, None, &self.config)
.await
.ok()
.and_then(|cloud| Some(SocketAddr::new(cloud.ip?, 80)));
.ok();
let mut old = self.last.lock().unwrap();
if old.as_ref() != last.as_ref() {
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;
}
}
@ -181,7 +209,7 @@ async fn get_remote(
};
let ip = if host == base_address {
instances
.last()
.last_addr()
.ok_or_else(|| String::from("No running instance known"))
} else {
let requested_instance = host.split('.').next().unwrap();