diff --git a/src/cli/explorer.rs b/src/cli/explorer.rs index 82c49c3..07b50fd 100644 --- a/src/cli/explorer.rs +++ b/src/cli/explorer.rs @@ -4,9 +4,9 @@ use rand::Rng; use std::collections::HashMap; -use crate::utils::docker::run_docker_image; +use crate::utils::docker::{container_exists, kill_container, run_docker_image}; -pub fn explorer() { +pub async fn explorer() { let random_string: String = (0..64).map(|_| rand::thread_rng().sample(Alphanumeric).to_string()).collect(); let secret_key_base = format!("SECRET_KEY_BASE={}", random_string); @@ -29,10 +29,19 @@ pub fn explorer() { let host_config = HostConfig { port_bindings: Some(port_bindings), ..Default::default() }; + const CONTAINER_NAME: &str = "madara-explorer"; + + if container_exists(CONTAINER_NAME).await { + // TODO: handle error + let _ = kill_container(CONTAINER_NAME).await; + } + run_docker_image( "ghcr.io/lambdaclass/stark_compass_explorer:v0.2.34.2", - "madara-explorer", + CONTAINER_NAME, Some(env), Some(host_config), - ); + ) + .await; + log::info!("🧭 Explorer is running on http://localhost:4000"); } diff --git a/src/main.rs b/src/main.rs index 1b67b24..4d9af55 100644 --- a/src/main.rs +++ b/src/main.rs @@ -36,7 +36,7 @@ async fn main() { Some(Commands::Init) => cli::init::init(), Some(Commands::List) => cli::list::list(), Some(Commands::Run) => cli::run::run().await, - Some(Commands::Explorer) => cli::explorer::explorer(), + Some(Commands::Explorer) => cli::explorer::explorer().await, None => log::info!("Use --help to see the complete list of available commands"), } } diff --git a/src/utils/docker.rs b/src/utils/docker.rs index e03090d..f4e2bc2 100644 --- a/src/utils/docker.rs +++ b/src/utils/docker.rs @@ -1,14 +1,22 @@ -use bollard::container::{Config, CreateContainerOptions}; +use bollard::container::{Config, CreateContainerOptions, ListContainersOptions}; use bollard::image::CreateImageOptions; use bollard::models::HostConfig; use bollard::Docker; use futures_util::TryStreamExt; -pub fn run_docker_image(image: &str, container_name: &str, env: Option>, host_config: Option) { - is_docker_installed(); - match pull_and_start_docker_image(image, container_name, env, host_config) { +// TODO: fix unwraps and handle errors + +pub async fn run_docker_image( + image: &str, + container_name: &str, + env: Option>, + host_config: Option, +) { + is_docker_installed().await; + log::info!("🐳 Running docker image: {}", image); + match pull_and_start_docker_image(image, container_name, env, host_config).await { Ok(..) => { - log::info!("Successfully ran {}", container_name); + log::debug!("Successfully ran {}", container_name); } Err(err) => { log::error!("Error: {} running image: {}", err, image); @@ -16,12 +24,11 @@ pub fn run_docker_image(image: &str, container_name: &str, env: Option }; } -#[tokio::main] -async fn is_docker_installed() -> bool { +async fn is_docker_installed() { let docker = Docker::connect_with_local_defaults().unwrap(); - return match docker.version().await { + match docker.version().await { Ok(_) => { - log::info!("Docker running!"); + log::debug!("✅ Docker is installed!"); true } Err(_) => { @@ -30,8 +37,37 @@ async fn is_docker_installed() -> bool { }; } -#[tokio::main] -async fn pull_and_start_docker_image( +pub async fn container_exists(container_name: &str) -> bool { + let docker = Docker::connect_with_local_defaults().unwrap(); + let list_container_options = ListContainersOptions { all: true, ..Default::default() }; + match docker.list_containers::(Some(list_container_options)).await { + Ok(containers) => { + for container in containers { + if let Some(names) = container.names { + if names.contains(&format!("/{}", &container_name.to_string())) { + log::debug!("✅ Container {} exists!", container_name); + return true; + } + } + } + log::debug!("❌ Container {} does not exist!", container_name); + false + } + Err(_) => { + panic!("Failed to fetch containers, panicking"); + } + } +} + +pub async fn kill_container(container_name: &str) -> eyre::Result<()> { + let docker = Docker::connect_with_local_defaults().unwrap(); + // TODO: handle the error + let _ = docker.kill_container::(container_name, None).await; + docker.remove_container(container_name, None).await?; + Ok(()) +} + +pub async fn pull_and_start_docker_image( image: &str, container_name: &str, env: Option>,