ironflow_ops_docker/images/
cleanup.rs1use std::collections::HashMap;
4
5use async_trait::async_trait;
6use bollard::Docker;
7use bollard::query_parameters::PruneImagesOptions;
8use ironflow_core::error::OperationError;
9use ironflow_core::operation::{Operation, OperationContext, TypedOperation};
10use serde::{Deserialize, Serialize};
11use serde_json::Value;
12
13use crate::containers::DockerRef;
14use crate::helpers::{docker_error, to_value};
15
16#[derive(Debug, Clone, Serialize, Deserialize)]
22pub struct ImagePruneOutput {
23 pub images_deleted: Vec<String>,
25 pub space_reclaimed: u64,
27}
28
29pub struct ImagePrune {
43 docker: Docker,
44 filters: HashMap<String, Vec<String>>,
45}
46
47impl ImagePrune {
48 pub fn new(client: impl Into<DockerRef>) -> Self {
50 Self {
51 docker: client.into().0,
52 filters: HashMap::new(),
53 }
54 }
55
56 pub fn filter(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
58 self.filters
59 .entry(key.into())
60 .or_default()
61 .push(value.into());
62 self
63 }
64
65 pub async fn run(&self, _ctx: &OperationContext) -> Result<ImagePruneOutput, OperationError> {
72 let options = PruneImagesOptions {
73 filters: Some(self.filters.clone()),
74 };
75 let response = self
76 .docker
77 .prune_images(Some(options))
78 .await
79 .map_err(docker_error)?;
80 let images_deleted = response
81 .images_deleted
82 .unwrap_or_default()
83 .into_iter()
84 .filter_map(|i| i.deleted.or(i.untagged))
85 .collect();
86 Ok(ImagePruneOutput {
87 images_deleted,
88 space_reclaimed: response.space_reclaimed.unwrap_or(0) as u64,
89 })
90 }
91}
92
93#[async_trait]
94impl Operation for ImagePrune {
95 fn kind(&self) -> &str {
96 "docker"
97 }
98
99 async fn execute(&self, ctx: &OperationContext) -> Result<Value, OperationError> {
100 to_value(&self.run(ctx).await?)
101 }
102
103 fn input(&self) -> Option<Value> {
104 Some(serde_json::json!({
105 "operation": "image_prune",
106 }))
107 }
108}
109
110impl TypedOperation for ImagePrune {
111 type Output = ImagePruneOutput;
112}