use crate::config::ContainerConfig;
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct ContainerId(String);
impl ContainerId {
#[must_use]
pub fn new() -> Self {
Self(Uuid::new_v4().to_string().replace('-', "")[..12].to_string())
}
#[must_use]
pub fn from_string(s: impl Into<String>) -> Self {
Self(s.into())
}
#[must_use]
pub fn as_str(&self) -> &str {
&self.0
}
}
impl Default for ContainerId {
fn default() -> Self {
Self::new()
}
}
impl std::fmt::Display for ContainerId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum ContainerState {
Created,
Starting,
Running,
Paused,
Restarting,
Exited,
Removing,
Dead,
}
impl std::fmt::Display for ContainerState {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Created => write!(f, "created"),
Self::Starting => write!(f, "starting"),
Self::Running => write!(f, "running"),
Self::Paused => write!(f, "paused"),
Self::Restarting => write!(f, "restarting"),
Self::Exited => write!(f, "exited"),
Self::Removing => write!(f, "removing"),
Self::Dead => write!(f, "dead"),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Container {
pub id: ContainerId,
pub name: String,
pub image: String,
pub machine_name: Option<String>,
pub state: ContainerState,
pub created: DateTime<Utc>,
pub started_at: Option<DateTime<Utc>>,
pub finished_at: Option<DateTime<Utc>>,
pub exit_code: Option<i32>,
pub config: Option<ContainerConfig>,
}
impl Container {
#[must_use]
pub fn new(name: impl Into<String>, image: impl Into<String>) -> Self {
Self {
id: ContainerId::new(),
name: name.into(),
image: image.into(),
machine_name: None,
state: ContainerState::Created,
created: Utc::now(),
started_at: None,
finished_at: None,
exit_code: None,
config: None,
}
}
#[must_use]
pub fn with_config(name: impl Into<String>, config: ContainerConfig) -> Self {
Self {
id: ContainerId::new(),
name: name.into(),
image: config.image.clone(),
machine_name: None,
state: ContainerState::Created,
created: Utc::now(),
started_at: None,
finished_at: None,
exit_code: None,
config: Some(config),
}
}
#[must_use]
pub fn new_for_machine(
name: impl Into<String>,
image: impl Into<String>,
machine: impl Into<String>,
) -> Self {
Self {
id: ContainerId::new(),
name: name.into(),
image: image.into(),
machine_name: Some(machine.into()),
state: ContainerState::Created,
created: Utc::now(),
started_at: None,
finished_at: None,
exit_code: None,
config: None,
}
}
#[must_use]
pub fn with_config_for_machine(
name: impl Into<String>,
config: ContainerConfig,
machine: impl Into<String>,
) -> Self {
Self {
id: ContainerId::new(),
name: name.into(),
image: config.image.clone(),
machine_name: Some(machine.into()),
state: ContainerState::Created,
created: Utc::now(),
started_at: None,
finished_at: None,
exit_code: None,
config: Some(config),
}
}
#[must_use]
pub fn is_running(&self) -> bool {
self.state == ContainerState::Running
}
}