use std::pin::Pin;
use std::time::{Duration, SystemTime};
use futures::stream::Stream;
use crate::error::Result;
use crate::spec::ContainerSpec;
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct ContainerId(String);
impl ContainerId {
#[must_use]
pub fn new(id: impl Into<String>) -> Self {
Self(id.into())
}
#[must_use]
pub fn as_str(&self) -> &str {
&self.0
}
}
impl std::fmt::Display for ContainerId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(&self.0)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ContainerStatus {
Starting,
Running,
Healthy,
Unhealthy,
Stopped {
exit_code: Option<i32>,
},
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum LogStream {
Stdout,
Stderr,
}
#[derive(Debug, Clone)]
pub struct LogChunk {
pub stream: LogStream,
pub timestamp: SystemTime,
pub bytes: Vec<u8>,
}
pub type LogChunkStream = Pin<Box<dyn Stream<Item = Result<LogChunk>> + Send>>;
pub trait ContainerRuntime: Send + Sync {
fn start(
&self,
spec: &ContainerSpec,
) -> impl std::future::Future<Output = Result<ContainerId>> + Send;
fn stop(
&self,
id: &ContainerId,
grace: Duration,
) -> impl std::future::Future<Output = Result<()>> + Send;
fn remove(&self, name: &str) -> impl std::future::Future<Output = Result<()>> + Send;
fn inspect(
&self,
id: &ContainerId,
) -> impl std::future::Future<Output = Result<ContainerStatus>> + Send;
fn wait_healthy(
&self,
id: &ContainerId,
timeout: Duration,
) -> impl std::future::Future<Output = Result<()>> + Send;
fn logs(
&self,
id: &ContainerId,
follow: bool,
) -> impl std::future::Future<Output = Result<LogChunkStream>> + Send;
}