#![allow(dead_code)]
use std::sync::atomic::{AtomicU8, Ordering};
use std::time::Duration;
use foundation_core::valtron::sleep_async;
use foundation_deployment_docker::{DockerClient, DockerError};
static PULLING: AtomicU8 = AtomicU8::new(IDLE);
const IDLE: u8 = 0;
const BUSY: u8 = 1;
struct Turn;
impl Drop for Turn {
fn drop(&mut self) {
PULLING.store(IDLE, Ordering::Release);
}
}
async fn take_turn() -> Turn {
while PULLING
.compare_exchange(IDLE, BUSY, Ordering::Acquire, Ordering::Relaxed)
.is_err()
{
sleep_async(Duration::from_millis(100)).await;
}
Turn
}
pub const DOCKER_SOCK: &str = "/var/run/docker.sock";
pub async fn ensure_image(client: &DockerClient, repo: &str, tag: &str) {
let _turn = take_turn().await;
let reference = format!("{repo}:{tag}");
match client.image_inspect(&reference).await {
Ok(_) => return,
Err(DockerError::Api { status: 404, .. }) => {}
Err(e) => panic!("inspect {reference}: {e:?}"),
}
client
.image_pull(Some(repo), None, None, Some(tag), None, None)
.await
.unwrap_or_else(|e| panic!("start pulling {reference}: {e:?}"))
.finish()
.await
.unwrap_or_else(|e| panic!("pull {reference}: {e:?}"));
}
pub async fn client_with_alpine() -> DockerClient {
let client = DockerClient::connect_unix(DOCKER_SOCK);
ensure_image(&client, "alpine", "latest").await;
client
}