build agents only from internal/meta; delete the hive's local meta flake
The hive no longer renders, locks or commits a meta flake. A rebuild's MetaSync node picks the internal/meta commit and records it with the hyperhive and config pins it holds; Prebuild, Swap and Create build from it, and a head that does not pin the agent's current config fails the build naming the agent. hive-priv's meta_rev is required. Removed: meta.rs sync/lock/render, the manual-rebuild relock, the boot sweep's hyperhive bump (MetaLock), the update-meta-inputs form and its panel, MetaWindow, the hive's hyperhive_rev setting. Kept: agent_set::refresh holds what sync_agents also did (topology.json, the gateway's agent-socket map and nginx include), called from spawn, destroy, rebuild and the migration. The boot reconcile and the stale-start upgrade compare the agent's marker with the hyperhive pin of internal/meta; the dashboard's deployed chip reads the config marker a successful build writes.
This commit is contained in:
parent
cea4827918
commit
4aa11b3a94
64 changed files with 1042 additions and 3793 deletions
|
|
@ -8,9 +8,7 @@
|
|||
//! [`PrivEvent::Line`]s when asked to.
|
||||
|
||||
use anyhow::{Context as _, Result, anyhow, bail};
|
||||
use hive_priv_sock::{
|
||||
META_DIR, PrivEvent, PrivStream, PrivStreamLine, meta_flake_url, valid_meta_rev,
|
||||
};
|
||||
use hive_priv_sock::{PrivEvent, PrivStream, PrivStreamLine, meta_flake_url, valid_meta_rev};
|
||||
use tokio::io::{AsyncWriteExt, BufReader};
|
||||
use tokio::net::unix::OwnedWriteHalf;
|
||||
use tokio::process::Command;
|
||||
|
|
@ -102,7 +100,7 @@ pub(crate) async fn destroy_container(name: &str) -> Result<(String, String)> {
|
|||
pub(crate) async fn container_flake_action(
|
||||
verb: &str,
|
||||
name: &str,
|
||||
meta_rev: Option<&str>,
|
||||
meta_rev: &str,
|
||||
stream: bool,
|
||||
writer: &mut OwnedWriteHalf,
|
||||
) -> Result<(String, String)> {
|
||||
|
|
@ -216,14 +214,10 @@ async fn log_and_forward(stdout: &str, stderr: &str, stream: bool, writer: &mut
|
|||
/// request.
|
||||
pub(crate) const FORGE_URL_ENV: &str = "HIVE_PRIV_FORGE_URL";
|
||||
|
||||
/// The flake agent toplevels are built from: the hive's own meta flake, or
|
||||
/// `internal/meta` at `meta_rev` when the request names one. The URL is
|
||||
/// `forge_base`, hive-priv's own; only the rev comes from the request, and it
|
||||
/// is checked here.
|
||||
fn meta_flake(meta_rev: Option<&str>, forge_base: Option<&str>) -> Result<String> {
|
||||
let Some(rev) = meta_rev else {
|
||||
return Ok(META_DIR.to_owned());
|
||||
};
|
||||
/// The flake agent toplevels are built from: `internal/meta` at `rev`. The URL
|
||||
/// is `forge_base`, hive-priv's own; only the rev comes from the request, and
|
||||
/// it is checked here.
|
||||
fn meta_flake(rev: &str, forge_base: Option<&str>) -> Result<String> {
|
||||
if !valid_meta_rev(rev) {
|
||||
bail!("meta_rev {rev:?} is not a 40-digit lowercase hex commit id");
|
||||
}
|
||||
|
|
@ -377,7 +371,7 @@ async fn run_bounded(
|
|||
/// `PrivEvent::Line` forwarding. Bounded by [`NIX_BUILD_TIMEOUT`].
|
||||
async fn nix_build_toplevel(
|
||||
name: &str,
|
||||
meta_rev: Option<&str>,
|
||||
meta_rev: &str,
|
||||
writer: Option<&mut OwnedWriteHalf>,
|
||||
) -> Result<String> {
|
||||
let flake = meta_flake(meta_rev, std::env::var(FORGE_URL_ENV).ok().as_deref())?;
|
||||
|
|
@ -726,30 +720,19 @@ mod tests {
|
|||
/// `hive-c0re`'s own `lifecycle::prebuild_toplevel` construction, since
|
||||
/// that step's whole point is warming the store for this later build.
|
||||
/// A drifted attr path defeats the cache-warming silently — no error,
|
||||
/// just a slower `update`.
|
||||
#[test]
|
||||
fn toplevel_attr_matches_prebuild_toplevels_construction() {
|
||||
assert_eq!(
|
||||
toplevel_attr(&meta_flake(None, None).unwrap(), "atlas"),
|
||||
"/var/lib/hyperhive/meta#nixosConfigurations.atlas.config.system.build.toplevel"
|
||||
);
|
||||
}
|
||||
|
||||
/// The flake is the hive's own unless the request names an `internal/meta`
|
||||
/// commit, and then its URL is the unit's, never the request's.
|
||||
/// just a slower `update`. The flake is `internal/meta` at the rev, and its
|
||||
/// URL is the unit's, never the request's.
|
||||
#[test]
|
||||
fn a_meta_rev_builds_from_internal_meta_at_the_units_forge() {
|
||||
let rev = "c".repeat(40);
|
||||
let forge = Some("http://forge.t.local");
|
||||
assert_eq!(
|
||||
toplevel_attr(&meta_flake(Some(&rev), forge).unwrap(), "atlas"),
|
||||
toplevel_attr(&meta_flake(&rev, forge).unwrap(), "atlas"),
|
||||
format!(
|
||||
"git+http://forge.t.local/internal/meta.git?rev={rev}\
|
||||
#nixosConfigurations.atlas.config.system.build.toplevel"
|
||||
)
|
||||
);
|
||||
// No rev: the forge is not consulted at all.
|
||||
assert_eq!(meta_flake(None, forge).unwrap(), hive_priv_sock::META_DIR);
|
||||
}
|
||||
|
||||
/// Nothing but a commit id gets into the ref, whatever the request says.
|
||||
|
|
@ -763,7 +746,7 @@ mod tests {
|
|||
&format!("{}#evil", "a".repeat(34)),
|
||||
&format!("{}&ref=x", "a".repeat(34)),
|
||||
] {
|
||||
let err = meta_flake(Some(bad), forge).unwrap_err();
|
||||
let err = meta_flake(bad, forge).unwrap_err();
|
||||
assert!(
|
||||
format!("{err:#}").contains("not a 40-digit"),
|
||||
"{bad}: {err:#}"
|
||||
|
|
@ -775,7 +758,7 @@ mod tests {
|
|||
fn a_meta_rev_without_a_forge_in_the_unit_is_refused() {
|
||||
let rev = "c".repeat(40);
|
||||
for forge in [None, Some("")] {
|
||||
let err = meta_flake(Some(&rev), forge).unwrap_err();
|
||||
let err = meta_flake(&rev, forge).unwrap_err();
|
||||
assert!(format!("{err:#}").contains(FORGE_URL_ENV), "{err:#}");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -353,19 +353,13 @@ async fn exec(
|
|||
ref name,
|
||||
stream,
|
||||
ref meta_rev,
|
||||
} => {
|
||||
container::container_flake_action("update", name, meta_rev.as_deref(), stream, writer)
|
||||
.await
|
||||
}
|
||||
} => container::container_flake_action("update", name, meta_rev, stream, writer).await,
|
||||
|
||||
PrivRequest::CreateContainer {
|
||||
ref name,
|
||||
stream,
|
||||
ref meta_rev,
|
||||
} => {
|
||||
container::container_flake_action("create", name, meta_rev.as_deref(), stream, writer)
|
||||
.await
|
||||
}
|
||||
} => container::container_flake_action("create", name, meta_rev, stream, writer).await,
|
||||
|
||||
PrivRequest::DestroyContainer { ref name } => container::destroy_container(name).await,
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue