Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/holger

xtask/src/k8s.rs

//! **`cargo xtask k8s`**: Holger's Kubernetes flavour (lane B4, A31 §7.3, §7.7).
//!
//! * `image`: build `holger` and `holger-scan-worker` static (musl, release) in
//!   the toolchain container, then mint both images FROM scratch:
//!   `holger.rs/nordisk/holger:<ver>` (distribution/Dockerfile) and
//!   `holger.rs/nordisk/holger-scan-worker:<ver>`
//!   (distribution/scan-worker/Containerfile). No registry is asked
//!   (`--pull=never`, `--network=none`).
//! * `chart`: `helm lint` and `helm template` of deploy/helm/holger, and the
//!   rendered pod checked (two containers, the shared emptyDir, no token, a
//!   read-only root, no privilege escalation, the remote engine in the RON).
//! * `test`: **the container test.** The chart rendered and played by podman
//!   (`podman kube play`): the server and its scan-worker sidecar in one pod,
//!   `/readyz` goes ready, goes 503 naming the sandbox when the sidecar stops,
//!   and ready again when it starts. Then **Holger serves its own image**: a
//!   local Holger (the static binary with the OCI format, holger.rs's shape, as
//!   a local process) takes the worker image by `podman push` and hands it back
//!   to `podman pull`, the same image. Never the live holger.rs.
//! * `publish`: the release step's plan, printed: the two pushes to
//!   holger.rs's own OCI registry. It pushes nothing (the release does).
//!
//! The images come from holger.rs ITSELF (owner decision, 2026-10-26): Holger
//! serves its own OCI images.

use std::path::{Path, PathBuf};
use std::process::{Command, Stdio};
use std::time::{Duration, Instant};

use anyhow::{bail, Context, Result};

/// Holger's own OCI registry: holger.rs, the `nordisk` repository.
pub const REGISTRY: &str = "holger.rs/nordisk";
/// The static target.
pub const MUSL: &str = "x86_64-unknown-linux-musl";
/// The chart.
pub const CHART: &str = "deploy/helm/holger";
/// The container flavour's features: the default (the upstream) without
/// `systemd` (the kubelet is the process manager). A test holds it to the
/// manifest's default.
pub const K8S_FEATURES: &str = "downstream-core,fmt-raw,fmt-rust,fmt-npm,fmt-maven,fmt-python,fmt-docker,fmt-go,fmt-helm,fmt-deb,fmt-rpm,fmt-znippy,fmt-build-thing,secure_update,sign,sync,fetch,export-push";
/// The registry the test stands up in holger.rs's shape: the container flavour
/// plus every format (`all-formats`, the OCI one among them), as holger.rs serves its images.
pub const REGISTRY_FEATURES: &str = "downstream-core,fmt-raw,fmt-rust,fmt-npm,fmt-maven,fmt-python,fmt-docker,fmt-go,fmt-helm,fmt-deb,fmt-rpm,fmt-znippy,fmt-build-thing,secure_update,sign,sync,fetch,export-push,all-formats";
/// Where `build` keeps the registry variant (the server's own path is reused by
/// the next build).
pub const REGISTRY_BIN: &str = "k8s/holger-oci";
/// The test pod's release name: every container it makes is `b4-k8s-…`.
const RELEASE: &str = "b4-k8s";

/// The server's version, from the root workspace (the chart's appVersion).
pub fn version(root: &Path) -> Result<String> {
    let text = std::fs::read_to_string(root.join("Cargo.toml"))?;
    let v: toml::Value = toml::from_str(&text)?;
    v.get("workspace")
        .and_then(|w| w.get("package"))
        .and_then(|p| p.get("version"))
        .and_then(|v| v.as_str())
        .map(str::to_string)
        .context("the root Cargo.toml has no [workspace.package] version")
}

/// The server image.
pub fn server_ref(ver: &str) -> String {
    format!("{REGISTRY}/holger:{ver}")
}

/// The scan-worker sidecar image.
pub fn worker_ref(ver: &str) -> String {
    format!("{REGISTRY}/holger-scan-worker:{ver}")
}

/// What the release pushes, in order.
pub fn publish_plan(ver: &str) -> Vec<String> {
    [server_ref(ver), worker_ref(ver)]
        .into_iter()
        .map(|r| format!("podman push {r} docker://{r}"))
        .collect()
}

