Skip to main content

swf_builders/services/task/
run.rs

1use super::*;
2
3// ============== RunTaskDefinitionBuilder ==============
4/// Internal enum tracking which process type variant is being built for a run task.
5pub(crate) enum ProcessDefinitionBuilder {
6    /// Container process builder.
7    Container(Box<ContainerProcessDefinitionBuilder>),
8    /// Script process builder.
9    Script(Box<ScriptProcessDefinitionBuilder>),
10    /// Shell command process builder.
11    Shell(Box<ShellProcessDefinitionBuilder>),
12    /// Sub-workflow process builder.
13    Workflow(Box<WorkflowProcessDefinitionBuilder>),
14}
15
16/// Builder for constructing a run task that executes a container, script, shell command, or sub-workflow.
17#[derive(Default)]
18pub struct RunTaskDefinitionBuilder {
19    task: RunTaskDefinition,
20    builder: Option<ProcessDefinitionBuilder>,
21}
22
23/// Macro to generate process variant methods for RunTaskDefinitionBuilder.
24macro_rules! process_variant_method {
25    ($method:ident, $variant:ident, $builder:ident) => {
26        pub fn $method(&mut self) -> &mut $builder {
27            self.builder = Some(ProcessDefinitionBuilder::$variant(Box::default()));
28            match &mut self.builder {
29                Some(ProcessDefinitionBuilder::$variant(ref mut builder)) => builder,
30                _ => unreachable!(concat!(
31                    "Builder should always be set to ",
32                    stringify!($variant)
33                )),
34            }
35        }
36    };
37}
38
39impl RunTaskDefinitionBuilder {
40    pub fn new() -> Self {
41        Self::default()
42    }
43
44    process_variant_method!(container, Container, ContainerProcessDefinitionBuilder);
45    process_variant_method!(script, Script, ScriptProcessDefinitionBuilder);
46    process_variant_method!(shell, Shell, ShellProcessDefinitionBuilder);
47    process_variant_method!(workflow, Workflow, WorkflowProcessDefinitionBuilder);
48}
49
50impl TaskDefinitionBuilderBase for RunTaskDefinitionBuilder {
51    fn if_(&mut self, condition: &str) -> &mut Self {
52        self.task.common.if_ = Some(condition.to_string());
53        self
54    }
55
56    fn with_timeout_reference(&mut self, reference: &str) -> &mut Self {
57        self.task.common.timeout = Some(OneOfTimeoutDefinitionOrReference::Reference(
58            reference.to_string(),
59        ));
60        self
61    }
62
63    fn with_timeout<F>(&mut self, setup: F) -> &mut Self
64    where
65        F: FnOnce(&mut TimeoutDefinitionBuilder),
66    {
67        let mut builder = TimeoutDefinitionBuilder::new();
68        setup(&mut builder);
69        let timeout = builder.build();
70        self.task.common.timeout = Some(OneOfTimeoutDefinitionOrReference::Timeout(timeout));
71        self
72    }
73
74    fn with_input<F>(&mut self, setup: F) -> &mut Self
75    where
76        F: FnOnce(&mut InputDataModelDefinitionBuilder),
77    {
78        let mut builder = InputDataModelDefinitionBuilder::new();
79        setup(&mut builder);
80        self.task.common.input = Some(builder.build());
81        self
82    }
83
84    fn with_output<F>(&mut self, setup: F) -> &mut Self
85    where
86        F: FnOnce(&mut OutputDataModelDefinitionBuilder),
87    {
88        let mut builder = OutputDataModelDefinitionBuilder::new();
89        setup(&mut builder);
90        self.task.common.output = Some(builder.build());
91        self
92    }
93
94    fn with_export<F>(&mut self, setup: F) -> &mut Self
95    where
96        F: FnOnce(&mut OutputDataModelDefinitionBuilder),
97    {
98        let mut builder = OutputDataModelDefinitionBuilder::new();
99        setup(&mut builder);
100        self.task.common.export = Some(builder.build());
101        self
102    }
103
104    fn then(&mut self, directive: &str) -> &mut Self {
105        self.task.common.then = Some(directive.to_string());
106        self
107    }
108
109    fn build(mut self) -> TaskDefinition {
110        if let Some(builder) = self.builder.take() {
111            match builder {
112                ProcessDefinitionBuilder::Container(b) => self.task.run.container = Some(b.build()),
113                ProcessDefinitionBuilder::Script(b) => self.task.run.script = Some(b.build()),
114                ProcessDefinitionBuilder::Shell(b) => self.task.run.shell = Some(b.build()),
115                ProcessDefinitionBuilder::Workflow(b) => self.task.run.workflow = Some(b.build()),
116            }
117        }
118        TaskDefinition::Run(Box::new(self.task))
119    }
120}
121
122/// Builder for constructing a container process definition.
123pub struct ContainerProcessDefinitionBuilder {
124    container: ContainerProcessDefinition,
125}
126
127impl ContainerProcessDefinitionBuilder {
128    fn new() -> Self {
129        Self {
130            container: ContainerProcessDefinition::default(),
131        }
132    }
133
134    /// Sets the container image to run.
135    pub fn with_image(&mut self, image: &str) -> &mut Self {
136        self.container.image = image.to_string();
137        self
138    }
139
140    /// Sets the command to execute inside the container.
141    pub fn with_command(&mut self, command: &str) -> &mut Self {
142        self.container.command = Some(command.to_string());
143        self
144    }
145
146    /// Sets the port mappings for the container.
147    pub fn with_ports(&mut self, ports: HashMap<String, serde_json::Value>) -> &mut Self {
148        self.container.ports = Some(ports);
149        self
150    }
151
152    /// Sets the volume mounts for the container.
153    pub fn with_volumes(&mut self, volumes: HashMap<String, serde_json::Value>) -> &mut Self {
154        self.container.volumes = Some(volumes);
155        self
156    }
157
158    /// Replaces all environment variables with the provided map.
159    pub fn with_environment_variables(&mut self, env: HashMap<String, String>) -> &mut Self {
160        self.container.environment = Some(env);
161        self
162    }
163
164    /// Adds a single environment variable to the container.
165    pub fn with_env(&mut self, key: &str, value: &str) -> &mut Self {
166        self.container
167            .environment
168            .get_or_insert_with(HashMap::new)
169            .insert(key.to_string(), value.to_string());
170        self
171    }
172
173    /// Builds the `ContainerProcessDefinition`.
174    pub fn build(self) -> ContainerProcessDefinition {
175        self.container
176    }
177}
178
179impl Default for ContainerProcessDefinitionBuilder {
180    fn default() -> Self {
181        Self::new()
182    }
183}
184
185/// Builder for constructing a script process definition.
186pub struct ScriptProcessDefinitionBuilder {
187    script: ScriptProcessDefinition,
188}
189
190impl ScriptProcessDefinitionBuilder {
191    fn new() -> Self {
192        Self {
193            script: ScriptProcessDefinition::default(),
194        }
195    }
196
197    /// Sets the script source code to execute.
198    pub fn with_code(&mut self, code: &str) -> &mut Self {
199        self.script.code = Some(code.to_string());
200        self
201    }
202
203    /// Builds the `ScriptProcessDefinition`.
204    pub fn build(self) -> ScriptProcessDefinition {
205        self.script
206    }
207}
208
209impl Default for ScriptProcessDefinitionBuilder {
210    fn default() -> Self {
211        Self::new()
212    }
213}
214
215/// Builder for constructing a shell process definition.
216pub struct ShellProcessDefinitionBuilder {
217    shell: ShellProcessDefinition,
218}
219
220impl ShellProcessDefinitionBuilder {
221    fn new() -> Self {
222        Self {
223            shell: ShellProcessDefinition::default(),
224        }
225    }
226
227    /// Sets the shell command to execute.
228    pub fn with_command(&mut self, command: &str) -> &mut Self {
229        self.shell.command = command.to_string();
230        self
231    }
232
233    /// Sets the shell command arguments.
234    pub fn with_arguments(&mut self, arguments: OneOfRunArguments) -> &mut Self {
235        self.shell.arguments = Some(arguments);
236        self
237    }
238
239    /// Sets the shell command arguments as a key-value map.
240    pub fn with_map_arguments(&mut self, args: HashMap<String, Value>) -> &mut Self {
241        self.shell.arguments = Some(OneOfRunArguments::Map(args));
242        self
243    }
244
245    /// Sets the shell command arguments as an ordered array of strings.
246    pub fn with_array_arguments(&mut self, args: Vec<String>) -> &mut Self {
247        self.shell.arguments = Some(OneOfRunArguments::Array(args));
248        self
249    }
250
251    /// Builds the `ShellProcessDefinition`.
252    pub fn build(self) -> ShellProcessDefinition {
253        self.shell
254    }
255}
256
257impl Default for ShellProcessDefinitionBuilder {
258    fn default() -> Self {
259        Self::new()
260    }
261}
262
263/// Builder for constructing a sub-workflow process definition.
264pub struct WorkflowProcessDefinitionBuilder {
265    workflow: WorkflowProcessDefinition,
266}
267
268impl WorkflowProcessDefinitionBuilder {
269    fn new() -> Self {
270        Self {
271            workflow: WorkflowProcessDefinition::default(),
272        }
273    }
274
275    /// Sets the namespace of the target workflow.
276    pub fn with_namespace(&mut self, namespace: &str) -> &mut Self {
277        self.workflow.namespace = namespace.to_string();
278        self
279    }
280
281    /// Sets the name of the target workflow.
282    pub fn with_name(&mut self, name: &str) -> &mut Self {
283        self.workflow.name = name.to_string();
284        self
285    }
286
287    /// Sets the version of the target workflow.
288    pub fn with_version(&mut self, version: &str) -> &mut Self {
289        self.workflow.version = version.to_string();
290        self
291    }
292
293    /// Sets the input data for the target workflow.
294    pub fn with_input(&mut self, input: Value) -> &mut Self {
295        self.workflow.input = Some(input);
296        self
297    }
298
299    /// Builds the `WorkflowProcessDefinition`.
300    pub fn build(self) -> WorkflowProcessDefinition {
301        self.workflow
302    }
303}
304
305impl Default for WorkflowProcessDefinitionBuilder {
306    fn default() -> Self {
307        Self::new()
308    }
309}