refactor(#962): replace children_of(MANAGER_NAME) with top_level_agents()
Add topology::top_level_agents_in(topo) and top_level_agents() which find the topology root by structure (parent=None) rather than by name, then return its children. Lifecycle.rs role logic now uses this instead of children_of(MANAGER_NAME), removing the hardcoded manager-name reference from the bind-mount logic. Also adds two unit tests for top_level_agents_in.
This commit is contained in:
parent
d79df752d6
commit
828be8e2c8
2 changed files with 43 additions and 1 deletions
|
|
@ -1156,7 +1156,7 @@ fn set_nspawn_flags(
|
|||
agent_name,
|
||||
crate::topology::ROLE_CAN_MANAGE_TOP_LEVEL_AGENTS,
|
||||
) {
|
||||
let top_level = crate::topology::children_of(MANAGER_NAME);
|
||||
let top_level = crate::topology::top_level_agents();
|
||||
for tl in &top_level {
|
||||
if !direct_children.contains(tl) {
|
||||
bind_child_agent_dirs(tl, &mut binds);
|
||||
|
|
|
|||
|
|
@ -74,6 +74,34 @@ pub fn children_of_in(
|
|||
.collect()
|
||||
}
|
||||
|
||||
/// Return the agents that are direct children of the topology root
|
||||
/// (the unique agent whose own parent is `None`). These are the
|
||||
/// "top-level" agents — one layer below the auto-managed manager.
|
||||
///
|
||||
/// Callers should use this instead of `children_of(MANAGER_NAME)` so
|
||||
/// the manager's logical name is not hardcoded outside lifecycle.rs.
|
||||
/// If the topology has no root agent (e.g. empty file on cold boot),
|
||||
/// returns an empty vec.
|
||||
#[must_use]
|
||||
pub fn top_level_agents() -> Vec<String> {
|
||||
top_level_agents_in(&read())
|
||||
}
|
||||
|
||||
/// Pure form of [`top_level_agents`] for unit tests.
|
||||
#[must_use]
|
||||
pub fn top_level_agents_in(topo: &BTreeMap<String, Option<String>>) -> Vec<String> {
|
||||
// Find the unique root (parent = None). If none or multiple exist,
|
||||
// fall back to empty — the topology is malformed or uninitialised.
|
||||
let roots: Vec<&str> = topo
|
||||
.iter()
|
||||
.filter_map(|(name, parent)| if parent.is_none() { Some(name.as_str()) } else { None })
|
||||
.collect();
|
||||
match roots.as_slice() {
|
||||
[root] => children_of_in(topo, root),
|
||||
_ => vec![],
|
||||
}
|
||||
}
|
||||
|
||||
/// Resolve a magic recipient sentinel (currently just
|
||||
/// [`hive_sh4re::PARENT_RECIPIENT`]) to a real broker recipient at
|
||||
/// send time. Returns an owned `String` so callers can plug it
|
||||
|
|
@ -623,6 +651,20 @@ mod tests {
|
|||
assert!(children_of_in(&topo, "nobody").is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn top_level_agents_in_returns_children_of_root() {
|
||||
let topo = topo_three_level();
|
||||
// root's children = [alice]; bob+carol are under alice.
|
||||
let top = top_level_agents_in(&topo);
|
||||
assert_eq!(top, vec!["alice"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn top_level_agents_in_empty_topo_returns_empty() {
|
||||
let topo = BTreeMap::new();
|
||||
assert!(top_level_agents_in(&topo).is_empty());
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Roles tests (no disk I/O — use the pure `has_role_in` / in-memory maps)
|
||||
// -----------------------------------------------------------------------
|
||||
|
|
|
|||
Loading…
Reference in a new issue