fn run(cmd: &mut Command) -> Result<()> {
    let shown = format!("{cmd:?}");
    let st = cmd.status().with_context(|| format!("starting {shown}"))?;
    if !st.success() {
        bail!("{shown} exited {st}");
    }
    Ok(())
}

fn output(cmd: &mut Command) -> Result<String> {
    let shown = format!("{cmd:?}");
    let o = cmd
        .stderr(Stdio::inherit())
        .output()
        .with_context(|| format!("starting {shown}"))?;
    if !o.status.success() {
        bail!("{shown} exited {}", o.status);
    }
    Ok(String::from_utf8_lossy(&o.stdout).into_owned())
}

fn target_dir(root: &Path) -> PathBuf {
    std::env::var_os("CARGO_TARGET_DIR")
        .map(PathBuf::from)
        .unwrap_or_else(|| root.join("target"))
}

/// Build both static binaries in the toolchain container; their paths.
pub fn build(root: &Path) -> Result<(PathBuf, PathBuf)> {
    let parent = root.parent().unwrap_or(root);
    let target = target_dir(root);
    std::fs::create_dir_all(&target)?;
    let registry = std::env::var_os("CARGO_REGISTRY_DIR")
        .map(PathBuf::from)
        .unwrap_or_else(|| {
            PathBuf::from(std::env::var_os("HOME").unwrap_or_default()).join(".cargo/registry")
        });
    let toolchain = std::env::var("TOOLCHAIN_IMAGE")
        .unwrap_or_else(|_| "localhost/nordisk-cargo-toolchain:live".into());
    let out = target.join(MUSL).join("release");
    for (pkg, bin, features) in [
        ("holger", "holger", Some(REGISTRY_FEATURES)),
        ("holger", "holger", Some(K8S_FEATURES)),
        ("holger-scan-worker", "holger-scan-worker", None),
    ] {
        let mut flavour: Vec<String> = Vec::new();
        if let Some(f) = features {
            flavour = vec![
                "--no-default-features".into(),
                "--features".into(),
                f.into(),
            ];
        }
        run(Command::new("podman")
            .args(["run", "--rm", "--pids-limit=-1"])
            .arg(format!("--volume={0}:{0}", parent.display()))
            .arg(format!("--volume={0}:{0}", target.display()))
            .arg(format!(
                "--volume={}:/usr/local/cargo/registry",
                registry.display()
            ))
            .arg(format!("--env=CARGO_TARGET_DIR={}", target.display()))
            .arg(format!("--workdir={}", root.display()))
            .arg(&toolchain)
            .args([
                "cargo",
                "build",
                "--release",
                "--locked",
                "-p",
                pkg,
                "--bin",
                bin,
                "--target",
                MUSL,
            ])
            .args(&flavour))?;
        if features == Some(REGISTRY_FEATURES) {
            let keep = target.join(REGISTRY_BIN);
            std::fs::create_dir_all(keep.parent().unwrap())?;
            std::fs::copy(out.join("holger"), &keep)?;
        }
    }
    Ok((out.join("holger"), out.join("holger-scan-worker")))
}

const PASSWD: &str = "nonroot:x:65532:65532:nonroot:/tmp:/sbin/nologin\nscan:x:65533:65532:scan:/scratch:/sbin/nologin\n";
const GROUP: &str = "nonroot:x:65532:\n";

/// Mint one image from `containerfile` with `bin` beside it.
fn mint(root: &Path, name: &str, containerfile: &str, bin: &Path, tag: &str) -> Result<()> {
    let ctx = target_dir(root).join(format!("k8s-context-{name}"));
    let _ = std::fs::remove_dir_all(&ctx);
    std::fs::create_dir_all(&ctx)?;
    let bytes = std::fs::read(bin).with_context(|| bin.display().to_string())?;
    if !is_static_elf(&bytes) {
        bail!(
            "{} is not a static ELF binary: FROM scratch has no loader",
            bin.display()
        );
    }
    std::fs::write(ctx.join(name), &bytes)?;
    std::fs::copy(root.join(containerfile), ctx.join("Containerfile"))?;
    std::fs::write(ctx.join("passwd"), PASSWD)?;
    std::fs::write(ctx.join("group"), GROUP)?;
    run(Command::new("podman")
        .args([
            "build",
            "--pull=never",
            "--network=none",
            "--layers=false",
            "-f",
        ])
        .arg(ctx.join("Containerfile"))
        .args(["-t", tag])
        .arg(&ctx))?;
    println!("minted {tag}");
    Ok(())
}

