fix(meta): forward HIVE_FORGE_URL etc. into globalEnvironment
The forwarded host env vars (HIVE_FORGE_URL, HIVE_FORGE_PUBLIC_URL, HYPERHIVE_HIVE_DOMAIN, ...) were emitted only into the harness service's own unit environment. Under network isolation that left the bash-task runner, the matrix daemon, tea-login and interactive shells without HIVE_FORGE_URL, so `hive-forge` and friends fell back to the loopback default (localhost:3000) — unreachable from a private netns, where the in-cluster gateway URL (forge.<domain>) is the only path. Emit the forwarded set into systemd.globalEnvironment too, which every unit + shell in the container inherits, so all in-container surfaces see the same forge/matrix endpoints. The existing harness-service forward is kept (harmless redundancy). Shared netns is unaffected (the localhost default still works there). Adds a regression test asserting the forwarded vars land inside the globalEnvironment block, and the generated flake parses.
This commit is contained in:
parent
f7199f183c
commit
c27f915e47
1 changed files with 61 additions and 2 deletions
|
|
@ -686,12 +686,27 @@ where
|
|||
HIVE_LABEL = name;
|
||||
HYPERHIVE_STATE_DIR = "/agents/${name}/state";
|
||||
HYPERHIVE_HARNESS_DIR = "/agents/${name}/harness";
|
||||
};
|
||||
"#,
|
||||
);
|
||||
// Forwarded vars (HIVE_FORGE_URL etc.) also go into globalEnvironment,
|
||||
// not just the harness service env below, so EVERY service + shell in
|
||||
// the container inherits them — crucially the bash-task runner (where
|
||||
// `hive-forge` + `git` actually run), plus the matrix daemon, tea-login
|
||||
// and interactive shells. Scoped to the harness service alone they were
|
||||
// invisible to bash tasks: harmless in shared netns (the localhost
|
||||
// default works) but broken under isolation, where the in-cluster
|
||||
// `forge.<domain>` URL is the only reachable path.
|
||||
for (var, val) in forwarded_env_vars() {
|
||||
let escaped = val.replace('\\', "\\\\").replace('"', "\\\"");
|
||||
let _ = writeln!(out, " {var} = \"{escaped}\";");
|
||||
}
|
||||
out.push_str(
|
||||
r" };
|
||||
systemd.services.${service}.environment = parentEnv // toolGroupsEnv // capabilitiesEnv // {
|
||||
HIVE_PORT = toString port;
|
||||
HIVE_LABEL = name;
|
||||
HIVE_DASHBOARD_PORT = toString dashboardPort;
|
||||
HIVE_OPERATOR_PRONOUNS = operatorPronouns;"#,
|
||||
HIVE_OPERATOR_PRONOUNS = operatorPronouns;",
|
||||
);
|
||||
// Per-model context-window env vars declared in the host-level
|
||||
// `services.hive-c0re.contextWindowTokens` option. Use a sorted
|
||||
|
|
@ -1038,4 +1053,48 @@ mod tests {
|
|||
"alice shouldn't have any inputs follows:\n{out}"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn render_flake_forwards_env_into_global_environment() {
|
||||
// Regression for the isolation breakage where forwarded vars
|
||||
// (HIVE_FORGE_URL etc.) landed only on the harness service env,
|
||||
// so the bash-task runner / matrix daemon / shells defaulted to
|
||||
// localhost and couldn't reach the in-cluster gateway. They must
|
||||
// also appear in `systemd.globalEnvironment`, which every unit +
|
||||
// shell in the container inherits.
|
||||
//
|
||||
// SAFETY: single-threaded mutation of a process env var the other
|
||||
// tests don't assert the absence of; restored before returning.
|
||||
unsafe {
|
||||
std::env::set_var("HIVE_FORGE_URL", "http://forge.example.test");
|
||||
}
|
||||
let out = render_flake(
|
||||
"github:example/hyperhive",
|
||||
"path:/nix/store/aaaa-nixpkgs-source",
|
||||
"path:/nix/store/bbbb-nixpkgs-unstable-source",
|
||||
8000,
|
||||
"she/her",
|
||||
&std::collections::HashMap::new(),
|
||||
&[sample_spec("alice", false, 9001)],
|
||||
);
|
||||
unsafe {
|
||||
std::env::remove_var("HIVE_FORGE_URL");
|
||||
}
|
||||
// The var must be emitted inside the globalEnvironment block, i.e.
|
||||
// before the per-service harness env block that follows it.
|
||||
let global_at = out
|
||||
.find("systemd.globalEnvironment = {")
|
||||
.expect("globalEnvironment block must exist");
|
||||
let service_at = out
|
||||
.find("systemd.services.${service}.environment")
|
||||
.expect("harness service env block must exist");
|
||||
let forge_at = out
|
||||
.find("HIVE_FORGE_URL = \"http://forge.example.test\"")
|
||||
.expect("HIVE_FORGE_URL must be forwarded into the flake");
|
||||
assert!(
|
||||
forge_at > global_at && forge_at < service_at,
|
||||
"HIVE_FORGE_URL must land inside systemd.globalEnvironment, \
|
||||
not only the harness service env:\n{out}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue