use std::path::PathBuf;
use bollard::models::ImageDeleteResponseItem;
use bollard::models::ImageSummary;
use bollard::query_parameters::ListNodesOptions;
pub mod container;
pub mod images;
pub mod service;
use bollard::models::Node;
use bollard::models::SystemInfo;
use crankshaft_config::backend::docker::EventConfig;
use crankshaft_events::Event;
use crankshaft_events::TaskId;
use thiserror::Error;
use tokio::sync::broadcast;
pub use crate::container::Container;
use crate::images::*;
#[derive(Error, Debug)]
pub enum Error {
#[error(transparent)]
Docker(#[from] bollard::errors::Error),
#[error("missing required builder field `{0}`")]
MissingBuilderField(&'static str),
#[error("{0}")]
Message(String),
}
pub type Result<T> = std::result::Result<T, Error>;
#[derive(Clone, Debug)]
pub struct Docker(bollard::Docker);
impl Docker {
pub fn new(client: bollard::Docker) -> Self {
Self(client)
}
pub fn with_socket_defaults() -> Result<Self> {
let client = bollard::Docker::connect_with_socket_defaults().map_err(Error::Docker)?;
Ok(Self::new(client))
}
pub fn with_http_defaults() -> Result<Self> {
let client = bollard::Docker::connect_with_http_defaults().map_err(Error::Docker)?;
Ok(Self::new(client))
}
pub fn with_defaults() -> Result<Self> {
let client = bollard::Docker::connect_with_defaults().map_err(Error::Docker)?;
Ok(Self::new(client))
}
pub fn inner(&self) -> &bollard::Docker {
&self.0
}
pub async fn list_images(&self) -> Result<Vec<ImageSummary>> {
list_images(self).await
}
pub async fn ensure_image(
&self,
image: impl Into<String>,
token: tokio_util::sync::CancellationToken,
events_ctx: Option<(broadcast::Sender<Event>, TaskId)>,
) -> Result<Option<()>> {
ensure_image(self, image, token, events_ctx).await
}
pub async fn remove_image<T: AsRef<str>, U: AsRef<str>>(
&self,
name: T,
tag: U,
) -> Result<impl IntoIterator<Item = ImageDeleteResponseItem> + use<T, U>> {
remove_image(self, name, tag).await
}
pub async fn remove_all_images(&self) -> Result<Vec<ImageDeleteResponseItem>> {
remove_all_images(self).await
}
pub fn container_builder(&self) -> container::Builder {
container::Builder::new(self.0.clone())
}
pub fn container_from_name(
&self,
id: impl Into<String>,
stdout: Option<PathBuf>,
stderr: Option<PathBuf>,
) -> Container {
Container::new(self.0.clone(), id.into(), stdout, stderr)
}
pub async fn nodes(&self) -> Result<Vec<Node>> {
self.0
.list_nodes(None::<ListNodesOptions>)
.await
.map_err(Into::into)
}
pub fn service_builder(&self) -> service::Builder {
service::Builder::new(self.0.clone())
}
pub async fn info(&self) -> Result<SystemInfo> {
self.0.info().await.map_err(Into::into)
}
}
#[derive(Debug, Clone)]
pub struct EventOptions {
pub sender: broadcast::Sender<Event>,
pub task_id: TaskId,
pub send_start: bool,
pub user_config: EventConfig,
}
#[cfg(test)]
mod tests {}