/// A static ELF: no `PT_INTERP` program header (no dynamic loader asked for).
pub fn is_static_elf(b: &[u8]) -> bool {
    if b.len() < 64 || !b.starts_with(b"\x7fELF") || b[4] != 2 {
        return false;
    }
    let u16_at = |o: usize| u16::from_le_bytes([b[o], b[o + 1]]) as usize;
    let u64_at = |o: usize| u64::from_le_bytes(b[o..o + 8].try_into().unwrap()) as usize;
    let (phoff, phentsize, phnum) = (u64_at(32), u16_at(54), u16_at(56));
    (0..phnum).all(|i| {
        let o = phoff + i * phentsize;
        o + 4 <= b.len() && u32::from_le_bytes(b[o..o + 4].try_into().unwrap()) != 3
    })
}

/// `image`: both images.
pub fn image(root: &Path, server: &Path, worker: &Path) -> Result<()> {
    let ver = version(root)?;
    mint(
        root,
        "holger",
        "distribution/Dockerfile",
        server,
        &server_ref(&ver),
    )?;
    mint(
        root,
        "holger-scan-worker",
        "distribution/scan-worker/Containerfile",
        worker,
        &worker_ref(&ver),
    )
}

fn helm() -> String {
    std::env::var("HELM").unwrap_or_else(|_| "helm".into())
}

/// `helm template` of the chart with `sets`.
pub fn render(root: &Path, sets: &[&str]) -> Result<String> {
    let mut c = Command::new(helm());
    c.args(["template", RELEASE]).arg(root.join(CHART));
    for s in sets {
        c.args(["--set", s]);
    }
    output(&mut c)
}

/// The rendered documents of one kind.
pub fn docs_of<'a>(rendered: &'a str, kind: &str) -> Vec<&'a str> {
    rendered
        .split("\n---")
        .filter(|d| d.lines().any(|l| l.trim() == format!("kind: {kind}")))
        .collect()
}

/// **The rendered pod, checked.** Every line a hardened sidecar pod must have.
pub fn check_rendered(rendered: &str, ver: &str) -> Result<()> {
    let deploy = docs_of(rendered, "Deployment");
    let [d] = deploy.as_slice() else {
        bail!("the chart renders {} Deployments, not one", deploy.len())
    };
    let want = [
        format!("image: \"{}\"", server_ref(ver)),
        format!("image: \"{}\"", worker_ref(ver)),
        "- name: scan-worker".to_string(),
        "- serve".to_string(),
        "automountServiceAccountToken: false".to_string(),
        "readOnlyRootFilesystem: true".to_string(),
        "allowPrivilegeEscalation: false".to_string(),
        "runAsNonRoot: true".to_string(),
        "path: /readyz".to_string(),
        "mountPath: /run/holger-scan".to_string(),
        "type: RuntimeDefault".to_string(),
    ];
    for w in &want {
        if !d.contains(w.as_str()) {
            bail!("the rendered Deployment lacks `{w}`");
        }
    }
    if d.contains("privileged: true") || d.contains("hostPath") || d.contains("hostNetwork") {
        bail!("the rendered Deployment asks for the host");
    }
    let scan_mounts = d.matches("mountPath: /run/holger-scan").count();
    if scan_mounts != 2 {
        bail!("the shared directory is mounted {scan_mounts} times, not by exactly the server and the sidecar");
    }
    let cm = docs_of(rendered, "ConfigMap").join("\n");
    if !cm.contains("engine: remote") || !cm.contains("/run/holger-scan/worker.sock") {
        bail!("the config's sandbox is not the remote engine on the sidecar's socket");
    }
    let np = docs_of(rendered, "NetworkPolicy").join("\n");
    if !np.contains("Egress") {
        bail!("no NetworkPolicy closes egress");
    }
    Ok(())
}

