use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;
use crate::entities::containered_opts::{ContainerExecutor, ContaineredOpts, PortBinding};
use crate::entities::info::ShortName;
#[derive(Deserialize, Serialize, PartialEq, Eq, PartialOrd, Ord, Clone, Default)]
pub struct ComposeServiceOpts {
pub image: String,
#[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
pub environment: BTreeMap<String, String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub ports: Vec<PortBinding>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub volumes: Vec<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub command: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub healthcheck_cmd: Option<String>,
#[serde(
default = "default_healthcheck_interval",
skip_serializing_if = "is_default_healthcheck_interval"
)]
pub healthcheck_interval_secs: u64,
#[serde(
default = "default_healthcheck_retries",
skip_serializing_if = "is_default_healthcheck_retries"
)]
pub healthcheck_retries: u32,
}
fn default_healthcheck_interval() -> u64 {
5
}
fn is_default_healthcheck_interval(v: &u64) -> bool {
*v == 5
}
fn default_healthcheck_retries() -> u32 {
3
}
fn is_default_healthcheck_retries(v: &u32) -> bool {
*v == 3
}
impl std::fmt::Display for ComposeServiceOpts {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut parts = vec![format!("image: {}", self.image)];
if !self.environment.is_empty() {
parts.push(format!("{} env vars", self.environment.len()));
}
if !self.ports.is_empty() {
parts.push(format!("{} port(s)", self.ports.len()));
}
if !self.volumes.is_empty() {
parts.push(format!("{} volume(s)", self.volumes.len()));
}
if self.healthcheck_cmd.is_some() {
parts.push("healthcheck".to_string());
}
write!(f, "{}", parts.join(", "))
}
}
#[derive(Deserialize, Serialize, PartialEq, Eq, PartialOrd, Ord, Clone, Default)]
pub struct ComposeOpts {
pub app: ContaineredOpts,
#[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
pub services: BTreeMap<String, ComposeServiceOpts>,
#[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
pub with: BTreeMap<String, ShortName>,
#[serde(skip_serializing_if = "Option::is_none")]
pub project_name: Option<String>,
#[serde(default, skip_serializing_if = "crate::utils::is_false")]
pub detach: bool,
#[serde(default, skip_serializing_if = "crate::utils::is_false")]
pub abort_on_container_exit: bool,
#[serde(default = "crate::utils::yes", skip_serializing_if = "crate::utils::is_true")]
pub remove_on_exit: bool,
#[serde(default, skip_serializing_if = "ContainerExecutor::is_default")]
pub executor: ContainerExecutor,
}
impl ComposeOpts {
pub fn effective_executor(&self) -> &ContainerExecutor {
if self.executor.is_default() {
&self.app.executor
} else {
&self.executor
}
}
}