diff --git a/Cargo.lock b/Cargo.lock index e646c0719..0d37578d1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2611,7 +2611,12 @@ name = "jstzd" version = "0.1.0-alpha.0" dependencies = [ "anyhow", + "async-trait", "bollard", + "env_logger", + "futures-util", + "log", + "tokio", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 6082fd6c1..19b43f3f6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -100,9 +100,7 @@ url = "2.4.1" urlpattern = "0.2.0" wasm-bindgen = "0.2.92" bollard = "0.16.1" -# async-dropper = { version = "0.3.1", features = ["tokio", "simple"] } -# async-trait = "0.1.82" -# async-scoped = "0.9.0" +async-trait = "0.1.82" [workspace.dependencies.tezos-smart-rollup] version = "0.2.2" diff --git a/crates/jstzd/Cargo.toml b/crates/jstzd/Cargo.toml index a2130d008..8b2b663c6 100644 --- a/crates/jstzd/Cargo.toml +++ b/crates/jstzd/Cargo.toml @@ -7,4 +7,9 @@ repository.workspace = true [dependencies] anyhow.workspace = true +async-trait.workspace = true bollard.workspace = true +env_logger.workspace = true +futures-util.workspace = true +tokio.workspace = true +log.workspace = true \ No newline at end of file diff --git a/crates/jstzd/src/docker/image.rs b/crates/jstzd/src/docker/image.rs index b55179829..1b4489f57 100644 --- a/crates/jstzd/src/docker/image.rs +++ b/crates/jstzd/src/docker/image.rs @@ -1,3 +1,12 @@ +use anyhow::Result; +use bollard::{ + image::{CreateImageOptions, ListImagesOptions}, + Docker, +}; +use futures_util::StreamExt; +use log::info; +use std::{collections::HashMap, sync::Arc}; +#[async_trait::async_trait] pub trait Image: Sized { const LATEST_TAG: &'static str = "latest"; fn image_name(&self) -> &str; @@ -15,6 +24,48 @@ pub trait Image: Sized { fn exposed_ports(&self) -> &[u16] { &[] } + async fn pull_image(&self, client: Arc) -> Result<()> { + if Self::image_exists(self, client.clone()).await { + info!("Image: {:?} already exists ", self.image_name()); + return Ok(()); + } + self.create_image(client.clone()).await + } + async fn image_exists(&self, client: Arc) -> bool { + let filters = [("reference".to_string(), vec![self.image_uri()])] + .into_iter() + .collect::>(); + let images = &client + .list_images(Some(ListImagesOptions:: { + all: true, + filters, + ..Default::default() + })) + .await; + match images { + Ok(images) => !images.is_empty(), + Err(_) => false, + } + } + async fn create_image(&self, client: Arc) -> anyhow::Result<()> { + let options = Some(CreateImageOptions { + from_image: self.image_name(), + tag: self.image_tag(), + ..Default::default() + }); + let mut stream = client.create_image(options, None, None); + while let Some(create_info) = stream.next().await { + match create_info { + Ok(info) => { + if let Some(status) = info.status { + println!("{:?}", status) + } + } + Err(e) => return Err(e.into()), + } + } + Ok(()) + } } pub struct GenericImage { diff --git a/crates/jstzd/src/main.rs b/crates/jstzd/src/main.rs new file mode 100644 index 000000000..e2ca89eea --- /dev/null +++ b/crates/jstzd/src/main.rs @@ -0,0 +1,22 @@ +use bollard::Docker; +use env_logger::Env; +use jstzd::docker::{GenericImage, Image}; +use std::sync::Arc; + +pub async fn example() -> anyhow::Result<()> { + let docker = Docker::connect_with_socket_defaults().unwrap(); + let docker = Arc::new(docker); + let image = GenericImage::new("busybox").with_tag("latest"); + image.pull_image(docker.clone()).await?; + + Ok(()) +} + +#[tokio::main] +async fn main() { + env_logger::init_from_env(Env::default().default_filter_or("info")); + match example().await { + Ok(_) => log::info!("Success"), + Err(e) => log::error!("Error: {}", e), + } +}