Skip to main content

stormchaser_model/
dsl.rs

1//! Domain-Specific Language (DSL) abstract syntax tree and types.
2
3use schemars::JsonSchema;
4use serde::{Deserialize, Serialize};
5use serde_json::Value;
6use std::collections::HashMap;
7
8/// Root structure representing a parsed workflow definition.
9#[derive(Debug, Clone, Serialize, Deserialize)]
10pub struct Workflow {
11    /// Indicates if this workflow is a reusable template.
12    #[serde(default)]
13    pub is_template: bool,
14    /// The version of the Stormchaser DSL used.
15    pub dsl_version: String,
16    /// The name of the workflow.
17    pub name: String,
18    /// Optional description of the workflow.
19    pub description: Option<String>,
20    /// Optional cron schedule for triggering the workflow.
21    pub cron: Option<String>,
22    /// External reusable workflows or templates imported.
23    pub libraries: Vec<Library>,
24    /// Custom step definitions imported for this workflow.
25    #[serde(default)]
26    pub step_libraries: Vec<StepLibrary>,
27    /// Sub-workflows included for execution.
28    #[serde(default)]
29    pub includes: Vec<Include>,
30    /// Execution strategy and constraints for the workflow.
31    pub strategy: Option<Strategy>,
32    /// Resource quotas applied to the entire workflow run.
33    pub quotas: Option<Quotas>,
34    /// Storage configurations to provision.
35    pub storage: Vec<Storage>,
36    /// Expected inputs for the workflow.
37    pub inputs: Vec<Input>,
38    /// Outputs to be produced by the workflow.
39    pub outputs: Vec<Output>,
40    /// Event handlers for system or custom events.
41    pub handlers: Vec<Handler>,
42    /// The sequential or parallel steps to execute.
43    pub steps: Vec<Step>,
44    /// Steps to execute if the main workflow fails.
45    pub on_failure: Option<Vec<Step>>,
46    /// Steps to execute regardless of success or failure.
47    pub finally: Option<Vec<Step>>,
48}
49
50/// Import definition for external workflow templates.
51#[derive(Debug, Clone, Serialize, Deserialize)]
52pub struct Library {
53    /// Alias to use when referencing this library.
54    pub name: String,
55    /// Source URI of the library.
56    pub source: String,
57    /// Specific version or reference of the library.
58    pub version: String,
59    /// Checksum to verify the library's integrity.
60    pub checksum: String,
61}
62
63/// Import definition for external step types.
64#[derive(Debug, Clone, Serialize, Deserialize)]
65pub struct StepLibrary {
66    /// Alias to use for the imported step type.
67    pub name: String,
68    /// The base step type being imported.
69    pub r#type: String,
70    /// Default parameters applied to the step.
71    #[serde(default)]
72    pub params: HashMap<String, String>,
73    /// Step specification override.
74    #[serde(default)]
75    pub spec: Value,
76    /// Default timeout for the step.
77    pub timeout: Option<String>,
78    /// Whether failures are ignored by default.
79    pub allow_failure: Option<bool>,
80    /// Default retry policy.
81    pub retry: Option<RetryPolicy>,
82}
83
84/// Defines an inclusion of another workflow.
85#[derive(Debug, Clone, Serialize, Deserialize)]
86pub struct Include {
87    /// Name of the inclusion block.
88    pub name: String,
89    /// Reference to the workflow to include.
90    pub workflow: String,
91    /// Input variables to pass to the included workflow.
92    #[serde(default)]
93    pub inputs: HashMap<String, String>,
94}
95
96/// Execution strategy settings (e.g., parallelism, affinity).
97#[derive(Debug, Clone, Serialize, Deserialize)]
98pub struct Strategy {
99    /// Runner affinity rules.
100    pub affinity: Option<String>,
101    /// Whether to abort all parallel steps if one fails.
102    pub fail_fast: Option<bool>,
103    /// Maximum number of parallel executions.
104    pub max_parallel: Option<u32>,
105    /// List of allowed processes or capabilities.
106    pub process_allow_list: Option<Vec<String>>,
107}
108
109/// Resource quotas for a run.
110#[derive(Debug, Clone, Serialize, Deserialize)]
111pub struct Quotas {
112    /// Maximum concurrent steps.
113    pub max_concurrency: Option<u32>,
114    /// Maximum CPU limit.
115    pub max_cpu: Option<String>,
116    /// Maximum memory limit.
117    pub max_memory: Option<String>,
118    /// Maximum storage limit.
119    pub max_storage: Option<String>,
120    /// Maximum duration.
121    pub timeout: Option<String>,
122}
123
124/// Storage volume definition to be provisioned.
125#[derive(Debug, Clone, Serialize, Deserialize)]
126pub struct Storage {
127    /// Logical name of the storage volume.
128    pub name: String,
129    /// Type of backend (e.g., 's3', 'gcs').
130    pub backend: Option<String>,
131    /// Size of the storage requested.
132    pub size: String,
133    /// Pre-provisioning instructions (e.g., download an artifact into it).
134    pub provision: Vec<Provision>,
135    /// Paths to preserve after execution.
136    pub preserve: Vec<String>,
137    /// Artifacts to upload.
138    pub artifacts: Vec<Artifact>,
139    /// Retention policy for the storage.
140    pub retainment: Option<String>,
141}
142
143/// Instructions for provisioning data into storage.
144#[derive(Debug, Clone, Serialize, Deserialize)]
145pub struct Provision {
146    /// Type of resource to provision.
147    pub resource_type: String, // "secret", "config", "download", "artifact"
148    /// Name of the provision block.
149    pub name: String,
150    /// Source reference.
151    pub source: Option<String>,
152    /// URL to download from.
153    pub url: Option<String>,
154    /// Destination path.
155    pub destination: String,
156    /// File mode/permissions.
157    pub mode: Option<String>,
158    /// Verification checksum.
159    pub checksum: Option<String>,
160    /// Optional specific origin.
161    pub from: Option<String>,
162}
163
164/// Definition of an artifact to collect and upload.
165#[derive(Debug, Clone, Serialize, Deserialize)]
166pub struct Artifact {
167    /// Logical name of the artifact.
168    pub name: String,
169    /// Local path to the artifact file or directory.
170    pub path: String,
171    /// Retention period.
172    pub retention: String,
173}
174
175/// Workflow input parameter definition.
176#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
177pub struct Input {
178    /// Name of the input variable.
179    pub name: String,
180    /// Data type of the input.
181    pub r#type: String,
182    /// Description of the input.
183    pub description: Option<String>,
184    /// Default value if not provided.
185    pub default: Option<Value>,
186    /// Regex or validation rule for the input.
187    pub validation: Option<String>,
188    /// Allowed options for enum-like inputs.
189    pub options: Option<Vec<String>>,
190    /// Dynamic query to fetch options.
191    pub query: Option<String>,
192}
193
194/// Workflow output value definition.
195#[derive(Debug, Clone, Serialize, Deserialize)]
196pub struct Output {
197    /// Name of the output variable.
198    pub name: String,
199    /// CEL Expression to evaluate the output value.
200    pub value: String, // CEL Expression
201}
202
203/// Event handler mapping an event to an action.
204#[derive(Debug, Clone, Serialize, Deserialize)]
205pub struct Handler {
206    /// Name of the handler.
207    pub name: String,
208    /// Type of event to match.
209    pub event_type: String,
210    /// Condition expression to filter events.
211    pub condition: Option<String>,
212    /// Action to execute when the event occurs.
213    pub action: String,
214}
215
216/// Execution step definition within a workflow.
217#[derive(Debug, Clone, Serialize, Deserialize)]
218pub struct Step {
219    /// Name of the step.
220    pub name: String,
221    /// Type of the step.
222    pub r#type: String, // e.g., "GitCheckout", "RunContainer", "Parallel", etc.
223    /// CEL condition controlling whether the step runs.
224    pub condition: Option<String>,
225    /// Evaluated parameters for the step.
226    pub params: HashMap<String, String>, // CEL Expressions
227
228    /// Step-specific specification.
229    /// This allows each step type to define its own structured parameters.
230    /// For "RunContainer" on K8s, this would be a K8sJobSpec.
231    #[serde(default)]
232    pub spec: Value,
233
234    /// Execution strategy overrides for this step.
235    pub strategy: Option<Strategy>,
236    /// Values to aggregate from iterated steps.
237    pub aggregation: Vec<Aggregation>,
238    /// Iteration expression (e.g., a list of items to map over).
239    pub iterate: Option<String>,
240    /// Variable name for the current iteration item.
241    pub iterate_as: Option<String>,
242    /// Child steps if this is a group (e.g., Parallel).
243    pub steps: Option<Vec<Step>>, // For Parallel/Sequential
244    /// Next steps to execute after this one.
245    pub next: Vec<String>,
246    /// Steps to execute if this step fails.
247    pub on_failure: Option<Box<Step>>,
248    /// Retry policy for this step.
249    pub retry: Option<RetryPolicy>,
250    /// Timeout duration.
251    pub timeout: Option<String>,
252    /// Whether failure of this step should be ignored.
253    pub allow_failure: Option<bool>,
254    /// Log marker indicating the start of a section.
255    pub start_marker: Option<String>,
256    /// Log marker indicating the end of a section.
257    pub end_marker: Option<String>,
258    /// Extraction rules to capture output values.
259    pub outputs: Vec<OutputExtraction>,
260    /// Test reports to collect.
261    #[serde(default)]
262    pub reports: Vec<TestReport>,
263    /// Specific artifacts to collect for this step.
264    #[serde(default)]
265    pub artifacts: Option<Vec<String>>,
266}
267
268/// Definition for capturing a test report.
269#[derive(Debug, Clone, Serialize, Deserialize)]
270pub struct TestReport {
271    /// Name of the report.
272    pub name: String,
273    /// Path to the report file.
274    pub path: String,
275    /// Format of the report (e.g., 'junit').
276    pub format: String, // e.g., "junit"
277}
278
279/// Mount definition for attaching storage to a container.
280#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
281pub struct StorageMount {
282    /// Name of the storage volume to mount.
283    pub name: String,
284    /// Path where the volume should be mounted inside the container.
285    pub mount_path: String,
286    /// Whether the mount should be read-only.
287    pub read_only: Option<bool>,
288}
289
290/// Minimal common set of arguments for running containers (portable across runners)
291#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
292pub struct CommonContainerSpec {
293    /// Container image to run.
294    pub image: String,
295    /// Override the container entrypoint.
296    pub command: Option<Vec<String>>,
297    /// Arguments passed to the command.
298    pub args: Option<Vec<String>>,
299    /// Environment variables.
300    pub env: Option<Vec<EnvVar>>,
301    /// Requested CPU.
302    pub cpu: Option<String>,
303    /// Requested memory.
304    pub memory: Option<String>,
305    /// Whether to run in privileged mode.
306    pub privileged: Option<bool>,
307    /// Storage volumes to mount.
308    pub storage_mounts: Option<Vec<StorageMount>>,
309}
310
311/// Structured specification for a Kubernetes Job (RunK8sJob step)
312#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
313pub struct K8sJobSpec {
314    /// Container image.
315    pub image: String,
316    /// Command.
317    pub command: Option<Vec<String>>,
318    /// Arguments.
319    pub args: Option<Vec<String>>,
320    /// Environment variables.
321    pub env: Option<Vec<EnvVar>>,
322    /// Resource requirements.
323    pub resources: Option<Resources>,
324    /// Secret mounts.
325    pub secret_mounts: Option<Vec<SecretMount>>,
326    /// Config map mounts.
327    pub config_map_mounts: Option<Vec<ConfigMapMount>>,
328    /// Storage mounts.
329    pub storage_mounts: Option<Vec<StorageMount>>,
330
331    /// Active deadline seconds.
332    pub active_deadline_seconds: Option<i64>,
333    /// Backoff limit.
334    pub backoff_limit: Option<i32>,
335    /// Completions.
336    pub completions: Option<i32>,
337    /// Parallelism.
338    pub parallelism: Option<i32>,
339    /// TTL seconds after finished.
340    pub ttl_seconds_after_finished: Option<i32>,
341    /// Privileged flag.
342    pub privileged: Option<bool>,
343    /// Minimum version of K8s node.
344    pub minimum_version: Option<String>,
345    /// Node selector labels.
346    pub node_selector: Option<HashMap<String, String>>,
347    /// Service account name.
348    pub service_account_name: Option<String>,
349    /// Restart policy.
350    pub restart_policy: Option<String>, // "OnFailure" or "Never"
351    /// Custom labels.
352    pub labels: Option<HashMap<String, String>>,
353    /// Custom annotations.
354    pub annotations: Option<HashMap<String, String>>,
355}
356
357/// Key-value pair for environment variables.
358#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
359pub struct EnvVar {
360    /// Variable name.
361    pub name: String,
362    /// Variable value.
363    pub value: String,
364}
365
366/// Resource specification for CPU and memory.
367#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
368pub struct Resources {
369    /// Minimum guaranteed resources.
370    pub requests: Option<ResourceRequirements>,
371    /// Maximum allowed resources.
372    pub limits: Option<ResourceRequirements>,
373}
374
375/// Resource requirements structure.
376#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
377pub struct ResourceRequirements {
378    /// CPU specification.
379    pub cpu: Option<String>,
380    /// Memory specification.
381    pub memory: Option<String>,
382}
383
384/// Secret mount definition.
385#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
386pub struct SecretMount {
387    /// Name of the secret.
388    pub name: String,
389    /// Mount path.
390    pub mount_path: String,
391}
392
393/// ConfigMap mount definition.
394#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
395pub struct ConfigMapMount {
396    /// Name of the ConfigMap.
397    pub name: String,
398    /// Mount path.
399    pub mount_path: String,
400}
401
402/// Aggregation rule for map/reduce patterns.
403#[derive(Debug, Clone, Serialize, Deserialize)]
404pub struct Aggregation {
405    /// Name of the aggregation.
406    pub name: String,
407    /// Optional description.
408    pub description: Option<String>,
409    /// CEL Expression for aggregation.
410    pub value: String, // CEL Expression
411}
412
413/// Rule for extracting outputs from logs or files.
414#[derive(Debug, Clone, Serialize, Deserialize)]
415pub struct OutputExtraction {
416    /// Output key name.
417    pub name: String,
418    /// Source to extract from (e.g., 'stdout', 'file').
419    pub source: String,
420    /// Optional marker string.
421    pub marker: Option<String>,
422    /// Data format (e.g., 'json', 'regex').
423    pub format: Option<String>,
424    /// Regular expression to match.
425    pub regex: Option<String>,
426    /// Regex capture group index.
427    pub group: Option<u32>,
428    /// Whether the extracted output is sensitive.
429    pub sensitive: Option<bool>,
430}
431
432/// Step retry policy definition.
433#[derive(Debug, Clone, Serialize, Deserialize)]
434pub struct RetryPolicy {
435    /// Number of retry attempts.
436    pub count: u32,
437    /// Backoff strategy ('fixed', 'exponential').
438    pub backoff: String,
439    /// Maximum backoff delay.
440    pub max_delay: Option<String>,
441}
442
443/// Human-in-the-loop approval specification.
444#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
445pub struct ApprovalSpec {
446    /// List of user IDs or groups allowed to approve.
447    pub approvers: Option<Vec<String>>,
448    /// Input fields required during approval.
449    pub inputs: Option<Vec<Input>>,
450    /// Notification settings.
451    pub notify: Option<EmailSpec>,
452    /// Timeout for waiting for approval.
453    pub timeout: Option<String>,
454}
455
456/// Specification for waiting on a system event.
457#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
458pub struct WaitEventSpec {
459    /// Key used for correlation.
460    pub correlation_key: String,
461    /// Expected value for correlation.
462    pub correlation_value: String,
463    /// Timeout.
464    pub timeout: Option<String>,
465}
466
467/// Specification for invoking an AWS Lambda function.
468#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
469pub struct LambdaInvokeSpec {
470    /// Name of the Lambda function.
471    pub function_name: String,
472    /// JSON payload.
473    pub payload: Option<Value>,
474    /// Invocation type.
475    pub invocation_type: Option<String>, // "RequestResponse", "Event", "DryRun"
476    /// Qualifier (alias/version).
477    pub qualifier: Option<String>, // Alias or version
478    /// AWS Region.
479    pub region: Option<String>,
480    /// IAM Role ARN to assume.
481    pub assume_role_arn: Option<String>, // IAM Role ARN to assume
482    /// Optional session name.
483    pub role_session_name: Option<String>, // Optional session name for the assumed role
484}
485
486/// Specification for checking out a Git repository.
487#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
488pub struct GitCheckoutSpec {
489    /// Repository URL.
490    pub repo: String,
491    /// Git reference (branch, tag, commit).
492    pub r#ref: Option<String>,
493    /// Clone depth.
494    pub depth: Option<u32>,
495    /// Sparse checkout paths.
496    pub sparse_checkout: Option<Vec<String>>,
497    /// Destination directory.
498    pub destination: Option<String>,
499    /// Storage mounts.
500    pub storage_mounts: Option<Vec<StorageMount>>,
501}
502
503/// Specification for executing a WASM module.
504#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
505pub struct WasmStepSpec {
506    /// URI to WASM module.
507    pub module: String, // URI to WASM module (e.g., file://, s3://, or registry name)
508    /// Function to invoke.
509    pub function: String,
510    /// Arguments to pass.
511    pub args: Option<Value>,
512}
513
514/// Specification for invoking a Webhook.
515#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
516pub struct WebhookInvokeSpec {
517    /// Webhook URL.
518    pub url: String,
519    /// HTTP method.
520    pub method: Option<String>, // Default to POST
521    /// HTTP headers.
522    pub headers: Option<HashMap<String, String>>,
523    /// Request body template.
524    pub body: Option<String>, // MiniJinja template
525    /// Request timeout.
526    pub timeout: Option<String>,
527}
528
529/// Supported email backends.
530#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
531#[serde(rename_all = "snake_case")]
532pub enum EmailBackend {
533    /// Standard SMTP protocol.
534    Smtp,
535    /// Amazon Simple Email Service.
536    Ses,
537}
538
539/// Specification for sending an email notification.
540#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
541pub struct EmailSpec {
542    /// Sender address.
543    pub from: String,
544    /// List of recipient addresses.
545    pub to: Vec<String>,
546    /// CC addresses.
547    pub cc: Option<Vec<String>>,
548    /// BCC addresses.
549    pub bcc: Option<Vec<String>>,
550    /// Email subject.
551    pub subject: String,
552    /// Body template (MiniJinja).
553    pub body: String, // MiniJinja template
554    /// Send as HTML.
555    pub html: Option<bool>,
556    /// Email backend choice.
557    pub backend: Option<EmailBackend>, // Defaults to SMTP
558    /// SMTP Server address.
559    pub smtp_server: Option<String>,
560    /// SMTP Port.
561    pub smtp_port: Option<u16>,
562    /// SMTP username.
563    pub smtp_username: Option<String>,
564    /// SMTP password.
565    pub smtp_password: Option<String>,
566    /// Use TLS.
567    pub smtp_use_tls: Option<bool>,
568    /// Use mTLS.
569    pub smtp_use_mtls: Option<bool>,
570    /// SES region.
571    pub ses_region: Option<String>,
572    /// SES role ARN to assume.
573    pub ses_role_arn: Option<String>,
574    /// SES configuration set.
575    pub ses_configuration_set_name: Option<String>,
576}
577
578/// Specification for rendering a Jinja template.
579#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
580pub struct JinjaRenderSpec {
581    /// The template string.
582    pub template: String,
583    /// Context variables for rendering.
584    pub context: Option<Value>,
585    /// Output key for the result.
586    pub output_key: Option<String>, // Key to store the result in step outputs, defaults to "result"
587}
588
589/// Specification for emailing a test report.
590#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
591pub struct TestReportEmailSpec {
592    /// Sender address.
593    pub from: String,
594    /// Recipient addresses.
595    pub to: Vec<String>,
596    /// Email subject.
597    pub subject: String,
598    /// Custom template to override default.
599    pub template: Option<String>, // Override default template
600    /// Specific report name to send, or all if None.
601    pub report_name: Option<String>, // If None, send all reports for the run
602    /// Backend to use.
603    pub backend: Option<EmailBackend>, // Defaults to SMTP
604    /// SMTP Server.
605    pub smtp_server: Option<String>,
606    /// SMTP Port.
607    pub smtp_port: Option<u16>,
608    /// SMTP username.
609    pub smtp_username: Option<String>,
610    /// SMTP password.
611    pub smtp_password: Option<String>,
612    /// Use TLS.
613    pub smtp_use_tls: Option<bool>,
614    /// Use mTLS.
615    pub smtp_use_mtls: Option<bool>,
616    /// SES region.
617    pub ses_region: Option<String>,
618    /// SES role ARN.
619    pub ses_role_arn: Option<String>,
620    /// SES config set.
621    pub ses_configuration_set_name: Option<String>,
622}
623
624/// Specification for running a JQ query on data.
625#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
626pub struct JqSpec {
627    /// JQ program string.
628    pub program: String,
629    /// JSON input data.
630    pub input: Option<Value>,
631    /// Input file path.
632    pub input_file: Option<String>,
633    /// Output file path.
634    pub output_file: Option<String>,
635    /// Storage mounts.
636    pub storage_mounts: Option<Vec<StorageMount>>,
637}