Skip to main content

isoloom_render/
container.rs

1//! What every target that runs the machines as containers shares, whichever backend writes the
2//! files (Compose, Kubernetes) or builds the host they run on (a cloud VM, a local VM): the
3//! images Isoloom brings and the readiness probe here; the one-shot jobs and how a Compose
4//! project starts (`jobs`); the project files read into Compose's environment
5//! (`project_files`); the size of the VM the containers run on (`host`); the containers' side
6//! of a hybrid environment (`hybrid`). Pure functions over the spec and the plan.
7
8mod host;
9mod hybrid;
10mod jobs;
11mod project_files;
12
13pub use host::HostSize;
14pub use hybrid::{HybridContainers, docker_net};
15pub use jobs::{as_arguments, init_names, leaf_jobs, start_commands};
16pub use project_files::{copied_from_project, host_environment, project_variables, variable};
17
18use isoloom_plan::Health;
19use isoloom_spec::model::Machine;
20
21/// The check runner: a small image with `sh`, `curl` and busybox `nc`.
22pub const CHECK_IMAGE: &str = "curlimages/curl:8.11.1";
23
24/// A static busybox Isoloom brings into every machine with services, so its probe needs
25/// nothing from the machine's image (distroless and `scratch` images have no shell).
26pub const PROBE_IMAGE: &str = "busybox:1.37.0-musl";
27/// Where a machine sees that busybox (read-only).
28pub const PROBE_DIR: &str = "/.isoloom-probe";
29
30/// A small image with busybox `ip`, for the router, route sidecars and the stand-in.
31pub const UTILITY_IMAGE: &str = "alpine:3.20";
32
33/// A TCP probe for each service port but the dormant ones, run by Isoloom's own busybox (see
34/// [`PROBE_IMAGE`]).
35#[must_use]
36pub fn probe(m: &Machine) -> String {
37    m.ready_ports()
38        .iter()
39        .map(|port| format!("{PROBE_DIR}/busybox nc -z -w 2 127.0.0.1 {port}"))
40        .collect::<Vec<_>>()
41        .join(" && ")
42}
43
44/// Everything a machine's readiness checks, as one line for Isoloom's busybox `sh`: its ports
45/// ([`probe`]), then its own healthcheck (`health`; a page through busybox `wget`), grouped so
46/// its own `||` stays its own. Empty when there is neither.
47#[must_use]
48pub fn ready_test(m: &Machine, health: Option<&Health>) -> String {
49    let own = health.map(|h| format!("( {} )", h.shell_test(&format!("{PROBE_DIR}/busybox wget"))));
50    [probe(m)].into_iter().filter(|t| !t.is_empty()).chain(own).collect::<Vec<_>>().join(" && ")
51}
52
53/// The runner of a machine's `exec` checks, in `.isoloom/docker/checks/`: piped into the
54/// machine (`docker compose exec -T <machine> sh -s < exec-<machine>.sh`).
55#[must_use]
56pub fn exec_runner(machine: &str) -> String {
57    format!("exec-{machine}.sh")
58}
59
60#[cfg(test)]
61mod tests;