/// `chart`: lint, render, check.
pub fn chart(root: &Path) -> Result<()> {
    run(Command::new(helm())
        .arg("lint")
        .arg(root.join(CHART))
        .args(["--set", "tls.cert=c", "--set", "tls.key=k"]))?;
    let ver = version(root)?;
    let r = render(root, &["tls.cert=c", "tls.key=k"])?;
    check_rendered(&r, &ver)?;
    let down = render(
        root,
        &["tls.cert=c", "tls.key=k", "scanWorker.enabled=false"],
    )?;
    if down.contains("- name: scan-worker") || down.contains("mountPath: /run/holger-scan") {
        bail!("a downstream (scanWorker.enabled=false) still renders the sidecar");
    }
    println!("chart: lint and template green; the pod is hardened, the sidecar is wired");
    Ok(())
}

/// The test pod's config: the chart's upstream RON without TLS (loopback only).
fn test_ron(chart_ron: &str) -> String {
    let start = chart_ron
        .find("ron_tls: Some((")
        .expect("the chart's RON names ron_tls");
    let end = start + chart_ron[start..].find(")),").expect("ron_tls closes") + 3;
    let mut s = chart_ron.to_string();
    // The pod binds 0.0.0.0 and the host publishes it on 127.0.0.1 only: clear text is
    // written down (HOL-NCSC, `insecure: true`).
    s.replace_range(start..end, "ron_tls: None, insecure: true,");
    s
}

fn http_get(port: u16, path: &str) -> Option<(u16, String)> {
    use std::io::{Read as _, Write as _};
    let mut s = std::net::TcpStream::connect_timeout(
        &([127, 0, 0, 1], port).into(),
        Duration::from_secs(2),
    )
    .ok()?;
    s.set_read_timeout(Some(Duration::from_secs(10))).ok()?;
    s.write_all(
        format!("GET {path} HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n").as_bytes(),
    )
    .ok()?;
    let mut out = String::new();
    s.read_to_string(&mut out).ok()?;
    let code = out.split_whitespace().nth(1)?.parse().ok()?;
    let body = out
        .split_once("\r\n\r\n")
        .map(|(_, b)| b.to_string())
        .unwrap_or_default();
    Some((code, body))
}

fn wait_for(port: u16, path: &str, want: u16, secs: u64) -> Result<String> {
    let t = Instant::now();
    let mut last = None;
    while t.elapsed() < Duration::from_secs(secs) {
        last = http_get(port, path);
        if let Some((c, b)) = &last {
            if *c == want {
                return Ok(b.clone());
            }
        }
        std::thread::sleep(Duration::from_millis(500));
    }
    bail!("{path} never answered {want} in {secs} s; last {last:?}")
}

fn free_port() -> Result<u16> {
    Ok(std::net::TcpListener::bind("127.0.0.1:0")?
        .local_addr()?
        .port())
}

fn podman_quiet(args: &[&str]) {
    let _ = Command::new("podman")
        .args(args)
        .stdout(Stdio::null())
        .stderr(Stdio::null())
        .status();
}

