1use crate::config::ContainerConfig;
4use chrono::{DateTime, Utc};
5use serde::{Deserialize, Serialize};
6use uuid::Uuid;
7
8#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
10pub struct ContainerId(String);
11
12impl ContainerId {
13 #[must_use]
15 pub fn new() -> Self {
16 Self(Uuid::new_v4().to_string().replace('-', "")[..12].to_string())
17 }
18
19 #[must_use]
21 pub fn from_string(s: impl Into<String>) -> Self {
22 Self(s.into())
23 }
24
25 #[must_use]
27 pub fn as_str(&self) -> &str {
28 &self.0
29 }
30}
31
32impl Default for ContainerId {
33 fn default() -> Self {
34 Self::new()
35 }
36}
37
38impl std::fmt::Display for ContainerId {
39 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
40 write!(f, "{}", self.0)
41 }
42}
43
44#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
46#[serde(rename_all = "lowercase")]
47pub enum ContainerState {
48 Created,
50 Starting,
52 Running,
54 Paused,
56 Restarting,
58 Exited,
60 Removing,
62 Dead,
64}
65
66impl std::fmt::Display for ContainerState {
67 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
68 match self {
69 Self::Created => write!(f, "created"),
70 Self::Starting => write!(f, "starting"),
71 Self::Running => write!(f, "running"),
72 Self::Paused => write!(f, "paused"),
73 Self::Restarting => write!(f, "restarting"),
74 Self::Exited => write!(f, "exited"),
75 Self::Removing => write!(f, "removing"),
76 Self::Dead => write!(f, "dead"),
77 }
78 }
79}
80
81#[derive(Debug, Clone, Serialize, Deserialize)]
83pub struct Container {
84 pub id: ContainerId,
86 pub name: String,
88 pub image: String,
90 pub machine_name: Option<String>,
92 pub state: ContainerState,
94 pub created: DateTime<Utc>,
96 pub started_at: Option<DateTime<Utc>>,
98 pub finished_at: Option<DateTime<Utc>>,
100 pub exit_code: Option<i32>,
102 pub config: Option<ContainerConfig>,
104}
105
106impl Container {
107 #[must_use]
109 pub fn new(name: impl Into<String>, image: impl Into<String>) -> Self {
110 Self {
111 id: ContainerId::new(),
112 name: name.into(),
113 image: image.into(),
114 machine_name: None,
115 state: ContainerState::Created,
116 created: Utc::now(),
117 started_at: None,
118 finished_at: None,
119 exit_code: None,
120 config: None,
121 }
122 }
123
124 #[must_use]
126 pub fn with_config(name: impl Into<String>, config: ContainerConfig) -> Self {
127 Self {
128 id: ContainerId::new(),
129 name: name.into(),
130 image: config.image.clone(),
131 machine_name: None,
132 state: ContainerState::Created,
133 created: Utc::now(),
134 started_at: None,
135 finished_at: None,
136 exit_code: None,
137 config: Some(config),
138 }
139 }
140
141 #[must_use]
143 pub fn new_for_machine(
144 name: impl Into<String>,
145 image: impl Into<String>,
146 machine: impl Into<String>,
147 ) -> Self {
148 Self {
149 id: ContainerId::new(),
150 name: name.into(),
151 image: image.into(),
152 machine_name: Some(machine.into()),
153 state: ContainerState::Created,
154 created: Utc::now(),
155 started_at: None,
156 finished_at: None,
157 exit_code: None,
158 config: None,
159 }
160 }
161
162 #[must_use]
164 pub fn with_config_for_machine(
165 name: impl Into<String>,
166 config: ContainerConfig,
167 machine: impl Into<String>,
168 ) -> Self {
169 Self {
170 id: ContainerId::new(),
171 name: name.into(),
172 image: config.image.clone(),
173 machine_name: Some(machine.into()),
174 state: ContainerState::Created,
175 created: Utc::now(),
176 started_at: None,
177 finished_at: None,
178 exit_code: None,
179 config: Some(config),
180 }
181 }
182
183 #[must_use]
185 pub fn is_running(&self) -> bool {
186 self.state == ContainerState::Running
187 }
188}