diff --git a/.woodpecker/test.yml b/.woodpecker/test.yml new file mode 100644 index 0000000..53d91ac --- /dev/null +++ b/.woodpecker/test.yml @@ -0,0 +1,10 @@ +steps: + - name: clippy + image: rust:${RUST_VERSION} + commands: + - cargo clippy --all-targets --all-features -- -D warnings + +matrix: + RUST_VERSION: + - "1.91.1" + - "1.91.0" diff --git a/Cargo.lock b/Cargo.lock index 6fcc4e9..3d957d6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -30,6 +30,17 @@ dependencies = [ "tokio", ] +[[package]] +name = "async-trait" +version = "0.1.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "atomic-waker" version = "1.1.2" @@ -54,6 +65,7 @@ version = "0.1.0" dependencies = [ "anyhow", "async-compression", + "async-trait", "bollard", "tokio", "tokio-tar", diff --git a/Cargo.toml b/Cargo.toml index e7048e4..ce58e83 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,4 +8,5 @@ tokio = { version = "1", features = ["full"] } async-compression = { version = "0.4", features = ["tokio", "xz"] } bollard = "0.19" anyhow = "1.0" -tokio-tar = "0.3" \ No newline at end of file +tokio-tar = "0.3" +async-trait = "0.1" \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..a802652 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,11 @@ +FROM rust:1.91.1 + +WORKDIR /beekeper + +COPY src/ src/ +COPY Cargo.toml . +COPY Cargo.lock . + +RUN cargo build --release + +CMD ["./target/release/beekeper"] \ No newline at end of file diff --git a/docker-compose.yml b/dev/docker-compose.yml similarity index 100% rename from docker-compose.yml rename to dev/docker-compose.yml diff --git a/src/docker/bollard.rs b/src/docker/bollard.rs new file mode 100644 index 0000000..0498ffa --- /dev/null +++ b/src/docker/bollard.rs @@ -0,0 +1,49 @@ +use bollard::Docker; +use std::sync::{Arc, Mutex}; + +pub struct BollardAdapter { + client: Arc>>, +} + +impl BollardAdapter { + pub fn new() -> Self { + Self { + client: Arc::new(Mutex::new(None)), + } + } +} + +impl crate::docker::DockerAdapter for BollardAdapter { + async fn connect_docker(&self, docker_host: Option) -> anyhow::Result<()> { + let docker = match docker_host { + Some(host) => Docker::connect_with_http(&host, 60, bollard::API_DEFAULT_VERSION)?, + None => Docker::connect_with_socket_defaults()?, + }; + + docker.ping().await?; + + let mut client = self.client.lock().unwrap(); + *client = Some(docker); + + Ok(()) + } + + async fn list_service_with_label(&self, label: &str) -> anyhow::Result> { + Ok(vec![]) + } + + async fn shutdown_service(&self, service_name: &str) -> anyhow::Result<()> { + Ok(()) + } + + async fn start_service(&self, service_name: &str) -> anyhow::Result<()> { + Ok(()) + } +} + +impl Default for BollardAdapter { + fn default() -> Self { + Self::new() + } +} + diff --git a/src/docker/mod.rs b/src/docker/mod.rs new file mode 100644 index 0000000..ccd557e --- /dev/null +++ b/src/docker/mod.rs @@ -0,0 +1,24 @@ +mod bollard; + +pub use bollard::BollardAdapter; + +pub struct Docker { + adapter: T, +} + +impl Docker { + pub fn new(adapter: T) -> Self { + Self { adapter } + } + + pub async fn connect_docker(&self, docker_host: Option) -> anyhow::Result<()> { + self.adapter.connect_docker(docker_host).await + } +} + +pub trait DockerAdapter { + async fn connect_docker(&self, docker_host: Option) -> anyhow::Result<()>; + async fn list_service_with_label(&self, label: &str) -> anyhow::Result>; + async fn shutdown_service(&self, service_name: &str) -> anyhow::Result<()>; + async fn start_service(&self, service_name: &str) -> anyhow::Result<()>; +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index a0f5daa..003e8da 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,26 +1,30 @@ -use bollard::Docker; +mod docker; + +use docker::{BollardAdapter, Docker}; + +struct AppEnvVars { + backup_folder: String, + docker_host: Option, +} #[tokio::main] async fn main() -> anyhow::Result<()> { - let backup_root_folder = std::env::var("BACKUP_FOLDER")?; - let backup_root_path = std::path::Path::new(&backup_root_folder); + let envs = load_envs()?; + let backup_root_path = std::path::Path::new(&envs.backup_folder); let folders = list_folders(backup_root_path).await?; - let docker_host = std::env::var("DOCKER_HOST").ok(); - let docker_conn = connect_docker(docker_host).await?; - + let docker_conn = connect_docker(envs.docker_host).await?; Ok(()) } -async fn connect_docker(docker_host: Option) -> anyhow::Result { - Ok( - match docker_host { - Some(host) => Docker::connect_with_http(&host, 60, bollard::API_DEFAULT_VERSION)?, - None => Docker::connect_with_socket_defaults()?, - } - ) +async fn connect_docker(docker_host: Option) -> anyhow::Result> { + let adapter = BollardAdapter::new(); + let docker = Docker::new(adapter); + docker.connect_docker(docker_host).await?; + + Ok(docker) } async fn list_folders(path: &std::path::Path) -> anyhow::Result> { @@ -34,4 +38,16 @@ async fn list_folders(path: &std::path::Path) -> anyhow::Result anyhow::Result { + let backup_folder = std::env::var("BACKUP_FOLDER")?; + let docker_host = std::env::var("DOCKER_HOST").ok(); + + Ok( + AppEnvVars { + backup_folder, + docker_host, + } + ) } \ No newline at end of file