/// `test`: the pod plays, `/readyz` follows the sidecar, Holger serves its image.
pub fn test(root: &Path) -> Result<()> {
    let ver = version(root)?;
    for r in [server_ref(&ver), worker_ref(&ver)] {
        if !Command::new("podman")
            .args(["image", "exists", &r])
            .status()
            .is_ok_and(|s| s.success())
        {
            bail!("{r} is not on this host: run `cargo xtask k8s image` first");
        }
    }
    let values = std::fs::read_to_string(root.join(CHART).join("values.yaml"))?;
    let chart_ron = values_ron(&values)?;
    let dir = target_dir(root).join("k8s-test");
    let _ = std::fs::remove_dir_all(&dir);
    std::fs::create_dir_all(&dir)?;
    let ron_file = dir.join("holger.ron");
    std::fs::write(&ron_file, test_ron(&chart_ron))?;
    let mut c = Command::new(helm());
    c.args(["template", RELEASE]).arg(root.join(CHART));
    for s in [
        "tls.enabled=false",
        "image.pullPolicy=Never",
        "scanWorker.image.pullPolicy=Never",
        "networkPolicy.enabled=false",
    ] {
        c.args(["--set", s]);
    }
    c.arg("--set-file")
        .arg(format!("config.ron={}", ron_file.display()));
    let rendered = output(&mut c)?;
    // podman plays the pod's own kinds; the Service and the policy are the cluster's.
    let playable: Vec<&str> = ["Secret", "ConfigMap", "PersistentVolumeClaim", "Deployment"]
        .iter()
        .flat_map(|k| docs_of(&rendered, k))
        .collect();
    // Kubernetes makes an emptyDir mode 0777; podman hands it to whichever
    // container mounts it first (0755). The shared directory is laid here with
    // Kubernetes' mode, so the server (65532) and the sidecar (65533) both write.
    let share = dir.join("scan-share");
    std::fs::create_dir_all(&share)?;
    {
        use std::os::unix::fs::PermissionsExt as _;
        std::fs::set_permissions(&share, std::fs::Permissions::from_mode(0o777))?;
    }
    let pod = as_podman_share(&playable.join("\n---\n"), &share)?;
    let yaml = dir.join("pod.yaml");
    std::fs::write(&yaml, pod)?;
    let port = free_port()?;
    let pod = format!("{RELEASE}-holger-pod");
    let down = || {
        let _ = Command::new("podman")
            .args(["kube", "down", "--force"])
            .arg(&yaml)
            .stdout(Stdio::null())
            .stderr(Stdio::null())
            .status();
    };
    down();
    let r = (|| -> Result<()> {
        run(Command::new("podman")
            .args(["kube", "play", "--replace", "--publish"])
            .arg(format!("127.0.0.1:{port}:8443"))
            .arg(&yaml))?;
        let body = wait_for(port, "/readyz", 200, 120).context("the pod never went ready")?;
        println!("k8s test: /readyz {body:?} with the sidecar up");
        run(Command::new("podman")
            .args(["stop", "--time=2"])
            .arg(format!("{pod}-scan-worker")))?;
        let not = wait_for(port, "/readyz", 503, 30)
            .context("/readyz stayed ready with the sidecar stopped")?;
        if !not.contains("sandbox") {
            bail!("/readyz is 503 but does not name the sandbox: {not}");
        }
        println!("k8s test: /readyz 503 with the sidecar stopped: {not}");
        let (hz, _) = http_get(port, "/healthz").context("/healthz")?;
        if hz != 200 {
            bail!("/healthz answered {hz} while the sidecar was down: liveness is not readiness");
        }
        run(Command::new("podman")
            .arg("start")
            .arg(format!("{pod}-scan-worker")))?;
        wait_for(port, "/readyz", 200, 60).context("/readyz never came back with the sidecar")?;
        println!("k8s test: /readyz ready again with the sidecar back");
        Ok(())
    })();
    if r.is_err() {
        let _ = Command::new("podman")
            .args(["logs", "--tail=40"])
            .arg(format!("{pod}-holger"))
            .status();
        let _ = Command::new("podman")
            .args(["logs", "--tail=40"])
            .arg(format!("{pod}-scan-worker"))
            .status();
    }
    down();
    r?;
    serves_its_own_image(root, &ver, &dir)
}

/// The rendered pod with its shared `scan` emptyDir as a host directory (the
/// podman stand-in for Kubernetes' 0777 emptyDir).
fn as_podman_share(pod: &str, share: &Path) -> Result<String> {
    let from = "        - name: scan\n          emptyDir:\n";
    let i = pod
        .find(from)
        .context("the rendered pod has no `scan` emptyDir")?;
    let rest = &pod[i + from.len()..];
    let end = rest.find('\n').map(|n| n + 1).unwrap_or(rest.len());
    Ok(format!(
        "{}        - name: scan\n          hostPath:\n            path: {}\n            type: Directory\n{}",
        &pod[..i],
        share.display(),
        &rest[end..]
    ))
}

/// The `config.ron` block of values.yaml (read as text: the block scalar under
/// `config:` / `ron: |`, indented four spaces).
fn values_ron(values: &str) -> Result<String> {
    let mut lines = values.lines().skip_while(|l| l.trim_end() != "config:");
    lines.next();
    if lines.next().map(str::trim) != Some("ron: |") {
        bail!("values.yaml: `config:` is not followed by `ron: |`");
    }
    let body: Vec<&str> = lines
        .take_while(|l| l.is_empty() || l.starts_with("    "))
        .collect();
    Ok(body
        .iter()
        .map(|l| l.strip_prefix("    ").unwrap_or(l))
        .collect::<Vec<_>>()
        .join("\n"))
}

