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

nordisk/nornir

src/code_room/driver.rs

//! Where the nightly driver is on THIS box, and whether it can run
//! (decision D6, wiring map I5).
//!
//! The driver is a separate nightly artifact — `cargo-mimir-dump` + its
//! sibling `mimir-driver` + the pinned toolchain with `rustc-dev` — that the
//! stable workspace never builds. A dev box has it installed; a server box
//! runs it from the pinned toolchain IMAGE (an ops-kit step). This module
//! finds the pair, hands the consumer a probed [`DriverReady`], and turns
//! everything else into the typed [`State::DriverNotAvailable`] with the
//! step that failed — before a single commit is touched.
//!
//! | setting | meaning |
//! |---|---|
//! | `NORNIR_MIMIR_DRIVER` | path of `cargo-mimir-dump` (its sibling `mimir-driver` is the wrapper) |
//! | `NORNIR_MIMIR_DRIVER_HOST` | wrapper command line every tool is started through — the toolchain image, e.g. `podman run --rm -v /home/nornir/.nornir:/home/nornir/.nornir nordisk-cargo-toolchain:pinned`; the driver path is then a path INSIDE the image |
//! | `NORNIR_MIMIR_TOOLCHAIN` | the nightly the driver was built against, when it is not the one this tree pins |
//! | `NORNIR_MIMIR_CONTAINER_IMAGE` (+ `…_DRIVER`, `…_BINDS`) | the CONTAINER road ([`super::container`]): every tool in that image through draupnir; tried first, the host road said and taken when it does not work |
//!
//! Without `NORNIR_MIMIR_DRIVER` the pair is looked for, in order, at
//! `<nornir home>/mimir-driver/`, beside the running binary, and on `PATH`.

use std::path::{Path, PathBuf};

use mimir_ingest::{DriverHost, DriverReady, DriverSpec, pinned_toolchain};

use super::{Refusal, State};

pub const ENV_DRIVER: &str = "NORNIR_MIMIR_DRIVER";
pub const ENV_DRIVER_HOST: &str = "NORNIR_MIMIR_DRIVER_HOST";
pub const ENV_TOOLCHAIN: &str = "NORNIR_MIMIR_TOOLCHAIN";

const TOOL: &str = "cargo-mimir-dump";

/// What the settings + the box resolve to.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Settings {
    pub driver: Option<PathBuf>,
    pub host: Option<String>,
    pub toolchain: Option<String>,
    /// Directories searched when `driver` is unset (in order).
    pub search: Vec<PathBuf>,
}

impl Settings {
    /// From the environment and this process's surroundings.
    pub fn from_env() -> Self {
        let non_empty = |k: &str| std::env::var(k).ok().map(|v| v.trim().to_string()).filter(|v| !v.is_empty());
        let mut search = vec![crate::config::nornir_home().join("mimir-driver")];
        if let Some(dir) = std::env::current_exe().ok().and_then(|p| p.parent().map(Path::to_path_buf)) {
            search.push(dir);
        }
        search.extend(std::env::var_os("PATH").map(|p| std::env::split_paths(&p).collect::<Vec<_>>()).unwrap_or_default());
        Self { driver: non_empty(ENV_DRIVER).map(PathBuf::from), host: non_empty(ENV_DRIVER_HOST), toolchain: non_empty(ENV_TOOLCHAIN), search }
    }

    /// Which driver to run and where. No process is started: that is the probe.
    pub fn locate(&self) -> Result<DriverSpec, Refusal> {
        let host = match &self.host {
            Some(line) => DriverHost::Wrapped(line.split_whitespace().map(str::to_string).collect()),
            None => DriverHost::Installed,
        };
        let toolchain = self.toolchain.clone().unwrap_or_else(|| pinned_toolchain().to_string());
        let cargo_mimir_dump = match (&self.driver, &host) {
            (Some(p), _) => p.clone(),
            // inside the image the tool is on PATH unless told otherwise
            (None, DriverHost::Wrapped(_) | DriverHost::Runner(_)) => PathBuf::from(TOOL),
            (None, DriverHost::Installed) => self.search.iter().map(|d| d.join(TOOL)).find(|p| p.is_file()).ok_or_else(|| {
                Refusal::new(
                    State::DriverNotAvailable,
                    format!(
                        "the Mímir driver is not installed: no `{TOOL}` in {} — set {ENV_DRIVER} to it, or \
                         {ENV_DRIVER_HOST} to run it from the pinned toolchain image (toolchain {toolchain})",
                        self.search.iter().take(2).map(|d| d.display().to_string()).collect::<Vec<_>>().join(", "),
                    ),
                )
            })?,
        };
        Ok(DriverSpec { cargo_mimir_dump, driver: None, toolchain, host })
    }

