ironflow_ops_docker/containers/
create.rs1use async_trait::async_trait;
4use bollard::Docker;
5use bollard::models::ContainerCreateBody;
6use bollard::query_parameters::CreateContainerOptions;
7use ironflow_core::error::OperationError;
8use ironflow_core::operation::{Operation, OperationContext, TypedOperation};
9use serde::{Deserialize, Serialize};
10use serde_json::Value;
11
12use crate::containers::DockerRef;
13use crate::helpers::{docker_error, to_value};
14
15#[derive(Debug, Clone, Serialize, Deserialize)]
17pub struct ContainerCreateOutput {
18 pub id: String,
20 pub warnings: Vec<String>,
22}
23
24pub struct ContainerCreate {
38 docker: Docker,
39 name: String,
40 image: String,
41 cmd: Option<Vec<String>>,
42 env: Option<Vec<String>>,
43 exposed_ports: Option<Vec<String>>,
44}
45
46impl ContainerCreate {
47 pub fn new(
49 client: impl Into<DockerRef>,
50 name: impl Into<String>,
51 image: impl Into<String>,
52 ) -> Self {
53 Self {
54 docker: client.into().0,
55 name: name.into(),
56 image: image.into(),
57 cmd: None,
58 env: None,
59 exposed_ports: None,
60 }
61 }
62
63 pub fn cmd(mut self, cmd: Vec<String>) -> Self {
65 self.cmd = Some(cmd);
66 self
67 }
68
69 pub fn env(mut self, env: Vec<String>) -> Self {
71 self.env = Some(env);
72 self
73 }
74
75 pub fn exposed_ports(mut self, ports: Vec<String>) -> Self {
77 self.exposed_ports = Some(ports);
78 self
79 }
80
81 pub async fn run(
88 &self,
89 _ctx: &OperationContext,
90 ) -> Result<ContainerCreateOutput, OperationError> {
91 let options = CreateContainerOptions {
92 name: Some(self.name.clone()),
93 platform: String::new(),
94 };
95 let config = ContainerCreateBody {
96 image: Some(self.image.clone()),
97 cmd: self.cmd.clone(),
98 env: self.env.clone(),
99 exposed_ports: self.exposed_ports.clone(),
100 ..Default::default()
101 };
102 let response = self
103 .docker
104 .create_container(Some(options), config)
105 .await
106 .map_err(docker_error)?;
107 Ok(ContainerCreateOutput {
108 id: response.id,
109 warnings: response.warnings,
110 })
111 }
112}
113
114#[async_trait]
115impl Operation for ContainerCreate {
116 fn kind(&self) -> &str {
117 "docker"
118 }
119
120 async fn execute(&self, ctx: &OperationContext) -> Result<Value, OperationError> {
121 to_value(&self.run(ctx).await?)
122 }
123
124 fn input(&self) -> Option<Value> {
125 Some(serde_json::json!({
126 "operation": "container_create",
127 "name": self.name,
128 "image": self.image,
129 }))
130 }
131}
132
133impl TypedOperation for ContainerCreate {
134 type Output = ContainerCreateOutput;
135}