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}