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

nordisk/edda

crates/nornir-build-thing/tests/params_provenance.rs

//! The `--param` mechanism end to end: a declared cell takes CLI values, the
//! landings are real (boot_params token, staged file ON DISK before
//! mastering), and the PROVENANCE rides the existing descriptor path — the
//! applied values change the content id and appear in the serialized cell,
//! so the build record answers "which ISO holds which hub key" without
//! booting anything.

use std::collections::BTreeMap;

use nornir_build_thing::image_build::{build_iso, PrebuiltIsoBuilder};
use nornir_build_thing::iso::IsoBuild;
use nornir_build_thing::params::parse_cli_params;
use nornir_build_thing::BuildVariantSet;

const CELL: &str = r#"
[build]
offers = []

[[build.installer]]
name = "holger-installer"
variant = "holger-appliance"
installer_variant = "holger-installer-pid1"
volume_id = "HOLGER_INSTALL"
boot_params = ["console=ttyS0", "korp.entry=holger"]

[[build.installer.params]]
name = "site"
label = "Site name"
kind = "text"
required = true
boot_param = "korp.site"

[[build.installer.params]]
name = "hub_conf"
label = "Hub declaration (ceremony hub.conf)"
kind = "text"
required = true
staged_file = "hub.conf"
"#;

/// The declared installer cell takes `--param` values: the boot token lands,
/// the staged file rides the rendered ISO, the record is ON the descriptor,
/// and the content id tells two sites apart.
#[test]
fn a_declared_cell_applies_cli_params_and_the_descriptor_carries_them() {
    let set = BuildVariantSet::from_toml_str(CELL).expect("cell parses");
    let installer = &set.installers[0];
    assert_eq!(installer.params.len(), 2, "the declaration owns the roster");

    let supplied = parse_cli_params(&[
        "site=stockholm-7".to_string(),
        "hub_conf=[Peer]\nPublicKey = HIgo9xNzJMWLKASShiTqIybxZ0U3wGLiUeJ1PKf8ykw=\nAllowedIPs = 10.77.0.0/16".to_string(),
    ])
    .unwrap();

    let mut site_a = installer.clone();
    site_a.apply_cli_params(&supplied).unwrap();
    assert!(
        site_a.boot_params.contains(&"korp.site=stockholm-7".to_string()),
        "the boot token landed: {:?}",
        site_a.boot_params
    );

    // The rendered ISO carries the staged hub.conf and the record.
    let iso = site_a.installer_iso();
    let staged = iso.staged_param_files();
    assert_eq!(staged.len(), 1);
    assert_eq!(staged[0].0, "hub.conf");
    assert!(staged[0].1.contains("PublicKey"), "{}", staged[0].1);

    // PROVENANCE — the serialized descriptor names the values, and the
    // content id differs from both the unparameterised cell and another site.
    let json = serde_json::to_value(&iso).unwrap().to_string();
    assert!(json.contains("stockholm-7") && json.contains("hub_conf"), "{json}");
    let mut site_b = installer.clone();
    let mut other = supplied.clone();
    other.insert("site".into(), "malmoe-2".into());
    site_b.apply_cli_params(&other).unwrap();
    assert_ne!(
        site_a.installer_iso().content_id(),
        site_b.installer_iso().content_id(),
        "two sites' ISOs must have two identities"
    );
    assert_ne!(
        site_a.installer_iso().content_id(),
        installer.installer_iso().content_id(),
        "a parameterised ISO is not the bare cell's ISO"
    );
}

/// The staged file is REAL before mastering: `build_iso` lands it on the
/// staging tree even when the (prebuilt) builder then reports its own honest
/// failure — the landing is a pre-step, recorded output on disk.
#[test]
fn build_iso_lands_staged_param_files_on_the_staging_tree() {
    let dir = tempfile::tempdir().unwrap();
    let mut iso = IsoBuild {
        name: "holger-installer".into(),
        staging: "iso-root".into(),
        volume_id: "HOLGER_INSTALL".into(),
        params: BuildVariantSet::from_toml_str(CELL).unwrap().installers[0].params.clone(),
        ..Default::default()
    };
    std::fs::create_dir_all(dir.path().join("iso-root")).unwrap();
    let supplied: BTreeMap<String, String> = [
        ("site".to_string(), "stockholm-7".to_string()),
        ("hub_conf".to_string(), "[Peer]\nPublicKey = x\n".to_string()),
    ]
    .into();
    iso.apply_cli_params(&supplied).unwrap();

    // The prebuilt builder will honestly fail (no mastered ISO on disk) — the
    // outcome records that; the staged landing must have happened regardless.
    let outcome = build_iso(&PrebuiltIsoBuilder::default(), &iso, "holger", dir.path()).unwrap();
    assert!(!outcome.success, "no mastered ISO exists — an honest failure");
    let landed = std::fs::read_to_string(dir.path().join("iso-root/hub.conf")).unwrap();
    assert_eq!(landed, "[Peer]\nPublicKey = x\n", "the hub.conf is REAL on the staging tree");
}

/// RED — the refusals, each named: a secret-shaped declaration, a secret-
/// shaped supply, a missing required value, and `--param` on the cargo verb.
#[test]
fn refusals_name_the_secret_the_missing_and_the_wrong_door() {
    let bad = r#"
[build]
offers = []

[[build.iso]]
name = "x"
staging = "iso-root"

[[build.iso.params]]
name = "hub_private_key"
kind = "text"
boot_param = "k"
"#;
    let set = BuildVariantSet::from_toml_str(bad).expect("parses; validation refuses");
    let err = set.isos[0].validate().unwrap_err().to_string();
    assert!(err.contains("NAMES A SECRET"), "{err}");

    let set = BuildVariantSet::from_toml_str(CELL).unwrap();
    let mut cell = set.installers[0].clone();
    let missing = cell
        .apply_cli_params(&BTreeMap::new())
        .unwrap_err()
        .to_string();
    assert!(missing.contains("Site name"), "the refusal names the LABEL: {missing}");

    // The cargo verb refuses --param rather than dropping it silently.
    let args = nornir_build_thing::suite_cli::parse(&["--param", "site=x", "--list"]).unwrap();
    assert_eq!(args.params, vec!["site=x"]);
    let dir = tempfile::tempdir().unwrap();
    std::fs::create_dir_all(dir.path().join(".nornir")).unwrap();
    std::fs::write(
        dir.path().join(".nornir/build-variants.toml"),
        "[build]\noffers = []\n\n[[build.variant]]\nname = \"a\"\npackage = \"a\"\nbin = \"a\"\n",
    )
    .unwrap();
    let err = nornir_build_thing::suite_cli::run(dir.path(), &args).unwrap_err().to_string();
    assert!(err.contains("iso/installer"), "{err}");
}