swarm-controller: render, lock and commit internal/meta
A new update_meta node renders internal/meta's flake.nix with hive-meta-flake, the renderer hive-c0re uses: hyperhive pinned to its forge main, each custom agent a hive places pinned to its agent-configs main, all over https, and the swarm-wide values from SWARM_CONTROLLER_META_FLAKE (set by swarm-controller.nix from services.hyperhive.swarm.*). The swarm builder locks it, and the controller commits flake.nix and flake.lock in one commit and gives every hive's forge account read on the repo. A render equal to the committed flake.nix sends no lock and commits nothing. It runs at start, when hyperhive's main moves, before the deploy of a merged config PR and before the first deploy of a new agent; those deploys now wait for it. agent_web_port moves into hive-meta-flake so both callers compute the same port; hive-c0re re-exports it. On deploy: internal/meta appears on the forge and follows every merge. No hive builds from it yet. Refs #4857
This commit is contained in:
parent
f3c0a87c0f
commit
5950363a10
16 changed files with 970 additions and 41 deletions
|
|
@ -392,3 +392,32 @@ pub fn render_flake(
|
|||
out.push_str(" };\n };\n}\n");
|
||||
Ok(out)
|
||||
}
|
||||
|
||||
/// Web UI port range, shared by every agent including the manager.
|
||||
/// Deterministic from the agent's name (FNV-1a hash mod range size), so the
|
||||
/// dashboard can compute the same port without asking hive-c0re.
|
||||
const WEB_PORT_BASE: u16 = 8100;
|
||||
const WEB_PORT_RANGE: u16 = 900;
|
||||
|
||||
/// FNV-1a hash of a string — used by `agent_web_port`.
|
||||
fn fnv1a(s: &str) -> u32 {
|
||||
let mut hash: u32 = 2_166_136_261;
|
||||
for b in s.bytes() {
|
||||
hash ^= u32::from(b);
|
||||
hash = hash.wrapping_mul(16_777_619);
|
||||
}
|
||||
hash
|
||||
}
|
||||
|
||||
/// Per-agent web UI port — `WEB_PORT_BASE + FNV-1a(name) %
|
||||
/// WEB_PORT_RANGE` for every agent including the manager. The port
|
||||
/// allocation rule reads the same for every name; collisions are
|
||||
/// possible (birthday paradox at ~30 agents) and the operator
|
||||
/// resolves them by renaming an agent (different hash → different
|
||||
/// port). Stable across hosts, restarts, and dashboard renders —
|
||||
/// no state-file dance.
|
||||
#[must_use]
|
||||
pub fn agent_web_port(name: &str) -> u16 {
|
||||
// Modulo of a u32 by a u16's value is guaranteed < u16::MAX, so try_from never fails.
|
||||
WEB_PORT_BASE + u16::try_from(fnv1a(name) % u32::from(WEB_PORT_RANGE)).unwrap_or(0)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue