2025-12-10 08:39:32 +01:00
|
|
|
use serde::Serialize;
|
|
|
|
|
|
2026-01-26 08:26:15 +01:00
|
|
|
/// Describes a node container in the compose stack.
|
2025-12-10 08:39:32 +01:00
|
|
|
#[derive(Clone, Debug, Serialize)]
|
|
|
|
|
pub struct NodeDescriptor {
|
|
|
|
|
name: String,
|
|
|
|
|
image: String,
|
|
|
|
|
entrypoint: String,
|
|
|
|
|
volumes: Vec<String>,
|
|
|
|
|
extra_hosts: Vec<String>,
|
|
|
|
|
ports: Vec<String>,
|
2026-03-27 10:42:47 +01:00
|
|
|
#[serde(skip)]
|
|
|
|
|
container_ports: Vec<u16>,
|
2025-12-10 08:39:32 +01:00
|
|
|
environment: Vec<EnvEntry>,
|
|
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
|
|
|
platform: Option<String>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Environment variable entry for docker-compose templating.
|
|
|
|
|
#[derive(Clone, Debug, Serialize, PartialEq, Eq)]
|
|
|
|
|
pub struct EnvEntry {
|
|
|
|
|
key: String,
|
|
|
|
|
value: String,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl EnvEntry {
|
2026-02-02 07:19:22 +01:00
|
|
|
pub fn new(key: impl Into<String>, value: impl Into<String>) -> Self {
|
2025-12-10 08:39:32 +01:00
|
|
|
Self {
|
|
|
|
|
key: key.into(),
|
|
|
|
|
value: value.into(),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
|
pub fn key(&self) -> &str {
|
|
|
|
|
&self.key
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
|
pub fn value(&self) -> &str {
|
|
|
|
|
&self.value
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl NodeDescriptor {
|
2026-02-02 07:19:22 +01:00
|
|
|
#[allow(clippy::too_many_arguments)]
|
|
|
|
|
pub fn new(
|
|
|
|
|
name: impl Into<String>,
|
|
|
|
|
image: impl Into<String>,
|
|
|
|
|
entrypoint: impl Into<String>,
|
|
|
|
|
volumes: Vec<String>,
|
|
|
|
|
extra_hosts: Vec<String>,
|
|
|
|
|
ports: Vec<String>,
|
2026-03-27 10:42:47 +01:00
|
|
|
container_ports: Vec<u16>,
|
2026-02-02 07:19:22 +01:00
|
|
|
environment: Vec<EnvEntry>,
|
|
|
|
|
platform: Option<String>,
|
2025-12-10 08:39:32 +01:00
|
|
|
) -> Self {
|
|
|
|
|
Self {
|
2026-02-02 07:19:22 +01:00
|
|
|
name: name.into(),
|
|
|
|
|
image: image.into(),
|
|
|
|
|
entrypoint: entrypoint.into(),
|
|
|
|
|
volumes,
|
|
|
|
|
extra_hosts,
|
2025-12-10 08:39:32 +01:00
|
|
|
ports,
|
2026-03-27 10:42:47 +01:00
|
|
|
container_ports,
|
2025-12-10 08:39:32 +01:00
|
|
|
environment,
|
2026-02-02 07:19:22 +01:00
|
|
|
platform,
|
2025-12-10 08:39:32 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-27 10:42:47 +01:00
|
|
|
#[allow(clippy::too_many_arguments)]
|
|
|
|
|
pub fn with_loopback_ports(
|
|
|
|
|
name: impl Into<String>,
|
|
|
|
|
image: impl Into<String>,
|
|
|
|
|
entrypoint: impl Into<String>,
|
|
|
|
|
volumes: Vec<String>,
|
|
|
|
|
extra_hosts: Vec<String>,
|
|
|
|
|
container_ports: Vec<u16>,
|
|
|
|
|
environment: Vec<EnvEntry>,
|
|
|
|
|
platform: Option<String>,
|
|
|
|
|
) -> Self {
|
|
|
|
|
Self::new(
|
|
|
|
|
name,
|
|
|
|
|
image,
|
|
|
|
|
entrypoint,
|
|
|
|
|
volumes,
|
|
|
|
|
extra_hosts,
|
|
|
|
|
container_ports
|
|
|
|
|
.iter()
|
|
|
|
|
.copied()
|
|
|
|
|
.map(Self::loopback_port_binding)
|
|
|
|
|
.collect(),
|
|
|
|
|
container_ports,
|
|
|
|
|
environment,
|
|
|
|
|
platform,
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[must_use]
|
|
|
|
|
pub fn loopback_port_binding(port: u16) -> String {
|
|
|
|
|
format!("127.0.0.1::{port}")
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-10 08:39:32 +01:00
|
|
|
pub fn ports(&self) -> &[String] {
|
|
|
|
|
&self.ports
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-27 10:42:47 +01:00
|
|
|
pub fn container_ports(&self) -> &[u16] {
|
|
|
|
|
&self.container_ports
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn image(&self) -> &str {
|
|
|
|
|
&self.image
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn platform(&self) -> Option<&str> {
|
|
|
|
|
self.platform.as_deref()
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-02 07:19:22 +01:00
|
|
|
#[cfg(test)]
|
|
|
|
|
pub fn test_ports(&self) -> &[String] {
|
|
|
|
|
self.ports()
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-10 08:39:32 +01:00
|
|
|
#[cfg(test)]
|
|
|
|
|
pub fn environment(&self) -> &[EnvEntry] {
|
|
|
|
|
&self.environment
|
|
|
|
|
}
|
|
|
|
|
}
|