/// **Holger serves its own images** (owner decision 2026-10-26): a local Holger,
/// the image just built, with one writable OCI repository `nordisk` (holger.rs's
/// shape), takes the worker image by `podman push` and hands it back to
/// `podman pull`; the pulled image is the pushed one.
fn serves_its_own_image(root: &Path, ver: &str, dir: &Path) -> Result<()> {
    let bin = std::env::var_os("HOLGER_REGISTRY_BIN")
        .map(PathBuf::from)
        .unwrap_or_else(|| target_dir(root).join(REGISTRY_BIN));
    if !bin.is_file() {
        bail!(
            "{} is not there: `cargo xtask k8s image` builds it (holger with {REGISTRY_FEATURES})",
            bin.display()
        );
    }
    let port = free_port()?;
    let data = dir.join("registry-data");
    std::fs::create_dir_all(&data)?;
    let d = data.display();
    let ron = format!(
        r#"(
    repositories: [
        (ron_name: "nordisk", ron_repo_type: "oci", ron_upstreams: [], ron_in: None,
         ron_out: Some((ron_storage_endpoint: "storage", ron_exposed_endpoint: "default")),
         ron_data_dir: Some("{d}/nordisk")),
    ],
    exposed_endpoints: [ (ron_name: "default", ron_url: "127.0.0.1:{grpc}", ron_http_url: Some("127.0.0.1:{port}"), ron_tls: None) ],
    storage_endpoints: [ (ron_name: "storage", ron_storage_type: "znippy", ron_path: "{d}") ],
    audit: (dir: "{d}/audit", enabled: true),
)"#,
        grpc = free_port()?
    );
    let cfg = dir.join("registry.ron");
    std::fs::write(&cfg, ron)?;
    // The static binary as a local process: in holger.rs's shape, never holger.rs.
    let mut child = Command::new(&bin)
        .args(["start", "--config"])
        .arg(&cfg)
        .env("HOME", dir)
        .stdin(Stdio::null())
        .stdout(Stdio::null())
        .spawn()
        .with_context(|| bin.display().to_string())?;
    let r = (|| -> Result<()> {
        wait_for(port, "/healthz", 200, 60).context("the local Holger registry never answered")?;
        let local = format!("localhost:{port}/nordisk/holger-scan-worker:{ver}");
        run(Command::new("podman")
            .args(["push", "--tls-verify=false"])
            .arg(worker_ref(ver))
            .arg(format!("docker://{local}")))?;
        let pushed = output(
            Command::new("podman")
                .args(["image", "inspect", "--format={{.Id}}"])
                .arg(worker_ref(ver)),
        )?;
        podman_quiet(&["rmi", "--force", &local]);
        run(Command::new("podman")
            .args(["pull", "--tls-verify=false"])
            .arg(&local))?;
        let pulled = output(
            Command::new("podman")
                .args(["image", "inspect", "--format={{.Id}}"])
                .arg(&local),
        )?;
        if pushed.trim() != pulled.trim() {
            bail!(
                "the image Holger handed back ({}) is not the one pushed ({})",
                pulled.trim(),
                pushed.trim()
            );
        }
        podman_quiet(&["rmi", &local]);
        println!(
            "k8s test: a local Holger served {} to podman pull (image {})",
            worker_ref(ver),
            pulled.trim()
        );
        Ok(())
    })();
    let _ = child.kill();
    let _ = child.wait();
    r
}

