ironflow_ops_docker/containers/
state.rs1use async_trait::async_trait;
4use bollard::Docker;
5use bollard::query_parameters::{RenameContainerOptions, TopOptions};
6use ironflow_core::error::OperationError;
7use ironflow_core::operation::{Operation, OperationContext, TypedOperation};
8use serde::{Deserialize, Serialize};
9use serde_json::Value;
10
11use crate::containers::DockerRef;
12use crate::helpers::{docker_error, to_value};
13
14#[derive(Debug, Clone, Serialize, Deserialize)]
20pub struct ContainerPauseOutput {
21 pub container: String,
23}
24
25pub struct ContainerPause {
39 docker: Docker,
40 container: String,
41}
42
43impl ContainerPause {
44 pub fn new(client: impl Into<DockerRef>, container: impl Into<String>) -> Self {
46 Self {
47 docker: client.into().0,
48 container: container.into(),
49 }
50 }
51
52 pub async fn run(
58 &self,
59 _ctx: &OperationContext,
60 ) -> Result<ContainerPauseOutput, OperationError> {
61 self.docker
62 .pause_container(&self.container)
63 .await
64 .map_err(docker_error)?;
65 Ok(ContainerPauseOutput {
66 container: self.container.clone(),
67 })
68 }
69}
70
71#[async_trait]
72impl Operation for ContainerPause {
73 fn kind(&self) -> &str {
74 "docker"
75 }
76
77 async fn execute(&self, ctx: &OperationContext) -> Result<Value, OperationError> {
78 to_value(&self.run(ctx).await?)
79 }
80
81 fn input(&self) -> Option<Value> {
82 Some(serde_json::json!({
83 "operation": "container_pause",
84 "container": self.container,
85 }))
86 }
87}
88
89impl TypedOperation for ContainerPause {
90 type Output = ContainerPauseOutput;
91}
92
93#[derive(Debug, Clone, Serialize, Deserialize)]
99pub struct ContainerUnpauseOutput {
100 pub container: String,
102}
103
104pub struct ContainerUnpause {
118 docker: Docker,
119 container: String,
120}
121
122impl ContainerUnpause {
123 pub fn new(client: impl Into<DockerRef>, container: impl Into<String>) -> Self {
125 Self {
126 docker: client.into().0,
127 container: container.into(),
128 }
129 }
130
131 pub async fn run(
137 &self,
138 _ctx: &OperationContext,
139 ) -> Result<ContainerUnpauseOutput, OperationError> {
140 self.docker
141 .unpause_container(&self.container)
142 .await
143 .map_err(docker_error)?;
144 Ok(ContainerUnpauseOutput {
145 container: self.container.clone(),
146 })
147 }
148}
149
150#[async_trait]
151impl Operation for ContainerUnpause {
152 fn kind(&self) -> &str {
153 "docker"
154 }
155
156 async fn execute(&self, ctx: &OperationContext) -> Result<Value, OperationError> {
157 to_value(&self.run(ctx).await?)
158 }
159
160 fn input(&self) -> Option<Value> {
161 Some(serde_json::json!({
162 "operation": "container_unpause",
163 "container": self.container,
164 }))
165 }
166}
167
168impl TypedOperation for ContainerUnpause {
169 type Output = ContainerUnpauseOutput;
170}
171
172#[derive(Debug, Clone, Serialize, Deserialize)]
178pub struct ContainerRenameOutput {
179 pub old_name: String,
181 pub new_name: String,
183}
184
185pub struct ContainerRename {
199 docker: Docker,
200 container: String,
201 new_name: String,
202}
203
204impl ContainerRename {
205 pub fn new(
207 client: impl Into<DockerRef>,
208 container: impl Into<String>,
209 new_name: impl Into<String>,
210 ) -> Self {
211 Self {
212 docker: client.into().0,
213 container: container.into(),
214 new_name: new_name.into(),
215 }
216 }
217
218 pub async fn run(
224 &self,
225 _ctx: &OperationContext,
226 ) -> Result<ContainerRenameOutput, OperationError> {
227 let options = RenameContainerOptions {
228 name: self.new_name.clone(),
229 };
230 self.docker
231 .rename_container(&self.container, options)
232 .await
233 .map_err(docker_error)?;
234 Ok(ContainerRenameOutput {
235 old_name: self.container.clone(),
236 new_name: self.new_name.clone(),
237 })
238 }
239}
240
241#[async_trait]
242impl Operation for ContainerRename {
243 fn kind(&self) -> &str {
244 "docker"
245 }
246
247 async fn execute(&self, ctx: &OperationContext) -> Result<Value, OperationError> {
248 to_value(&self.run(ctx).await?)
249 }
250
251 fn input(&self) -> Option<Value> {
252 Some(serde_json::json!({
253 "operation": "container_rename",
254 "container": self.container,
255 "new_name": self.new_name,
256 }))
257 }
258}
259
260impl TypedOperation for ContainerRename {
261 type Output = ContainerRenameOutput;
262}
263
264#[derive(Debug, Clone, Serialize, Deserialize)]
270pub struct ContainerTopOutput {
271 pub titles: Vec<String>,
273 pub processes: Vec<Vec<String>>,
275}
276
277pub struct ContainerTop {
291 docker: Docker,
292 container: String,
293 ps_args: Option<String>,
294}
295
296impl ContainerTop {
297 pub fn new(client: impl Into<DockerRef>, container: impl Into<String>) -> Self {
299 Self {
300 docker: client.into().0,
301 container: container.into(),
302 ps_args: None,
303 }
304 }
305
306 pub fn ps_args(mut self, args: impl Into<String>) -> Self {
308 self.ps_args = Some(args.into());
309 self
310 }
311
312 pub async fn run(&self, _ctx: &OperationContext) -> Result<ContainerTopOutput, OperationError> {
319 let options = self.ps_args.as_ref().map(|args| TopOptions {
320 ps_args: args.to_string(),
321 });
322 let response = self
323 .docker
324 .top_processes(&self.container, options)
325 .await
326 .map_err(docker_error)?;
327 Ok(ContainerTopOutput {
328 titles: response.titles.unwrap_or_default(),
329 processes: response.processes.unwrap_or_default(),
330 })
331 }
332}
333
334#[async_trait]
335impl Operation for ContainerTop {
336 fn kind(&self) -> &str {
337 "docker"
338 }
339
340 async fn execute(&self, ctx: &OperationContext) -> Result<Value, OperationError> {
341 to_value(&self.run(ctx).await?)
342 }
343
344 fn input(&self) -> Option<Value> {
345 Some(serde_json::json!({
346 "operation": "container_top",
347 "container": self.container,
348 }))
349 }
350}
351
352impl TypedOperation for ContainerTop {
353 type Output = ContainerTopOutput;
354}