use isoloom_plan::{Build, Image};
use isoloom_spec::model::Target;
use super::*;
use crate::testing;
fn runner(m: &str) -> Option<String> {
let env = testing::machine(m, Target::Docker, &[]);
let c = Configured::of(&env, "m")?;
let Some(Image::Container {
build: Some(Build::Generated { process, .. }),
..
}) = &env.machines["m"].image
else {
return None;
};
script(&c, process)
}
#[test]
fn one_daemon_is_execd_with_its_logs_on_the_containers_output() {
let r = runner("os: debian@12, ports: { web: 80 }, app: { steps: [{ packages: [nginx] }, { service: nginx }] }").expect("a runner");
assert!(r.starts_with("#!/bin/sh\n# Generated by isoloom"), "{r}");
assert!(
r.contains("rm -f '/var/log/nginx/access.log' && ln -s /dev/stdout '/var/log/nginx/access.log'\n"),
"{r}"
);
assert!(
r.contains("rm -f '/var/log/nginx/error.log' && ln -s /dev/stderr '/var/log/nginx/error.log'\n"),
"{r}"
);
assert!(r.ends_with("isoloom_as '' '' 'nginx' '-g' 'daemon off;'\n"), "{r}");
assert!(!r.contains("isoloom_watch"));
}
#[test]
fn several_daemons_are_started_in_order_and_watched() {
let r = runner(
"os: debian@12, app: { steps: [{ service: { name: api, run: [/srv/api, --port, '8000'], cwd: /srv } }, { service: { name: worker, run: [/srv/worker], user: api } }] }",
)
.expect("a runner");
assert!(
r.contains("isoloom_start 'api' '' '/srv' '/srv/api' '--port' '8000'\nisoloom_start 'worker' 'api' '' '/srv/worker'\nisoloom_watch\n"),
"{r}"
);
assert!(r.contains("trap 'isoloom_stop; exit 143' TERM INT"));
}
#[test]
fn a_daemon_and_the_machines_command_run_side_by_side() {
let r = runner("os: debian@12, command: [tail, -f, /dev/null], app: { steps: [{ service: { name: api, run: [/srv/api] } }] }").expect("a runner");
assert!(r.contains("isoloom_start command '' '' \"$@\"\nisoloom_watch\n"), "{r}");
}
#[test]
fn a_container_without_services_has_no_runner() {
assert_eq!(runner("os: debian@12, app: { steps: [{ packages: [curl] }] }"), None);
assert_eq!(
runner("os: debian@12, command: [sleep, infinity], app: { steps: [{ packages: [curl] }] }"),
None
);
}
#[cfg(unix)]
#[test]
fn the_runner_parses_as_sh() {
for m in [
"os: debian@12, ports: { web: 80 }, app: { steps: [{ packages: [nginx] }, { service: nginx }] }",
"os: debian@12, app: { steps: [{ service: { name: a, run: [/a] } }, { service: { name: b, run: [/b, \"it's\"] } }] }",
] {
let r = runner(m).expect("a runner");
let status = std::process::Command::new("sh").args(["-n", "-c", &r]).status().expect("sh runs");
assert!(status.success(), "{r}");
}
}
fn started() -> (isoloom_plan::Environment, ContainerProcess) {
let mut env = testing::machine(
"os: debian@12, app: { steps: [{ command: [touch, /run/started], creates: /run/started }, { run: prepare.sh }] }",
Target::Docker,
&[],
);
if let Some(r) = env.machines.get_mut("m").and_then(|m| m.recipe.as_mut()) {
r.start = std::mem::take(&mut r.install);
}
let process = ContainerProcess::Started {
entrypoint: vec!["/docker-entrypoint.sh".into()],
command: vec!["nginx".into(), "-g".into(), "daemon off;".into()],
};
(env, process)
}
#[test]
fn an_images_start_steps_run_then_its_own_process() {
let (env, process) = started();
let c = Configured::of(&env, "m").unwrap();
let r = script(&c, &process).expect("a runner");
assert!(r.contains(". /usr/local/lib/isoloom/configure.sh\ncd /opt/isoloom\nisoloom_command 'creates' '1' '/run/started' 'touch' '/run/started'\nsh '/opt/isoloom/prepare.sh'\n"), "{r}");
assert!(r.ends_with("exec '/docker-entrypoint.sh' \"$@\"\n"), "{r}");
let d = super::super::dockerfile::render(&c, "nginx@sha256:0", &process);
assert!(!d.contains("RUN"), "start runs at each start, not at build: {d}");
assert!(
d.ends_with("COPY prepare.sh prepare.sh\nCOPY --chmod=0755 .isoloom/configure/m/run /usr/local/bin/isoloom-run\nENTRYPOINT [\"/usr/local/bin/isoloom-run\"]\nCMD [\"nginx\",\"-g\",\"daemon off;\"]\n"),
"{d}"
);
}
#[cfg(unix)]
#[test]
fn the_started_runner_parses_as_sh() {
let (env, process) = started();
let r = script(&Configured::of(&env, "m").unwrap(), &process).unwrap();
assert!(std::process::Command::new("sh").args(["-n", "-c", &r]).status().unwrap().success(), "{r}");
}