Skip to main content

stormchaser_runner_docker/container_machine/
mod.rs

1//! Docker container execution state machine.
2
3use serde_json::Value;
4use std::collections::HashMap;
5use stormchaser_model::dsl::Step;
6
7/// Cryptographic utilities for container state encryption.
8pub mod crypto;
9/// Docker-specific helper utilities.
10pub mod docker_utils;
11/// State machine transitions for containers.
12pub mod transitions;
13
14use bollard::Docker;
15use serde::{Deserialize, Serialize};
16use uuid::Uuid;
17
18/// Metadata associated with a container executing a workflow step.
19#[derive(Debug, Clone, Serialize, Deserialize)]
20pub struct ContainerMetadata {
21    /// The unique identifier of the workflow run.
22    pub run_id: Uuid,
23    /// The unique identifier of the step being executed.
24    pub step_id: Uuid,
25    /// The step specification from the workflow DSL.
26    pub step_dsl: Step,
27    /// When the container task was received.
28    pub received_at: chrono::DateTime<chrono::Utc>,
29    /// Optional encryption key for secure state sharing.
30    pub encryption_key: Option<String>,
31    /// Optional storage mounts configured for the container.
32    pub storage: Option<HashMap<String, Value>>,
33    /// Optional URLs for uploading test reports.
34    pub test_report_urls: Option<HashMap<String, Value>>,
35}
36
37/// Metrics collected during or after the container's execution.
38#[derive(Debug, Clone, Serialize, Deserialize, Default)]
39pub struct ContainerMetrics {
40    /// The exit code of the container, if it has finished.
41    pub exit_code: Option<i64>,
42    /// How long the container ran in milliseconds.
43    pub duration_ms: u64,
44    /// How long the container took to start after being received, in milliseconds.
45    pub latency_ms: u64,
46    /// Hashes of the storage artifacts generated by the container.
47    pub storage_hashes: Option<HashMap<String, String>>,
48    /// Artifacts generated by the container.
49    pub artifacts: Option<HashMap<String, Value>>,
50    /// Test reports generated by the container.
51    pub test_reports: Option<Value>,
52}
53
54/// The final outcome state of the container.
55#[derive(Debug, Clone, Serialize, Deserialize)]
56pub enum ContainerState {
57    /// The container completed successfully.
58    Succeeded(ContainerMetrics),
59    /// The container failed with an error message and metrics.
60    Failed(String, ContainerMetrics),
61}
62
63/// The result of attempting to start the container.
64pub enum StartResult {
65    /// The container was successfully started.
66    Running(DockerContainerMachine<state::Running>),
67    /// The container failed to start.
68    #[allow(dead_code)]
69    Failed(DockerContainerMachine<state::Finished>),
70}
71
72/// State types for the container state machine.
73pub mod state {
74    /// The initial state before starting.
75    pub struct Initialized;
76    /// The state when the container is currently running.
77    pub struct Running {
78        /// The name of the Docker container.
79        pub container_name: String,
80        /// The time the container was dispatched to run.
81        pub dispatched_at: chrono::DateTime<chrono::Utc>,
82        /// Docker volumes that need to be cleaned up after execution.
83        pub volumes_to_cleanup: Vec<String>,
84        /// Names of the storage endpoints.
85        pub storage_names: Vec<String>,
86        /// The mounts configured for this container.
87        pub mounts: Vec<bollard::service::Mount>,
88    }
89    /// The state when the container has finished executing.
90    pub struct Finished {
91        /// The final result of the execution.
92        pub result: super::ContainerState,
93    }
94}
95
96/// The core state machine representing a Docker container's lifecycle.
97#[derive(Clone)]
98pub struct DockerContainerMachine<S> {
99    /// The NATS client used for messaging, if available.
100    pub nats: Option<async_nats::Client>,
101    /// The Docker client.
102    pub docker: Docker,
103    /// Metadata associated with this container execution.
104    pub metadata: ContainerMetadata,
105    /// The current state of the machine.
106    pub state: S,
107}
108
109impl DockerContainerMachine<state::Initialized> {
110    /// Creates a new, initialized container state machine.
111    pub fn new(
112        docker: Docker,
113        metadata: ContainerMetadata,
114        nats: Option<async_nats::Client>,
115    ) -> Self {
116        Self {
117            nats,
118            docker,
119            metadata,
120            state: state::Initialized,
121        }
122    }
123}