Watch
0
0
Fork
You've already forked hyperhive
0

read privateUsers from the closure record at start, and move the data owner option under hive-controller

This commit is contained in:
atlas 2026-11-01 16:18:34 +01:00 • committed by mara
commit f5a609911c

View file

@ -335,17 +335,31 @@ pub enum PrivRequest {
/// Written to the container's `/etc/hyperhive-hive-facts` on every
/// call, so a fact the hive no longer has is removed, not kept.
#[serde(default)]
hive_facts: HiveFacts,
hive_facts: Box<HiveFacts>,
/// Whether the agent's evaluated config sets
/// `services.hyperhive.agent.user.privateUsers`, as the swarm builder
/// recorded it. `Some(true)` starts the container in its own user
/// namespace; `Some(false)` does not, and hive-priv refuses an agent
/// whose data it already moved. `None`, which is what a hive-c0re
/// without the field or without a readable record sends, keeps the
/// agent as it is: namespaced if hive-priv moved its data, else not.
#[serde(default)]
private_users: Option<bool>,
},
/// Create the agent's socket dir `/run/hive-agent/<name>` as `0751
/// root:root` if it is missing; an existing directory is left as it is.
/// It is a bind source, so it has to exist before every container start,
/// and `/run` is a tmpfs. The container's own activation hands it to the
/// agent user. Called from `lifecycle::set_nspawn_flags`.
/// agent user, or, for a namespaced agent, by this request. Called from
/// `lifecycle::set_nspawn_flags`.
EnsureAgentSocketDir {
/// Logical agent name (validated by `validate_agent_name`).
name: String,
/// As for `WriteNspawnFlags`: a namespaced agent's dir goes to the
/// data owner.
#[serde(default)]
private_users: Option<bool>,
},
/// Write `/run/systemd/system/container@<container>.service.d/hyperhive-limits.conf`
@ -701,6 +715,32 @@ pub enum PrivEvent {
mod tests {
use super::{InfraContainer, PrivRequest, valid_closure_path, valid_meta_rev};
/// A request from a hive-c0re that predates the field decodes with the
/// agent's namespace left to hive-priv, and the field round-trips.
#[test]
fn private_users_is_optional_on_the_wire() {
let old = serde_json::json!({"op": "ensure_agent_socket_dir", "name": "iris"});
let PrivRequest::EnsureAgentSocketDir {
private_users: None,
..
} = serde_json::from_value(old).expect("decodes")
else {
panic!("no field reads as None");
};
for want in [Some(true), Some(false)] {
let wire = serde_json::to_value(PrivRequest::EnsureAgentSocketDir {
name: "iris".to_owned(),
private_users: want,
})
.expect("encodes");
let PrivRequest::EnsureAgentSocketDir { private_users, .. } =
serde_json::from_value(wire).expect("decodes")
else {
panic!("variant");
};
assert_eq!(private_users, want);
}
}
#[test]
fn infra_control_names_no_c0re_or_swarm_service() {
// Neither the daemon nor the swarm's forge and matrix have a