add a per-agent nix builds mode, host or none, carried like privateUsers
This commit is contained in:
parent
b9484e62a0
commit
5485151ba6
5 changed files with 618 additions and 58 deletions
|
|
@ -174,6 +174,7 @@ mod tests {
|
|||
built_unix: 1,
|
||||
cached,
|
||||
private_users: false,
|
||||
nix_builds: hive_types::NixBuilds::Host,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -246,6 +246,7 @@ mod tests {
|
|||
built_unix: 1,
|
||||
cached: true,
|
||||
private_users: false,
|
||||
nix_builds: hive_types::NixBuilds::Host,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -275,6 +275,7 @@ fn closure(cached: bool) -> AgentClosure {
|
|||
built_unix: 1,
|
||||
cached,
|
||||
private_users: false,
|
||||
nix_builds: hive_types::NixBuilds::Host,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use std::path::{Path, PathBuf};
|
|||
|
||||
use anyhow::{Context, Result};
|
||||
use hive_priv_sock::BindMount;
|
||||
use hive_types::Permission;
|
||||
use hive_types::{NixBuilds, Permission};
|
||||
|
||||
use crate::coordinator::{AgentPaths, HiveEnv};
|
||||
|
||||
|
|
@ -451,9 +451,11 @@ async fn set_nspawn_flags(
|
|||
});
|
||||
}
|
||||
|
||||
// Whether the agent's config sets `privateUsers`, as the swarm builder
|
||||
// recorded it. Read from the record, never from the agent's nix.
|
||||
let private_users = private_users_of(&crate::attic::closure::record(agent_name).await);
|
||||
// What the agent's config sets for `privateUsers` and `nixBuilds`, as the
|
||||
// swarm builder recorded it. Read from the record, never from the agent's nix.
|
||||
let record = crate::attic::closure::record(agent_name).await;
|
||||
let private_users = private_users_of(&record);
|
||||
let nix_builds = nix_builds_of(&record);
|
||||
|
||||
// Web-socket subdir: bind-mount `/run/hive-agent/<name>/` into the
|
||||
// container so the harness can bind `web.sock` there and the host-side
|
||||
|
|
@ -487,6 +489,7 @@ async fn set_nspawn_flags(
|
|||
&load_creds,
|
||||
super::hive_facts(hive),
|
||||
private_users,
|
||||
nix_builds,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
|
@ -529,6 +532,21 @@ fn private_users_of(
|
|||
}
|
||||
}
|
||||
|
||||
/// What hive-priv is told about the agent's nix builds: the record's mode, or
|
||||
/// `None` (leave the agent as the last write set it) when there is no record or
|
||||
/// it cannot be read, so a swarm outage never turns an agent's host builds on.
|
||||
fn nix_builds_of(
|
||||
record: &Result<Option<swarm_wire::agent_closures::AgentClosure>>,
|
||||
) -> Option<NixBuilds> {
|
||||
match record {
|
||||
Ok(record) => record.as_ref().map(|r| r.nix_builds),
|
||||
Err(e) => {
|
||||
tracing::warn!(error = %format!("{e:#}"), "closure record unreadable; the agent's nix builds are left as they are");
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The binds every agent container gets, before its own state, config and
|
||||
/// role-specific dirs.
|
||||
fn base_binds(runtime_dir: &Path, claude_dir: &Path, claude_mount: String) -> Vec<BindMount> {
|
||||
|
|
@ -559,8 +577,16 @@ mod tests {
|
|||
stage_limits,
|
||||
};
|
||||
use crate::coordinator::HiveEnv;
|
||||
use hive_types::NixBuilds;
|
||||
|
||||
fn record_with(private_users: bool) -> swarm_wire::agent_closures::AgentClosure {
|
||||
record_with_builds(private_users, NixBuilds::Host)
|
||||
}
|
||||
|
||||
fn record_with_builds(
|
||||
private_users: bool,
|
||||
nix_builds: NixBuilds,
|
||||
) -> swarm_wire::agent_closures::AgentClosure {
|
||||
swarm_wire::agent_closures::AgentClosure {
|
||||
meta_rev: "a".repeat(40),
|
||||
store_path: "/nix/store/x".to_owned(),
|
||||
|
|
@ -568,6 +594,7 @@ mod tests {
|
|||
built_unix: 1,
|
||||
cached: true,
|
||||
private_users,
|
||||
nix_builds,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -609,6 +636,38 @@ mod tests {
|
|||
assert_eq!(super::private_users_of(&Ok(Some(old))), Some(false));
|
||||
}
|
||||
|
||||
/// The record's mode is what hive-priv is told, both ways. No record and an
|
||||
/// unreadable one say nothing, so a swarm outage changes no agent; a record
|
||||
/// from before the field reads as host builds.
|
||||
#[test]
|
||||
fn the_records_nix_builds_is_what_the_start_path_passes() {
|
||||
for mode in [NixBuilds::Host, NixBuilds::Disabled] {
|
||||
assert_eq!(
|
||||
super::nix_builds_of(&Ok(Some(record_with_builds(false, mode)))),
|
||||
Some(mode)
|
||||
);
|
||||
}
|
||||
assert_eq!(super::nix_builds_of(&Ok(None)), None);
|
||||
assert_eq!(super::nix_builds_of(&Err(anyhow::anyhow!("down"))), None);
|
||||
let old = serde_json::json!({
|
||||
"meta_rev": "a", "store_path": "/nix/store/x",
|
||||
"system": "s", "built_unix": 1,
|
||||
});
|
||||
let old = serde_json::from_value(old).expect("decodes");
|
||||
assert_eq!(super::nix_builds_of(&Ok(Some(old))), Some(NixBuilds::Host));
|
||||
// A mode a newer swarm wrote, which this build does not know, decodes
|
||||
// and builds nothing.
|
||||
let newer = serde_json::json!({
|
||||
"meta_rev": "a", "store_path": "/nix/store/x",
|
||||
"system": "s", "built_unix": 1, "nix_builds": "container",
|
||||
});
|
||||
let newer = serde_json::from_value(newer).expect("decodes");
|
||||
assert_eq!(
|
||||
super::nix_builds_of(&Ok(Some(newer))),
|
||||
Some(NixBuilds::Disabled)
|
||||
);
|
||||
}
|
||||
|
||||
/// No agent container gets a cross-agent scratch dir; `/knowledge` is the
|
||||
/// control that the lookup finds a bind that is there.
|
||||
#[test]
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ use hive_priv_sock::{
|
|||
BindMount, CredentialMount, HiveFacts, InfraAction, InfraContainer, MEASURE_AGENT_DISK_TIMEOUT,
|
||||
NetworkIsolation, PRIV_SOCK, PrivEvent, PrivRequest, PrivResponse, PrivStream,
|
||||
};
|
||||
use hive_types::NixBuilds;
|
||||
use std::os::fd::{AsRawFd as _, OwnedFd, RawFd};
|
||||
|
||||
use tokio::io::{AsyncBufReadExt, AsyncWriteExt, BufReader, Interest};
|
||||
|
|
@ -320,6 +321,7 @@ pub async fn write_nspawn_flags(
|
|||
load_credentials: &[CredentialMount],
|
||||
hive_facts: HiveFacts,
|
||||
private_users: Option<bool>,
|
||||
nix_builds: Option<NixBuilds>,
|
||||
) -> Result<()> {
|
||||
ok(call(&PrivRequest::WriteNspawnFlags {
|
||||
container: container.to_owned(),
|
||||
|
|
@ -328,6 +330,7 @@ pub async fn write_nspawn_flags(
|
|||
load_credentials: load_credentials.to_vec(),
|
||||
hive_facts: Box::new(hive_facts),
|
||||
private_users,
|
||||
nix_builds,
|
||||
})
|
||||
.await?)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue