use super::strings;
use crate::model;
use std::collections::BTreeMap;
use std::path::PathBuf;
use std::time::Duration;
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct BuildStep {
pub name: String,
pub script: String,
pub user: Option<String>,
pub cache_key: String,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Shell(pub Vec<String>);
impl Default for Shell {
fn default() -> Self {
Self(strings(&["/bin/bash", "-euo", "pipefail", "-c"]))
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct CachePolicy {
pub restore: bool,
pub keep: usize,
pub keep_for: Duration,
}
impl Default for CachePolicy {
fn default() -> Self {
Self {
restore: true,
keep: 24,
keep_for: Duration::from_secs(14 * 24 * 60 * 60),
}
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct BuildPlan {
pub name: String,
pub base: String,
pub tag: String,
pub cpus: u32,
pub memory_in_bytes: u64,
pub vm: model::VmResources,
pub mounts: Vec<model::Mount>,
pub steps: Vec<BuildStep>,
pub environment: Vec<String>,
pub labels: BTreeMap<String, String>,
pub user: Option<String>,
pub workdir: Option<PathBuf>,
pub interface: model::NatInterface,
pub base_key: String,
pub rootfs_size_in_bytes: u64,
pub cache: CachePolicy,
pub shell: Shell,
pub keepalive: Vec<String>,
pub reclaim: bool,
}
impl BuildPlan {
pub fn default_keepalive() -> Vec<String> {
strings(&["/bin/sh", "-c", "while :; do sleep 86400; done"])
}
pub fn new(
name: impl Into<String>,
base: impl Into<String>,
tag: impl Into<String>,
interface: model::NatInterface,
base_key: impl Into<String>,
) -> Self {
let container = model::LinuxContainerConfiguration::default();
Self {
name: name.into(),
base: base.into(),
tag: tag.into(),
cpus: container.cpus,
memory_in_bytes: container.memory_in_bytes,
vm: model::VmResources::default(),
mounts: Vec::new(),
steps: Vec::new(),
environment: Vec::new(),
labels: BTreeMap::new(),
user: None,
workdir: None,
interface,
base_key: base_key.into(),
rootfs_size_in_bytes: model::BootSpec::DEFAULT_ROOTFS_SIZE_IN_BYTES,
cache: CachePolicy::default(),
shell: Shell::default(),
keepalive: Self::default_keepalive(),
reclaim: true,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::model::GIB;
#[test]
fn builds_with_bash_failing_a_step_and_reclaims_after() {
let plan = BuildPlan::new(
"builder",
"docker.io/library/debian:stable-slim",
"example/base:latest",
model::NatInterface::new("192.168.64.7/24", "192.168.64.1"),
"basekey",
);
assert_eq!(plan.shell.0, ["/bin/bash", "-euo", "pipefail", "-c"]);
assert!(plan.cache.restore);
assert_eq!(plan.cache.keep, 24);
assert_eq!(plan.cache.keep_for, Duration::from_secs(14 * 24 * 60 * 60));
assert!(plan.reclaim);
assert_eq!(plan.rootfs_size_in_bytes, 8 * GIB);
}
}