use crate::bootstrap::state::AppState;
use bollard::{
container::RemoveContainerOptions, image::RemoveImageOptions, volume::RemoveVolumeOptions,
};
use shared::Response as RpResponse;
pub async fn remove_container(state: AppState, id: String) -> RpResponse {
let opts = RemoveContainerOptions {
v: true,
..Default::default()
};
match state.docker.inner.remove_container(&id, Some(opts)).await {
Ok(()) => {
state.docker_cache.df.invalidate().await;
state.docker_cache.networks.invalidate().await;
RpResponse::Ok
}
Err(e) => RpResponse::err("RuntimeError", e.to_string()),
}
}
pub async fn remove_image(state: AppState, id: String) -> RpResponse {
let result = match remove_image_by_name(&state, &id).await {
Err(e) if needs_untag(&e) => remove_image_tag_by_tag(&state, &id).await,
other => other,
};
state.docker_cache.df.invalidate().await;
match result {
Ok(()) => RpResponse::Ok,
Err(e) => RpResponse::err("RuntimeError", e.to_string()),
}
}
async fn remove_image_by_name(state: &AppState, name: &str) -> Result<(), bollard::errors::Error> {
let opts = RemoveImageOptions {
force: false,
noprune: false,
};
state
.docker
.inner
.remove_image(name, Some(opts), None)
.await
.map(|_| ())
}
async fn remove_image_tag_by_tag(state: &AppState, id: &str) -> Result<(), bollard::errors::Error> {
let tags = state
.docker
.inner
.inspect_image(id)
.await?
.repo_tags
.unwrap_or_default();
for tag in tags {
remove_image_by_name(state, &tag).await?;
}
Ok(())
}
fn needs_untag(e: &bollard::errors::Error) -> bool {
let msg = e.to_string();
msg.contains("more than one tag") || msg.contains("multiple repositories")
}
pub async fn remove_volume(state: AppState, name: String) -> RpResponse {
match state
.docker
.inner
.remove_volume(&name, Some(RemoveVolumeOptions { force: false }))
.await
{
Ok(()) => {
state.docker_cache.df.invalidate().await;
RpResponse::Ok
}
Err(e) => RpResponse::err("RuntimeError", e.to_string()),
}
}
pub async fn remove_network(state: AppState, id: String) -> RpResponse {
match state.docker.inner.remove_network(&id).await {
Ok(()) => {
state.docker_cache.networks.invalidate().await;
RpResponse::Ok
}
Err(e) => RpResponse::err("RuntimeError", e.to_string()),
}
}