    /// Locate, then prove it runs (`DriverSpec::probe`).
    pub fn probe(&self) -> Result<DriverReady, Refusal> {
        // the CONTAINER road first when an image is named; when it does not
        // work, say so and read on the host — never silently
        #[cfg(feature = "mimir-container")]
        if let Some(road) = super::container::ContainerRoad::from_env() {
            let toolchain = self.toolchain.clone().unwrap_or_else(|| pinned_toolchain().to_string());
            let spec = DriverSpec {
                cargo_mimir_dump: road.cargo_mimir_dump(),
                driver: None,
                toolchain,
                host: DriverHost::Runner(mimir_ingest::RunnerHandle(std::sync::Arc::new(super::container::BoxRoad::new(road.clone())))),
            };
            match spec.probe() {
                Ok(ready) => {
                    eprintln!("nornir-consumer: Mímir driver on the CONTAINER road: {} · {} · {}", road.image, road.cargo_mimir_dump().display(), ready.rustc);
                    return Ok(ready);
                }
                Err(e) => eprintln!(
                    "nornir-consumer: Mímir driver: the CONTAINER road ({}, driver {}) does not work — {e}; reading on the HOST road",
                    road.image,
                    road.cargo_mimir_dump().display()
                ),
            }
        }
        let spec = self.locate()?;
        spec.probe().map_err(|e| {
            Refusal::new(
                State::DriverNotAvailable,
                format!("the Mímir driver cannot run here ({}; host {}): {e}", spec.cargo_mimir_dump.display(), spec.host.describe()),
            )
        })
    }
}

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

    fn settings(search: Vec<PathBuf>) -> Settings {
        Settings { driver: None, host: None, toolchain: None, search }
    }

    #[test]
    fn no_driver_anywhere_is_driver_not_available_naming_where_it_looked() {
        let dir = tempfile::tempdir().unwrap();
        let r = settings(vec![dir.path().to_path_buf()]).probe().unwrap_err();
        assert_eq!(r.state, State::DriverNotAvailable);
        assert!(r.note.contains("not installed") && r.note.contains(&dir.path().display().to_string()), "{r}");
        assert!(r.note.contains(ENV_DRIVER) && r.note.contains(pinned_toolchain()), "{r}");
    }

    #[test]
    fn the_first_search_dir_that_holds_the_tool_wins_and_the_pin_is_the_default_toolchain() {
        let (a, b) = (tempfile::tempdir().unwrap(), tempfile::tempdir().unwrap());
        std::fs::write(b.path().join(TOOL), b"").unwrap();
        let spec = settings(vec![a.path().to_path_buf(), b.path().to_path_buf()]).locate().unwrap();
        assert_eq!(spec.cargo_mimir_dump, b.path().join(TOOL));
        assert_eq!((spec.toolchain.as_str(), &spec.host), (pinned_toolchain(), &DriverHost::Installed));
        assert_eq!(spec.driver_path(), b.path().join("mimir-driver"));
    }

    #[test]
    fn a_host_line_wraps_the_tool_and_needs_no_local_binary() {
        let s = Settings {
            driver: None,
            host: Some("podman run --rm  -v /srv:/srv img:pinned".into()),
            toolchain: Some("nightly-2026-01-01".into()),
            search: vec![],
        };
        let spec = s.locate().unwrap();
        assert_eq!(spec.host, DriverHost::Wrapped(["podman", "run", "--rm", "-v", "/srv:/srv", "img:pinned"].map(String::from).to_vec()));
        assert_eq!((spec.cargo_mimir_dump, spec.toolchain.as_str()), (PathBuf::from(TOOL), "nightly-2026-01-01"));
    }

    /// A pair that is on disk but cannot run (here: empty files, and a nightly
    /// nobody has) is the same state with the probe's step in the sentence.
    #[test]
    fn a_driver_that_does_not_probe_is_driver_not_available_with_the_step() {
        let dir = tempfile::tempdir().unwrap();
        std::fs::write(dir.path().join(TOOL), b"").unwrap();
        std::fs::write(dir.path().join("mimir-driver"), b"").unwrap();
        let mut s = settings(vec![dir.path().to_path_buf()]);
        s.toolchain = Some("nightly-1999-01-01".into());
        let r = s.probe().unwrap_err();
        assert_eq!(r.state, State::DriverNotAvailable);
        assert!(r.note.contains("cannot run here") && r.note.contains("nightly-1999-01-01 is not installed"), "{r}");
    }
}