use core::fmt::Debug;
use async_trait::async_trait;
use strum::{Display, EnumString, EnumVariantNames};
use crate::Options;
mod local;
pub use local::{LocalDriver, LocalHandle};
mod docker;
pub use docker::{DockerDriver, DockerHandle};
#[derive(Copy, Clone, PartialEq, Debug, clap::ValueEnum, EnumString, EnumVariantNames, Display)]
#[strum(serialize_all = "lowercase")]
pub enum DriverMode {
Local,
Docker,
}
#[async_trait]
pub trait Driver {
type Handle: Debug;
async fn run(&self, app: &str, opts: Options) -> anyhow::Result<Self::Handle>;
async fn wait(&self, handle: &mut Self::Handle) -> anyhow::Result<()>;
async fn exit(&self, mut handle: Self::Handle) -> anyhow::Result<()>;
}
pub enum GenericDriver {
Local(LocalDriver),
Docker(DockerDriver),
}
impl GenericDriver {
pub fn new(mode: DriverMode) -> Result<Self, anyhow::Error> {
let d = match mode {
DriverMode::Local => Self::Local(LocalDriver::new()),
DriverMode::Docker => Self::Docker(DockerDriver::new()?),
};
Ok(d)
}
}
#[derive(Debug)]
pub enum GenericHandle {
Local(LocalHandle),
Docker(DockerHandle),
}
#[async_trait]
impl Driver for GenericDriver {
type Handle = GenericHandle;
async fn run(&self, app: &str, opts: Options) -> anyhow::Result<Self::Handle> {
let h = match self {
GenericDriver::Local(d) => d.run(app, opts).await.map(GenericHandle::Local)?,
GenericDriver::Docker(d) => d.run(app, opts).await.map(GenericHandle::Docker)?,
};
Ok(h)
}
async fn wait(&self, handle: &mut Self::Handle) -> anyhow::Result<()> {
match (self, handle) {
(GenericDriver::Local(d), GenericHandle::Local(h)) => d.wait(h).await?,
(GenericDriver::Docker(d), GenericHandle::Docker(h)) => d.wait(h).await?,
_ => panic!("driver/handler mismatch"),
};
Ok(())
}
async fn exit(&self, handle: Self::Handle) -> anyhow::Result<()> {
match (self, handle) {
(GenericDriver::Local(d), GenericHandle::Local(h)) => d.exit(h).await?,
(GenericDriver::Docker(d), GenericHandle::Docker(h)) => d.exit(h).await?,
_ => panic!("driver/handler mismatch"),
};
Ok(())
}
}