hive-priv: finish extracting exec's remaining match arms

This commit is contained in:
damocles 2026-08-29 14:00:22 +02:00
commit 592af562f9

View file

@ -350,19 +350,9 @@ async fn exec(
match req { match req {
PrivRequest::StartContainer { ref name } => start_container(name).await, PrivRequest::StartContainer { ref name } => start_container(name).await,
PrivRequest::StopContainer { ref name } => { PrivRequest::StopContainer { ref name } => stop_container(name).await,
validate_container_name(name)?;
stop_and_release(&container_system_name(name)).await
}
PrivRequest::KillContainer { ref name } => { PrivRequest::KillContainer { ref name } => kill_container(name).await,
validate_container_name(name)?;
// nixos-container has no kill verb. Use machinectl to send SIGKILL
// to all processes in the container — the right semantics for a
// forced shutdown after a graceful stop has already been attempted.
let machine = container_system_name(name);
machinectl_run(&["kill", &machine, "--signal=SIGKILL"]).await
}
PrivRequest::UpdateContainer { ref name, stream } => { PrivRequest::UpdateContainer { ref name, stream } => {
container_flake_action("update", name, stream, writer).await container_flake_action("update", name, stream, writer).await
@ -372,20 +362,14 @@ async fn exec(
container_flake_action("create", name, stream, writer).await container_flake_action("create", name, stream, writer).await
} }
PrivRequest::DestroyContainer { ref name } => { PrivRequest::DestroyContainer { ref name } => destroy_container(name).await,
validate_container_name(name)?;
container_run(&["destroy", &container_system_name(name)]).await
}
PrivRequest::ListContainers => container_run(&["list"]).await, PrivRequest::ListContainers => container_run(&["list"]).await,
PrivRequest::ReadContainerJournal { PrivRequest::ReadContainerJournal {
ref container, ref container,
ref query, ref query,
} => { } => exec_read_container_journal(container, query).await,
validate_container_system_name(container)?;
read_container_journal(container, query).await
}
PrivRequest::WriteNspawnFlags { PrivRequest::WriteNspawnFlags {
ref container, ref container,
@ -413,18 +397,12 @@ async fn exec(
PrivRequest::SetAgentPaused { PrivRequest::SetAgentPaused {
ref agent_name, ref agent_name,
paused, paused,
} => { } => exec_set_agent_paused(agent_name, paused),
validate_agent_name(agent_name)?;
set_agent_paused(agent_name, paused)
}
PrivRequest::WriteAgentForgeToken { PrivRequest::WriteAgentForgeToken {
ref agent_name, ref agent_name,
ref token, ref token,
} => { } => write_forge_token(agent_name, token),
validate_agent_name(agent_name)?;
write_agent_state_file(agent_name, "forge-token", &format!("{token}\n"))
}
PrivRequest::WriteAgentMatrixToken { PrivRequest::WriteAgentMatrixToken {
ref agent_name, ref agent_name,
@ -436,10 +414,7 @@ async fn exec(
PrivRequest::WriteAgentGithubToken { PrivRequest::WriteAgentGithubToken {
ref agent_name, ref agent_name,
ref token, ref token,
} => { } => write_github_token(agent_name, token),
validate_agent_name(agent_name)?;
write_agent_state_file(agent_name, "github-token", &format!("{token}\n"))
}
PrivRequest::WriteAgentExtraForgeAccount { PrivRequest::WriteAgentExtraForgeAccount {
ref agent_name, ref agent_name,
@ -451,12 +426,7 @@ async fn exec(
PrivRequest::DeleteAgentExtraForgeAccount { PrivRequest::DeleteAgentExtraForgeAccount {
ref agent_name, ref agent_name,
ref label, ref label,
} => { } => delete_extra_forge_account(agent_name, label),
validate_agent_name(agent_name)?;
validate_name_chars(label)?;
delete_agent_state_file(agent_name, &format!("forge-{label}-token"))?;
delete_agent_state_file(agent_name, &format!("forge-{label}.json"))
}
PrivRequest::RestartMatrixDaemon { ref agent_name } => { PrivRequest::RestartMatrixDaemon { ref agent_name } => {
restart_matrix_daemon(agent_name).await restart_matrix_daemon(agent_name).await
@ -469,52 +439,37 @@ async fn exec(
} }
PrivRequest::EnsureAgentSubvolume { ref agent_name } => { PrivRequest::EnsureAgentSubvolume { ref agent_name } => {
validate_agent_name(agent_name)?; exec_ensure_agent_subvolume(agent_name).await
ensure_agent_subvolume(agent_name).await
} }
PrivRequest::DeleteAgentSubvolume { ref agent_name } => { PrivRequest::DeleteAgentSubvolume { ref agent_name } => {
validate_agent_name(agent_name)?; exec_delete_agent_subvolume(agent_name).await
delete_agent_subvolume(agent_name).await
} }
PrivRequest::EnsureBtrfsQuota => ensure_btrfs_quota().await, PrivRequest::EnsureBtrfsQuota => ensure_btrfs_quota().await,
PrivRequest::ReadSubvolumeUsage { ref agent_name } => { PrivRequest::ReadSubvolumeUsage { ref agent_name } => {
validate_agent_name(agent_name)?; exec_read_subvolume_usage(agent_name).await
read_subvolume_usage(agent_name).await
} }
PrivRequest::SetSubvolumeQuota { PrivRequest::SetSubvolumeQuota {
ref agent_name, ref agent_name,
limit_bytes, limit_bytes,
} => { } => exec_set_subvolume_quota(agent_name, limit_bytes).await,
validate_agent_name(agent_name)?;
set_subvolume_quota(agent_name, limit_bytes).await
}
PrivRequest::UpgradeAgentSubvolume { ref agent_name } => { PrivRequest::UpgradeAgentSubvolume { ref agent_name } => {
validate_agent_name(agent_name)?; exec_upgrade_agent_subvolume(agent_name).await
upgrade_agent_subvolume(agent_name).await
} }
PrivRequest::SnapshotAgentSubvolume { PrivRequest::SnapshotAgentSubvolume {
ref agent_name, ref agent_name,
ref snapshot_name, ref snapshot_name,
} => { } => exec_snapshot_agent_subvolume(agent_name, snapshot_name).await,
validate_agent_name(agent_name)?;
validate_snapshot_name(snapshot_name)?;
snapshot_agent_subvolume(agent_name, snapshot_name).await
}
PrivRequest::DeleteAgentSnapshot { PrivRequest::DeleteAgentSnapshot {
ref agent_name, ref agent_name,
ref snapshot_name, ref snapshot_name,
} => { } => exec_delete_agent_snapshot(agent_name, snapshot_name).await,
validate_agent_name(agent_name)?;
validate_snapshot_name(snapshot_name)?;
delete_agent_snapshot(agent_name, snapshot_name).await
}
PrivRequest::SendAgentSnapshotToFile { PrivRequest::SendAgentSnapshotToFile {
ref agent_name, ref agent_name,
@ -522,13 +477,7 @@ async fn exec(
ref parent_snapshot_name, ref parent_snapshot_name,
ref dest_file_name, ref dest_file_name,
} => { } => {
validate_agent_name(agent_name)?; exec_send_agent_snapshot_to_file(
validate_snapshot_name(snapshot_name)?;
if let Some(parent) = parent_snapshot_name {
validate_snapshot_name(parent)?;
}
validate_credential_name(dest_file_name)?;
send_agent_snapshot_to_file(
agent_name, agent_name,
snapshot_name, snapshot_name,
parent_snapshot_name.as_deref(), parent_snapshot_name.as_deref(),
@ -542,17 +491,11 @@ async fn exec(
ref snapshot_name, ref snapshot_name,
ref parent_snapshot_name, ref parent_snapshot_name,
} => { } => {
validate_agent_name(agent_name)?; exec_send_agent_snapshot_to_fd(
validate_snapshot_name(snapshot_name)?;
if let Some(parent) = parent_snapshot_name {
validate_snapshot_name(parent)?;
}
let dest = fd.context("no descriptor to stream into")?;
send_agent_snapshot_to_fd(
agent_name, agent_name,
snapshot_name, snapshot_name,
parent_snapshot_name.as_deref(), parent_snapshot_name.as_deref(),
dest, fd,
) )
.await .await
} }
@ -638,6 +581,155 @@ fn write_extra_forge_account(
Ok(res) Ok(res)
} }
/// `StopContainer`.
async fn stop_container(name: &str) -> Result<(String, String)> {
validate_container_name(name)?;
stop_and_release(&container_system_name(name)).await
}
/// `KillContainer`: `nixos-container` has no kill verb, so this uses
/// `machinectl` to send `SIGKILL` to every process in the container — the
/// right semantics for a forced shutdown after a graceful stop has already
/// been attempted.
async fn kill_container(name: &str) -> Result<(String, String)> {
validate_container_name(name)?;
let machine = container_system_name(name);
machinectl_run(&["kill", &machine, "--signal=SIGKILL"]).await
}
/// `DestroyContainer`.
async fn destroy_container(name: &str) -> Result<(String, String)> {
validate_container_name(name)?;
container_run(&["destroy", &container_system_name(name)]).await
}
/// `ReadContainerJournal`.
async fn exec_read_container_journal(
container: &str,
query: &JournalQuery,
) -> Result<(String, String)> {
validate_container_system_name(container)?;
read_container_journal(container, query).await
}
/// `SetAgentPaused`.
fn exec_set_agent_paused(agent_name: &str, paused: bool) -> Result<(String, String)> {
validate_agent_name(agent_name)?;
set_agent_paused(agent_name, paused)
}
/// `WriteAgentForgeToken`.
fn write_forge_token(agent_name: &str, token: &str) -> Result<(String, String)> {
validate_agent_name(agent_name)?;
write_agent_state_file(agent_name, "forge-token", &format!("{token}\n"))
}
/// `WriteAgentGithubToken`.
fn write_github_token(agent_name: &str, token: &str) -> Result<(String, String)> {
validate_agent_name(agent_name)?;
write_agent_state_file(agent_name, "github-token", &format!("{token}\n"))
}
/// `DeleteAgentExtraForgeAccount`. Missing files are not an error
/// (idempotent revoke).
fn delete_extra_forge_account(agent_name: &str, label: &str) -> Result<(String, String)> {
validate_agent_name(agent_name)?;
validate_name_chars(label)?;
delete_agent_state_file(agent_name, &format!("forge-{label}-token"))?;
delete_agent_state_file(agent_name, &format!("forge-{label}.json"))
}
/// `EnsureAgentSubvolume`.
async fn exec_ensure_agent_subvolume(agent_name: &str) -> Result<(String, String)> {
validate_agent_name(agent_name)?;
ensure_agent_subvolume(agent_name).await
}
/// `DeleteAgentSubvolume`.
async fn exec_delete_agent_subvolume(agent_name: &str) -> Result<(String, String)> {
validate_agent_name(agent_name)?;
delete_agent_subvolume(agent_name).await
}
/// `ReadSubvolumeUsage`.
async fn exec_read_subvolume_usage(agent_name: &str) -> Result<(String, String)> {
validate_agent_name(agent_name)?;
read_subvolume_usage(agent_name).await
}
/// `SetSubvolumeQuota`.
async fn exec_set_subvolume_quota(
agent_name: &str,
limit_bytes: Option<u64>,
) -> Result<(String, String)> {
validate_agent_name(agent_name)?;
set_subvolume_quota(agent_name, limit_bytes).await
}
/// `UpgradeAgentSubvolume`.
async fn exec_upgrade_agent_subvolume(agent_name: &str) -> Result<(String, String)> {
validate_agent_name(agent_name)?;
upgrade_agent_subvolume(agent_name).await
}
/// `SnapshotAgentSubvolume`.
async fn exec_snapshot_agent_subvolume(
agent_name: &str,
snapshot_name: &str,
) -> Result<(String, String)> {
validate_agent_name(agent_name)?;
validate_snapshot_name(snapshot_name)?;
snapshot_agent_subvolume(agent_name, snapshot_name).await
}
/// `DeleteAgentSnapshot`.
async fn exec_delete_agent_snapshot(
agent_name: &str,
snapshot_name: &str,
) -> Result<(String, String)> {
validate_agent_name(agent_name)?;
validate_snapshot_name(snapshot_name)?;
delete_agent_snapshot(agent_name, snapshot_name).await
}
/// `SendAgentSnapshotToFile`.
async fn exec_send_agent_snapshot_to_file(
agent_name: &str,
snapshot_name: &str,
parent_snapshot_name: Option<&str>,
dest_file_name: &str,
) -> Result<(String, String)> {
validate_agent_name(agent_name)?;
validate_snapshot_name(snapshot_name)?;
if let Some(parent) = parent_snapshot_name {
validate_snapshot_name(parent)?;
}
validate_credential_name(dest_file_name)?;
send_agent_snapshot_to_file(
agent_name,
snapshot_name,
parent_snapshot_name,
dest_file_name,
)
.await
}
/// `SendAgentSnapshotToFd`.
async fn exec_send_agent_snapshot_to_fd(
agent_name: &str,
snapshot_name: &str,
parent_snapshot_name: Option<&str>,
fd: Option<OwnedFd>,
) -> Result<(String, String)> {
validate_agent_name(agent_name)?;
validate_snapshot_name(snapshot_name)?;
if let Some(parent) = parent_snapshot_name {
validate_snapshot_name(parent)?;
}
let dest = fd.context("no descriptor to stream into")?;
send_agent_snapshot_to_fd(agent_name, snapshot_name, parent_snapshot_name, dest).await
}
/// Shared body for `CreateContainer` / `UpdateContainer`: validate the /// Shared body for `CreateContainer` / `UpdateContainer`: validate the
/// name, build the toplevel ourselves, and run /// name, build the toplevel ourselves, and run
/// `nixos-container <verb> … --system-path <built>` (streaming line /// `nixos-container <verb> … --system-path <built>` (streaming line