use bollard::Docker;
use ironflow_core::error::OperationError;
use ironflow_core::operation::OperationContext;
#[derive(Clone)]
pub struct DockerClient {
docker: Docker,
}
impl DockerClient {
pub fn new(docker: Docker) -> Self {
Self { docker }
}
pub fn connect_local() -> Result<Self, OperationError> {
let docker =
Docker::connect_with_local_defaults().map_err(|e| OperationError::External {
origin: "docker".to_string(),
message: e.to_string(),
})?;
Ok(Self { docker })
}
pub fn connect_with_url(url: &str, timeout_secs: u64) -> Result<Self, OperationError> {
let docker = Docker::connect_with_http(url, timeout_secs, bollard::API_DEFAULT_VERSION)
.map_err(|e| OperationError::External {
origin: "docker".to_string(),
message: e.to_string(),
})?;
Ok(Self { docker })
}
pub fn from_context(_ctx: &OperationContext) -> Result<Self, OperationError> {
Self::connect_local()
}
pub fn docker(&self) -> &Docker {
&self.docker
}
pub fn into_inner(self) -> Docker {
self.docker
}
}
impl std::fmt::Debug for DockerClient {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("DockerClient")
.field("connected", &true)
.finish()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn debug_does_not_leak_internals() {
let client = DockerClient::connect_local();
if let Ok(c) = client {
let debug = format!("{c:?}");
assert!(debug.contains("DockerClient"));
assert!(!debug.contains("docker.sock"));
}
}
}