use std::fmt;
use std::str::FromStr;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "kebab-case")]
pub enum BuilderBackendKind {
BuildahCli,
BuildahSidecar,
Sandbox,
Hcs,
}
impl BuilderBackendKind {
#[must_use]
pub const fn as_str(self) -> &'static str {
match self {
Self::BuildahCli => "buildah-cli",
Self::BuildahSidecar => "buildah-sidecar",
Self::Sandbox => "sandbox",
Self::Hcs => "hcs",
}
}
}
impl fmt::Display for BuilderBackendKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.as_str())
}
}
impl FromStr for BuilderBackendKind {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.trim().to_ascii_lowercase().as_str() {
"buildah-cli" | "buildah" | "cli" => Ok(Self::BuildahCli),
"buildah-sidecar" | "sidecar" | "buildd" => Ok(Self::BuildahSidecar),
"sandbox" | "macos-sandbox" => Ok(Self::Sandbox),
"hcs" | "windows-hcs" => Ok(Self::Hcs),
other => Err(format!(
"unknown builder backend kind: {other:?} (expected one of: \
buildah-cli, buildah-sidecar, sandbox, hcs)"
)),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct SidecarConfig {
#[serde(skip_serializing_if = "Option::is_none")]
pub addr: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub tls_dir: Option<std::path::PathBuf>,
#[serde(default = "SidecarConfig::default_idle_secs")]
pub idle_secs: u64,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub storage_graph_root: Option<std::path::PathBuf>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub storage_run_root: Option<std::path::PathBuf>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub storage_driver: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub context_mount: Option<(std::path::PathBuf, std::path::PathBuf)>,
}
impl SidecarConfig {
pub const DEFAULT_IDLE_SECS: u64 = 30;
#[must_use]
pub fn default_idle_secs() -> u64 {
Self::DEFAULT_IDLE_SECS
}
}
impl Default for SidecarConfig {
fn default() -> Self {
Self {
addr: None,
tls_dir: None,
idle_secs: Self::DEFAULT_IDLE_SECS,
storage_graph_root: None,
storage_run_root: None,
storage_driver: None,
context_mount: None,
}
}
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[allow(clippy::struct_excessive_bools)]
pub struct BuildSidecarRequest {
pub context_dir: String,
pub dockerfile_paths: Vec<String>,
pub tags: Vec<String>,
pub platforms: Vec<String>,
pub build_args: std::collections::BTreeMap<String, String>,
pub secrets: Vec<String>,
pub ssh: Vec<String>,
pub target_stage: Option<String>,
pub host_network: bool,
pub cache_from: Option<String>,
pub cache_to: Option<String>,
pub no_cache: bool,
pub squash: bool,
pub layers: bool,
pub format: Option<String>,
pub pull_policy: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum BuildSidecarEvent {
StageStarted {
index: u32,
name: Option<String>,
base_image: String,
},
StageFinished {
index: u32,
},
InstructionStarted {
stage: u32,
index: u32,
instruction: String,
},
InstructionFinished {
stage: u32,
index: u32,
cached: bool,
},
Log {
line: String,
is_stderr: bool,
},
Warning {
message: String,
},
Finished {
image_id: String,
manifest_ref: Option<String>,
},
Error {
message: String,
},
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn backend_kind_round_trips_through_as_str() {
for kind in [
BuilderBackendKind::BuildahCli,
BuilderBackendKind::BuildahSidecar,
BuilderBackendKind::Sandbox,
BuilderBackendKind::Hcs,
] {
assert_eq!(BuilderBackendKind::from_str(kind.as_str()).unwrap(), kind);
}
}
#[test]
fn backend_kind_accepts_aliases() {
assert_eq!(
BuilderBackendKind::from_str("buildah").unwrap(),
BuilderBackendKind::BuildahCli
);
assert_eq!(
BuilderBackendKind::from_str("sidecar").unwrap(),
BuilderBackendKind::BuildahSidecar
);
assert_eq!(
BuilderBackendKind::from_str("BUILDAH-SIDECAR").unwrap(),
BuilderBackendKind::BuildahSidecar
);
}
#[test]
fn sidecar_config_idle_default() {
let cfg = SidecarConfig::default();
assert_eq!(cfg.idle_secs, 30);
assert!(cfg.addr.is_none());
assert!(cfg.tls_dir.is_none());
assert!(cfg.storage_graph_root.is_none());
assert!(cfg.storage_run_root.is_none());
assert!(cfg.storage_driver.is_none());
}
}