1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
//! Remoção INDIVIDUAL de um recurso Docker (o par por-item dos `docker_prune`):
//! um container, imagem, volume ou rede específicos, escolhidos na aba Docker.
//! Sem `force` — o Docker recusa remover recursos em uso e o erro é propagado
//! ao cliente (a UI mostra a mensagem), evitando remoção acidental do que está
//! em uso. Invalida os caches de inventário afetados para a aba refletir na hora.
use crate::api::AppState;
use bollard::{
container::RemoveContainerOptions, image::RemoveImageOptions, volume::RemoveVolumeOptions,
};
use shared::Response as RpResponse;
/// `docker rm <id>` (sem `-f`): remove um container PARADO. `v: true` remove os
/// volumes anônimos associados (como o prune). Um container rodando é recusado
/// pelo Docker (409) — a UI só oferece "Remover" nos parados, mas o daemon não
/// força de qualquer forma.
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(()) => {
// Remover um container muda contagens de imagem em-uso e anexos de rede.
state.docker_cache.df.invalidate().await;
state.docker_cache.networks.invalidate().await;
RpResponse::Ok
}
Err(e) => RpResponse::err("DockerError", e.to_string()),
}
}
/// `docker rmi <id>` (sem `-f`): remove uma imagem sem uso. Uma imagem
/// referenciada por algum container é recusada pelo Docker.
pub async fn remove_image(state: AppState, id: String) -> RpResponse {
let opts = RemoveImageOptions {
force: false,
noprune: false,
};
match state.docker.inner.remove_image(&id, Some(opts), None).await {
Ok(_) => {
state.docker_cache.df.invalidate().await;
RpResponse::Ok
}
Err(e) => RpResponse::err("DockerError", e.to_string()),
}
}
/// `docker volume rm <name>` (sem `-f`): remove um volume sem uso.
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("DockerError", e.to_string()),
}
}
/// `docker network rm <id>`: remove uma rede sem uso. Uma rede com container
/// anexado (ou uma predefinida: bridge/host/none) é recusada pelo Docker.
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("DockerError", e.to_string()),
}
}