use crate::{
Container, ExposedPort, ImageName, Port, PortError, RunnableContainer,
RunnableContainerBuilder, ToRunnableContainer, WaitStrategy,
};
const NATS_IMAGE: &ImageName = &ImageName::new("docker.io/nats");
const CLIENT_PORT: Port = Port(4222);
const CLUSTER_PORT: Port = Port(6222);
const MONITORING_PORT: Port = Port(8222);
#[derive(Debug)]
pub struct Nats {
image: ImageName,
client_port: ExposedPort,
cluster_port: ExposedPort,
monitoring_port: ExposedPort,
}
impl Nats {
#[must_use]
pub fn with_tag(self, tag: impl Into<String>) -> Self {
let Self { mut image, .. } = self;
image.set_tag(tag);
Self { image, ..self }
}
#[must_use]
pub fn with_digest(self, digest: impl Into<String>) -> Self {
let Self { mut image, .. } = self;
image.set_digest(digest);
Self { image, ..self }
}
#[must_use]
pub fn with_client_port(mut self, port: ExposedPort) -> Self {
self.client_port = port;
self
}
#[must_use]
pub fn with_cluster_port(mut self, port: ExposedPort) -> Self {
self.cluster_port = port;
self
}
#[must_use]
pub fn with_monitoring_port(mut self, port: ExposedPort) -> Self {
self.monitoring_port = port;
self
}
}
impl Default for Nats {
fn default() -> Self {
Self {
image: NATS_IMAGE.clone(),
client_port: ExposedPort::new(CLIENT_PORT),
cluster_port: ExposedPort::new(CLUSTER_PORT),
monitoring_port: ExposedPort::new(MONITORING_PORT),
}
}
}
impl Container<Nats> {
pub async fn client_endpoint(&self) -> Result<String, PortError> {
let port = self.client_port.host_port().await?;
let host_ip = self.runner.container_host_ip().await?;
let url = format!("nats://{host_ip}:{port}");
Ok(url)
}
pub async fn monitoring_endpoint(&self) -> Result<String, PortError> {
let port = self.monitoring_port.host_port().await?;
let host_ip = self.runner.container_host_ip().await?;
let url = format!("http://{host_ip}:{port}");
Ok(url)
}
pub async fn cluster_endpoint(&self) -> Result<String, PortError> {
let port = self.cluster_port.host_port().await?;
let host_ip = self.runner.container_host_ip().await?;
let url = format!("nats-route://{host_ip}:{port}");
Ok(url)
}
}
impl ToRunnableContainer for Nats {
fn to_runnable(&self, builder: RunnableContainerBuilder) -> RunnableContainer {
builder
.with_image(self.image.clone())
.with_wait_strategy(WaitStrategy::stderr_contains(
"Listening for client connections",
))
.with_port_mappings([
self.client_port.clone(),
self.cluster_port.clone(),
self.monitoring_port.clone(),
])
.build()
}
}