Skip to main content

swf_core/models/task/
run_task.rs

1use serde::{Deserialize, Serialize};
2use serde_json::Value;
3use std::collections::HashMap;
4
5use super::constants::{ContainerCleanupPolicy, ProcessReturnType};
6use super::TaskDefinitionFields;
7use crate::models::resource::ExternalResourceDefinition;
8
9fn default_await() -> Option<bool> {
10    Some(true)
11}
12
13fn default_return_type() -> Option<String> {
14    Some(ProcessReturnType::STDOUT.to_string())
15}
16
17fn default_cleanup() -> String {
18    ContainerCleanupPolicy::ALWAYS.to_string()
19}
20
21/// Represents the configuration of a task used to run a given process
22#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)]
23pub struct RunTaskDefinition {
24    /// Gets/sets the configuration of the process to execute
25    #[serde(rename = "run")]
26    pub run: ProcessTypeDefinition,
27
28    /// Gets/sets the task's common fields
29    #[serde(flatten)]
30    pub common: TaskDefinitionFields,
31}
32impl RunTaskDefinition {
33    /// Initializes a new RunTaskDefinition
34    pub fn new(run: ProcessTypeDefinition) -> Self {
35        Self {
36            run,
37            common: TaskDefinitionFields::new(),
38        }
39    }
40}
41
42/// Represents the configuration of a process execution
43#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)]
44pub struct ProcessTypeDefinition {
45    /// Gets/sets the configuration of the container to run
46    #[serde(rename = "container", skip_serializing_if = "Option::is_none")]
47    pub container: Option<ContainerProcessDefinition>,
48
49    /// Gets/sets the configuration of the script to run
50    #[serde(rename = "script", skip_serializing_if = "Option::is_none")]
51    pub script: Option<ScriptProcessDefinition>,
52
53    /// Gets/sets the configuration of the shell command to run
54    #[serde(rename = "shell", skip_serializing_if = "Option::is_none")]
55    pub shell: Option<ShellProcessDefinition>,
56
57    /// Gets/sets the configuration of the workflow to run
58    #[serde(rename = "workflow", skip_serializing_if = "Option::is_none")]
59    pub workflow: Option<WorkflowProcessDefinition>,
60
61    /// Gets/sets a boolean indicating whether or not to await the process completion before continuing. Defaults to 'true'
62    #[serde(
63        rename = "await",
64        default = "default_await",
65        skip_serializing_if = "Option::is_none"
66    )]
67    pub await_: Option<bool>,
68
69    /// Gets/sets the configuration of the process output. Defaults to 'stdout'.
70    /// Possible values: 'stdout', 'stderr', 'code', 'all', 'none'
71    #[serde(
72        rename = "return",
73        default = "default_return_type",
74        skip_serializing_if = "Option::is_none"
75    )]
76    pub return_: Option<String>,
77}
78impl ProcessTypeDefinition {
79    /// Creates a new container process
80    pub fn using_container(container: ContainerProcessDefinition, await_: Option<bool>) -> Self {
81        Self {
82            container: Some(container),
83            await_,
84            ..Self::default()
85        }
86    }
87
88    /// Creates a new script process
89    pub fn using_script(script: ScriptProcessDefinition, await_: Option<bool>) -> Self {
90        Self {
91            script: Some(script),
92            await_,
93            ..Self::default()
94        }
95    }
96
97    /// Creates a new shell process
98    pub fn using_shell(shell: ShellProcessDefinition, await_: Option<bool>) -> Self {
99        Self {
100            shell: Some(shell),
101            await_,
102            ..Self::default()
103        }
104    }
105
106    /// Creates a new workflow process
107    pub fn using_workflow(workflow: WorkflowProcessDefinition, await_: Option<bool>) -> Self {
108        Self {
109            workflow: Some(workflow),
110            await_,
111            ..Self::default()
112        }
113    }
114
115    /// Gets the type of the defined process, or None if no process is configured
116    pub fn get_process_type(&self) -> Option<&str> {
117        if self.container.is_some() {
118            Some(super::constants::ProcessType::CONTAINER)
119        } else if self.script.is_some() {
120            Some(super::constants::ProcessType::SCRIPT)
121        } else if self.shell.is_some() {
122            Some(super::constants::ProcessType::SHELL)
123        } else if self.workflow.is_some() {
124            Some(super::constants::ProcessType::WORKFLOW)
125        } else {
126            None
127        }
128    }
129}
130
131/// Represents the configuration of a container's lifetime
132#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)]
133pub struct ContainerLifetimeDefinition {
134    /// Gets/sets the container cleanup policy to use. Defaults to "always" per spec 1.0.3
135    #[serde(rename = "cleanup", default = "default_cleanup")]
136    pub cleanup: String,
137
138    /// Gets/sets the duration after which to cleanup the container, in case the cleanup policy has been set to 'eventually'
139    #[serde(rename = "after", skip_serializing_if = "Option::is_none")]
140    pub after: Option<crate::models::duration::OneOfDurationOrIso8601Expression>,
141}
142
143/// Represents the configuration of a container process
144#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)]
145pub struct ContainerProcessDefinition {
146    /// Gets/sets the name of the container image to run
147    #[serde(rename = "image")]
148    pub image: String,
149
150    /// Gets/sets the name of the container to run
151    #[serde(rename = "name", skip_serializing_if = "Option::is_none")]
152    pub name: Option<String>,
153
154    /// Gets/sets the command, if any, to execute on the container
155    #[serde(rename = "command", skip_serializing_if = "Option::is_none")]
156    pub command: Option<String>,
157
158    /// Gets/sets a list containing the container's port mappings, if any
159    /// Keys and values can be strings or numbers (matches Go SDK's `map[string]interface{}`)
160    #[serde(rename = "ports", skip_serializing_if = "Option::is_none")]
161    pub ports: Option<HashMap<String, Value>>,
162
163    /// Gets/sets the volume mapping for the container, if any
164    /// Matches Go SDK's `map[string]interface{}` which allows both string and object values
165    #[serde(rename = "volumes", skip_serializing_if = "Option::is_none")]
166    pub volumes: Option<HashMap<String, Value>>,
167
168    /// Gets/sets a key/value mapping of the environment variables, if any, to use when running the configured process
169    #[serde(rename = "environment", skip_serializing_if = "Option::is_none")]
170    pub environment: Option<HashMap<String, String>>,
171
172    /// Gets/sets the data to pass to the process via stdin, if any
173    #[serde(rename = "stdin", skip_serializing_if = "Option::is_none")]
174    pub stdin: Option<String>,
175
176    /// Gets/sets a list of arguments, if any, to pass to the container (argv)
177    #[serde(rename = "arguments", skip_serializing_if = "Option::is_none")]
178    pub arguments: Option<Vec<String>>,
179
180    /// Gets/sets the policy that controls how the container's image should be pulled from the registry
181    #[serde(rename = "pullPolicy", skip_serializing_if = "Option::is_none")]
182    pub pull_policy: Option<String>,
183
184    /// Gets/sets the configuration of the container's lifetime
185    #[serde(rename = "lifetime", skip_serializing_if = "Option::is_none")]
186    pub lifetime: Option<ContainerLifetimeDefinition>,
187}
188
189/// Represents a value that can be either a list of arguments (array) or a key/value mapping (object).
190/// Matches Go SDK's RunArguments type which supports both forms.
191#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
192#[serde(untagged)]
193pub enum OneOfRunArguments {
194    /// A list of string arguments (e.g., ["arg1=value1", "arg2"])
195    Array(Vec<String>),
196    /// A key/value mapping of arguments (e.g., {"arg1": "value1"})
197    Map(HashMap<String, Value>),
198}
199
200impl Default for OneOfRunArguments {
201    fn default() -> Self {
202        OneOfRunArguments::Array(Vec::new())
203    }
204}
205
206impl OneOfRunArguments {
207    /// Returns the arguments as a slice if this is an Array variant
208    pub fn as_array(&self) -> Option<&[String]> {
209        match self {
210            OneOfRunArguments::Array(arr) => Some(arr),
211            _ => None,
212        }
213    }
214
215    /// Returns the arguments as a HashMap if this is a Map variant
216    pub fn as_map(&self) -> Option<&HashMap<String, Value>> {
217        match self {
218            OneOfRunArguments::Map(map) => Some(map),
219            _ => None,
220        }
221    }
222
223    /// Returns true if this is an Array variant
224    pub fn is_array(&self) -> bool {
225        matches!(self, OneOfRunArguments::Array(_))
226    }
227
228    /// Returns true if this is a Map variant
229    pub fn is_map(&self) -> bool {
230        matches!(self, OneOfRunArguments::Map(_))
231    }
232}
233
234/// Represents the definition of a script evaluation process
235#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)]
236pub struct ScriptProcessDefinition {
237    /// Gets/sets the language of the script to run
238    #[serde(rename = "language")]
239    pub language: String,
240
241    /// Gets/sets the script's code. Required if 'source' has not been set
242    #[serde(rename = "code", skip_serializing_if = "Option::is_none")]
243    pub code: Option<String>,
244
245    /// Gets the the script's source. Required if 'code' has not been set
246    #[serde(rename = "source", skip_serializing_if = "Option::is_none")]
247    pub source: Option<ExternalResourceDefinition>,
248
249    /// Gets/sets the data to pass to the process via stdin
250    #[serde(rename = "stdin", skip_serializing_if = "Option::is_none")]
251    pub stdin: Option<String>,
252
253    /// Gets/sets the arguments to pass to the script. Can be either a list of strings (argv) or a key/value mapping.
254    #[serde(rename = "arguments", skip_serializing_if = "Option::is_none")]
255    pub arguments: Option<OneOfRunArguments>,
256
257    /// Gets/sets a key/value mapping of the environment variables, if any, to use when running the configured process
258    #[serde(rename = "environment", skip_serializing_if = "Option::is_none")]
259    pub environment: Option<HashMap<String, String>>,
260}
261impl ScriptProcessDefinition {
262    /// Initializes a new script from code
263    pub fn from_code(
264        language: &str,
265        code: String,
266        stdin: Option<String>,
267        arguments: Option<OneOfRunArguments>,
268        environment: Option<HashMap<String, String>>,
269    ) -> Self {
270        Self {
271            language: language.to_string(),
272            code: Some(code),
273            source: None,
274            stdin,
275            arguments,
276            environment,
277        }
278    }
279
280    /// Initializes a new script from an external resource
281    pub fn from_source(
282        language: &str,
283        source: ExternalResourceDefinition,
284        stdin: Option<String>,
285        arguments: Option<OneOfRunArguments>,
286        environment: Option<HashMap<String, String>>,
287    ) -> Self {
288        Self {
289            language: language.to_string(),
290            code: None,
291            source: Some(source),
292            stdin,
293            arguments,
294            environment,
295        }
296    }
297}
298
299/// Represents the definition of a shell process
300#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)]
301pub struct ShellProcessDefinition {
302    /// Gets/sets the shell command to run
303    #[serde(rename = "command")]
304    pub command: String,
305
306    /// Gets/sets the data to pass to the shell command via stdin
307    #[serde(rename = "stdin", skip_serializing_if = "Option::is_none")]
308    pub stdin: Option<String>,
309
310    /// Gets/sets the arguments of the shell command to run (supports both array and map forms, matches Go SDK's RunArguments)
311    #[serde(rename = "arguments", skip_serializing_if = "Option::is_none")]
312    pub arguments: Option<OneOfRunArguments>,
313
314    /// Gets/sets a key/value mapping of the environment variables, if any, to use when running the configured process
315    #[serde(rename = "environment", skip_serializing_if = "Option::is_none")]
316    pub environment: Option<HashMap<String, String>>,
317}
318impl ShellProcessDefinition {
319    pub fn new(
320        command: &str,
321        stdin: Option<String>,
322        arguments: Option<OneOfRunArguments>,
323        environment: Option<HashMap<String, String>>,
324    ) -> Self {
325        Self {
326            command: command.to_string(),
327            stdin,
328            arguments,
329            environment,
330        }
331    }
332}
333
334fn default_workflow_version() -> String {
335    "latest".to_string()
336}
337
338/// Represents the definition of a (sub)workflow process
339#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)]
340pub struct WorkflowProcessDefinition {
341    /// Gets/sets the namespace the workflow to run belongs to
342    #[serde(rename = "namespace")]
343    pub namespace: String,
344
345    /// Gets/sets the name of the workflow to run
346    #[serde(rename = "name")]
347    pub name: String,
348
349    /// Gets/sets the version of the workflow to run. Defaults to 'latest'
350    #[serde(rename = "version", default = "default_workflow_version")]
351    pub version: String,
352
353    /// Gets/sets the data, if any, to pass as input to the workflow to execute. The value should be validated against the target workflow's input schema, if specified
354    #[serde(rename = "input", skip_serializing_if = "Option::is_none")]
355    pub input: Option<Value>,
356}
357impl WorkflowProcessDefinition {
358    pub fn new(namespace: &str, name: &str, version: &str, input: Option<Value>) -> Self {
359        let version = if version.is_empty() {
360            default_workflow_version()
361        } else {
362            version.to_string()
363        };
364        Self {
365            namespace: namespace.to_string(),
366            name: name.to_string(),
367            version,
368            input,
369        }
370    }
371}