use dragonfly_client_config::dfinit::{Config, ContainerRuntimeConfig};
use dragonfly_client_core::Result;
use tracing::{info, instrument};
pub mod containerd;
pub mod crio;
pub mod docker;
pub mod podman;
#[derive(Debug, Clone)]
enum Engine {
Containerd(containerd::Containerd),
Docker(docker::Docker),
Crio(crio::CRIO),
Podman(podman::Podman),
}
pub struct ContainerRuntime {
engine: Option<Engine>,
}
impl ContainerRuntime {
#[instrument(skip_all)]
pub fn new(config: &Config) -> Self {
Self {
engine: Self::get_engine(config),
}
}
#[instrument(skip_all)]
pub async fn run(&self) -> Result<()> {
match &self.engine {
None => Ok(()),
Some(Engine::Containerd(containerd)) => containerd.run().await,
Some(Engine::Docker(docker)) => docker.run().await,
Some(Engine::Crio(crio)) => crio.run().await,
Some(Engine::Podman(podman)) => podman.run().await,
}
}
#[instrument(skip_all)]
fn get_engine(config: &Config) -> Option<Engine> {
if let Some(ref container_runtime_config) = config.container_runtime.config {
let engine = match container_runtime_config {
ContainerRuntimeConfig::Containerd(containerd) => Engine::Containerd(
containerd::Containerd::new(containerd.clone(), config.proxy.clone()),
),
ContainerRuntimeConfig::Docker(docker) => {
Engine::Docker(docker::Docker::new(docker.clone(), config.proxy.clone()))
}
ContainerRuntimeConfig::CRIO(crio) => {
Engine::Crio(crio::CRIO::new(crio.clone(), config.proxy.clone()))
}
ContainerRuntimeConfig::Podman(podman) => {
Engine::Podman(podman::Podman::new(podman.clone(), config.proxy.clone()))
}
};
info!("container runtime engine is {:?}", engine);
return Some(engine);
}
info!("container runtime engine is not set");
None
}
}
#[cfg(test)]
mod tests {
#![allow(clippy::type_complexity)]
use super::*;
use dragonfly_client_config::dfinit;
#[test]
fn new_picks_engine_matching_config() {
let test_cases: Vec<(Option<ContainerRuntimeConfig>, fn(Option<&Engine>))> = vec![
(None, |engine| assert!(engine.is_none())),
(
Some(ContainerRuntimeConfig::Containerd(Default::default())),
|engine| assert!(matches!(engine, Some(Engine::Containerd(_)))),
),
(
Some(ContainerRuntimeConfig::Docker(Default::default())),
|engine| assert!(matches!(engine, Some(Engine::Docker(_)))),
),
(
Some(ContainerRuntimeConfig::CRIO(Default::default())),
|engine| assert!(matches!(engine, Some(Engine::Crio(_)))),
),
(
Some(ContainerRuntimeConfig::Podman(Default::default())),
|engine| assert!(matches!(engine, Some(Engine::Podman(_)))),
),
];
for (container_runtime_config, expect) in test_cases {
let runtime = ContainerRuntime::new(&Config {
container_runtime: dfinit::ContainerRuntime {
config: container_runtime_config,
},
..Default::default()
});
expect(runtime.engine.as_ref());
}
}
#[tokio::test]
async fn run_returns_ok_without_engine() {
let runtime = ContainerRuntime::new(&Config::default());
assert!(runtime.run().await.is_ok());
}
}