use bollard::Docker;
use std::{sync::Arc, path::Path};
use tokio::sync::Mutex;
use crate::{
executor::{docker::{self, DockerRuntime}, RuntimeType},
runtime::container::{ContainerRuntime, ContainerOutput}
};
#[cfg(test)]
mod docker_cleanup_tests {
use super::*;
fn should_skip_docker_tests() -> bool {
std::env::var("WRKFLW_TEST_SKIP_DOCKER").is_ok() ||
!docker::is_available()
}
async fn create_test_container(docker_client: &Docker) -> Option<String> {
if should_skip_docker_tests() {
return None;
}
let runtime = match DockerRuntime::new() {
Ok(rt) => rt,
Err(_) => return None,
};
let result = runtime
.run_container(
"alpine:latest",
&["echo", "test"],
&[],
Path::new("/"),
&[],
)
.await;
let running_containers = docker::get_tracked_containers();
if let Some(container_id) = running_containers.first() {
return Some(container_id.clone());
}
let container_id = format!("test-container-{}", uuid::Uuid::new_v4());
docker::track_container(&container_id);
Some(container_id)
}
async fn create_test_network(docker_client: &Docker) -> Option<String> {
if should_skip_docker_tests() {
return None;
}
match docker::create_job_network(docker_client).await {
Ok(network_id) => Some(network_id),
Err(_) => None,
}
}
#[tokio::test]
async fn test_docker_container_cleanup() {
if should_skip_docker_tests() {
println!("Docker tests disabled or Docker not available, skipping test");
return;
}
let docker = match Docker::connect_with_local_defaults() {
Ok(client) => client,
Err(_) => {
println!("Could not connect to Docker, skipping test");
return;
}
};
let container_id = match create_test_container(&docker).await {
Some(id) => id,
None => {
println!("Could not create test container, skipping test");
return;
}
};
let containers = docker::get_tracked_containers();
let is_tracked = containers.contains(&container_id);
assert!(is_tracked, "Container should be tracked for cleanup");
docker::cleanup_containers(&docker).await;
let containers = docker::get_tracked_containers();
let still_tracked = containers.contains(&container_id);
assert!(!still_tracked, "Container should be removed from tracking after cleanup");
}
#[tokio::test]
async fn test_docker_network_cleanup() {
if should_skip_docker_tests() {
println!("Docker tests disabled or Docker not available, skipping test");
return;
}
let docker = match Docker::connect_with_local_defaults() {
Ok(client) => client,
Err(_) => {
println!("Could not connect to Docker, skipping test");
return;
}
};
let network_id = match create_test_network(&docker).await {
Some(id) => id,
None => {
println!("Could not create test network, skipping test");
return;
}
};
let networks = docker::get_tracked_networks();
let is_tracked = networks.contains(&network_id);
assert!(is_tracked, "Network should be tracked for cleanup");
docker::cleanup_networks(&docker).await;
let networks = docker::get_tracked_networks();
let still_tracked = networks.contains(&network_id);
assert!(!still_tracked, "Network should be removed from tracking after cleanup");
}
#[tokio::test]
async fn test_full_resource_cleanup() {
if should_skip_docker_tests() {
println!("Docker tests disabled or Docker not available, skipping test");
return;
}
let docker = match Docker::connect_with_local_defaults() {
Ok(client) => client,
Err(_) => {
println!("Could not connect to Docker, skipping test");
return;
}
};
let _ = create_test_container(&docker).await;
let _ = create_test_network(&docker).await;
let container_count = docker::get_tracked_containers().len();
let network_count = docker::get_tracked_networks().len();
if container_count == 0 && network_count == 0 {
println!("No resources created for testing, skipping test");
return;
}
docker::cleanup_resources(&docker).await;
let remaining_containers = docker::get_tracked_containers().len();
let remaining_networks = docker::get_tracked_networks().len();
assert_eq!(remaining_containers, 0, "All containers should be cleaned up");
assert_eq!(remaining_networks, 0, "All networks should be cleaned up");
}
}