use camel_api::CamelError;
use crate::document::InboundListener;
pub async fn provision_inbound(
entry: &InboundListener,
) -> Result<std::net::SocketAddr, CamelError> {
let listener = tokio::net::TcpListener::bind("127.0.0.1:0")
.await
.map_err(|e| {
CamelError::EndpointCreationFailed(format!("inbound listener bind 127.0.0.1:0: {e}"))
})?;
let bound = listener.local_addr().map_err(|e| {
CamelError::EndpointCreationFailed(format!("inbound listener local_addr: {e}"))
})?;
camel_component_http::ServerRegistry::global()
.stage_listener(listener)
.await?;
tracing::debug!(
bind_var = %entry.bind_var,
%bound,
"staged inbound listener for the scenario boot"
);
Ok(bound)
}
#[cfg(test)]
mod tests {
use std::collections::BTreeMap;
use crate::boot_scenario::boot_scenario;
use crate::document::{InboundListener, RouteSource, ScenarioDocument};
use crate::env_layers::{LayeredEnv, ambient_std};
#[tokio::test]
async fn inbound_binds_port_zero() {
let dir = tempfile::tempdir().expect("temp dir");
std::fs::write(dir.path().join("Camel.toml"), "# minimal\n").expect("write Camel.toml");
std::fs::write(
dir.path().join("routes.yaml"),
r#"
routes:
- id: inbound-route
from: direct:start
steps:
- to: "log:${env:INBOUND}"
"#,
)
.expect("write routes.yaml");
let doc = ScenarioDocument {
source_path: dir.path().join("case.test.yaml"),
route_source: RouteSource::RouteFiles(vec!["routes.yaml".into()]),
scenario: Vec::new(),
partners: None,
env: None,
env_passthrough: None,
profile: None,
send_deadline: None,
inbound: Some(InboundListener {
bind_var: "INBOUND".to_string(),
}),
};
let env = LayeredEnv::new(BTreeMap::new(), BTreeMap::new(), Vec::new(), ambient_std());
let mut run = boot_scenario(&doc, dir.path(), &env)
.await
.expect("boot must provision the inbound listener and extend the env");
let bound = run
.inbound_bound
.expect("the boot result must carry the provisioned inbound address");
assert!(
bound.ip().is_loopback(),
"the listener must bind the loopback address: {bound}"
);
assert_ne!(bound.port(), 0, "port 0 must resolve to a real port");
run.boot
.shutdown(&mut run.ctx)
.await
.expect("clean shutdown must complete");
}
}