/// The verb.
pub fn main(root: &Path, args: &[String]) -> Result<()> {
    let flag = |f: &str| {
        args.iter()
            .position(|a| a == f)
            .and_then(|i| args.get(i + 1))
            .map(PathBuf::from)
    };
    match args.first().map(String::as_str) {
        Some("image") => {
            let (server, worker) = match (flag("--server"), flag("--worker")) {
                (Some(s), Some(w)) => (s, w),
                _ => build(root)?,
            };
            image(root, &server, &worker)
        }
        Some("chart") => chart(root),
        Some("test") => test(root),
        Some("publish") => {
            let ver = version(root)?;
            println!("the release step (not run here; nothing is pushed by this verb):");
            for l in publish_plan(&ver) {
                println!("  {l}");
            }
            Ok(())
        }
        _ => bail!("usage: cargo xtask k8s <image [--server <bin> --worker <bin>] | chart | test | publish>"),
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    fn root() -> PathBuf {
        Path::new(env!("CARGO_MANIFEST_DIR"))
            .parent()
            .unwrap()
            .to_path_buf()
    }

    /// **The images come from holger.rs itself** (owner decision 2026-10-26):
    /// the chart, the plain manifests, the Dockerfile's words and the release's
    /// publish step all name holger.rs's own registry, at the server's version.
    #[test]
    fn the_chart_the_dockerfile_and_the_publish_step_name_holger_rs() {
        let root = root();
        let ver = version(&root).unwrap();
        let values = std::fs::read_to_string(root.join(CHART).join("values.yaml")).unwrap();
        assert!(
            values.contains("repository: holger.rs/nordisk/holger\n"),
            "values.yaml: the server image"
        );
        assert!(
            values.contains("repository: holger.rs/nordisk/holger-scan-worker\n"),
            "values.yaml: the sidecar image"
        );
        let chart = std::fs::read_to_string(root.join(CHART).join("Chart.yaml")).unwrap();
        assert!(
            chart.contains(&format!("appVersion: \"{ver}\"")),
            "Chart.yaml's appVersion is the server's {ver}"
        );
        let plain = std::fs::read_to_string(root.join("deploy/k8s/deployment.yaml")).unwrap();
        assert!(
            plain.contains(&format!("image: {}", server_ref(&ver))),
            "deploy/k8s names holger.rs at {ver}"
        );
        let docker = std::fs::read_to_string(root.join("distribution/Dockerfile")).unwrap();
        assert!(
            docker.contains(&server_ref("<ver>")) || docker.contains("holger.rs/nordisk/holger"),
            "the Dockerfile names holger.rs"
        );
        assert_eq!(
            publish_plan(&ver),
            vec![
                format!("podman push holger.rs/nordisk/holger:{ver} docker://holger.rs/nordisk/holger:{ver}"),
                format!("podman push holger.rs/nordisk/holger-scan-worker:{ver} docker://holger.rs/nordisk/holger-scan-worker:{ver}"),
            ]
        );
        for f in [
            "deploy/helm/holger/values.yaml",
            "deploy/helm/holger/values-dev.yaml",
            "deploy/helm/holger/values-prod.yaml",
            "deploy/helm/holger/Chart.yaml",
            "deploy/k8s/deployment.yaml",
            "distribution/Dockerfile",
        ] {
            let t = std::fs::read_to_string(root.join(f)).unwrap();
            assert!(
                !t.to_lowercase().contains("codeberg"),
                "{f} names the old forge"
            );
            assert!(
                !t.contains(":latest") && !t.contains("tag: \"latest\""),
                "{f} names a moving tag"
            );
            assert!(
                !t.lines().any(|l| l.trim_start().starts_with("email:")),
                "{f} carries an e-mail address"
            );
        }
    }

    /// The stale Dockerfile is fixed: it is the FROM scratch runtime of the
    /// static binary (built by `cargo xtask k8s image`), non-root, with no shell.
    #[test]
    fn the_dockerfile_is_from_scratch_non_root_and_names_the_real_binary() {
        let d = std::fs::read_to_string(root().join("distribution/Dockerfile")).unwrap();
        let code: Vec<&str> = d
            .lines()
            .filter(|l| !l.trim_start().starts_with('#') && !l.trim().is_empty())
            .collect();
        assert_eq!(
            code.iter()
                .filter(|l| l.starts_with("FROM "))
                .collect::<Vec<_>>(),
            vec![&"FROM scratch"],
            "{code:?}"
        );
        assert!(code.iter().any(|l| l.starts_with("USER 65532")), "{code:?}");
        assert!(
            code.iter().any(|l| l.contains("ENTRYPOINT [\"/holger\"]")),
            "the binary is `holger`, not the alias: {code:?}"
        );
        assert!(
            !d.contains("holger-server"),
            "the alias binary needs a feature nobody builds"
        );
    }

    /// The container flavour is the default without `systemd`, nothing more and
    /// nothing less.
    #[test]
    fn the_container_flavour_is_the_default_without_systemd() {
        let cli: toml::Value =
            toml::from_str(&std::fs::read_to_string(root().join("server/cli/Cargo.toml")).unwrap())
                .unwrap();
        let mut default: Vec<&str> = cli["features"]["default"]
            .as_array()
            .unwrap()
            .iter()
            .filter_map(|f| f.as_str())
            .collect();
        assert!(default.contains(&"systemd"), "{default:?}");
        default.retain(|f| *f != "systemd");
        assert_eq!(K8S_FEATURES.split(',').collect::<Vec<_>>(), default);
    }

    #[test]
    fn the_podman_stand_in_swaps_only_the_shared_emptydir() {
        let pod = "      volumes:\n        - name: tmp\n          emptyDir:\n            sizeLimit: 256Mi\n        - name: scan\n          emptyDir:\n            sizeLimit: 4Gi\n        - name: scratch\n          emptyDir:\n            sizeLimit: 1Gi\n";
        let out = as_podman_share(pod, Path::new("/t/share")).unwrap();
        assert!(out.contains("        - name: scan\n          hostPath:\n            path: /t/share\n            type: Directory\n        - name: scratch\n          emptyDir:"), "{out}");
        assert_eq!(
            out.matches("emptyDir").count(),
            2,
            "tmp and scratch stay: {out}"
        );
    }

    #[test]
    fn the_test_config_is_the_charts_without_tls() {
        let values = std::fs::read_to_string(root().join(CHART).join("values.yaml")).unwrap();
        let ron = values_ron(&values).unwrap();
        assert!(
            ron.contains("engine: remote") && ron.contains("ron_tls: Some(("),
            "{ron}"
        );
        let t = test_ron(&ron);
        assert!(
            t.contains("ron_tls: None,") && !t.contains("tls.crt"),
            "{t}"
        );
        assert!(t.contains("engine: remote"), "the rest stays: {t}");
    }

    #[test]
    fn a_static_binary_is_told_from_a_dynamic_one() {
        let me = std::fs::read(std::env::current_exe().unwrap()).unwrap();
        // The test binary is linked against glibc: it asks for a loader.
        assert!(!is_static_elf(&me), "a glibc test binary is dynamic");
        assert!(!is_static_elf(b"#!/bin/sh\n"), "a script is not an ELF");
    }

    /// The rendered pod, when helm is on this host (the `chart` verb requires it).
    #[test]
    fn the_rendered_pod_runs_the_sidecar_hardened() {
        if Command::new(helm())
            .arg("version")
            .stdout(Stdio::null())
            .stderr(Stdio::null())
            .status()
            .map(|s| !s.success())
            .unwrap_or(true)
        {
            eprintln!("helm is not on this host; `cargo xtask k8s chart` checks the rendered pod");
            return;
        }
        let root = root();
        let r = render(&root, &["tls.cert=c", "tls.key=k"]).unwrap();
        check_rendered(&r, &version(&root).unwrap()).unwrap();
    }

    #[test]
    fn a_pod_without_the_sidecar_or_with_a_privileged_container_is_refused() {
        let ver = "9.9.9";
        let good = format!(
            "kind: Deployment\nautomountServiceAccountToken: false\nreadOnlyRootFilesystem: true\nallowPrivilegeEscalation: false\nrunAsNonRoot: true\ntype: RuntimeDefault\npath: /readyz\nimage: \"{}\"\nimage: \"{}\"\n- name: scan-worker\n- serve\nmountPath: /run/holger-scan\nmountPath: /run/holger-scan\n---\nkind: ConfigMap\nengine: remote /run/holger-scan/worker.sock\n---\nkind: NetworkPolicy\npolicyTypes: [\"Ingress\", \"Egress\"]\n",
            server_ref(ver),
            worker_ref(ver)
        );
        check_rendered(&good, ver).unwrap();
        assert!(check_rendered(&good.replace("- name: scan-worker", ""), ver).is_err());
        assert!(check_rendered(
            &good.replace("runAsNonRoot: true", "runAsNonRoot: true\nprivileged: true"),
            ver
        )
        .is_err());
        assert!(check_rendered(&good.replace("engine: remote", "engine: podman"), ver).is_err());
    }
}