refactor(#2302): type socket wire fields as ident, validated by serde on deserialize
This commit is contained in:
parent
bf644cc126
commit
84b750fba5
33 changed files with 333 additions and 263 deletions
|
|
@ -17,6 +17,7 @@ clap_complete.workspace = true
|
|||
clap-markdown = "0.1"
|
||||
hive-host-sock.workspace = true
|
||||
hive-sh4re.workspace = true
|
||||
hive-types.workspace = true
|
||||
indicatif.workspace = true
|
||||
serde_json.workspace = true
|
||||
tokio.workspace = true
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ async fn agents_restart(socket: &Path, name: &str, no_wait: bool) -> Result<()>
|
|||
let resp = crate::client::request(
|
||||
socket,
|
||||
hive_host_sock::HostRequest::Restart {
|
||||
name: name.to_owned(),
|
||||
name: crate::util::parse_ident(name)?,
|
||||
},
|
||||
)
|
||||
.await
|
||||
|
|
@ -135,18 +135,23 @@ pub(crate) async fn run_agents(socket: &Path, cmd: AgentsCmd) -> Result<()> {
|
|||
AgentsCmd::Restart { name, no_wait } => agents_restart(socket, &name, no_wait).await,
|
||||
AgentsCmd::RestartAll { no_wait } => agents_restart_all(socket, no_wait).await,
|
||||
AgentsCmd::Spawn { name } => {
|
||||
let name = crate::util::parse_ident(&name)?;
|
||||
render(crate::client::request(socket, HostRequest::Spawn { name }).await?)
|
||||
}
|
||||
AgentsCmd::RequestSpawn { name } => {
|
||||
let name = crate::util::parse_ident(&name)?;
|
||||
render(crate::client::request(socket, HostRequest::RequestSpawn { name }).await?)
|
||||
}
|
||||
AgentsCmd::Kill { name } => {
|
||||
let name = crate::util::parse_ident(&name)?;
|
||||
render(crate::client::request(socket, HostRequest::Kill { name }).await?)
|
||||
}
|
||||
AgentsCmd::Destroy { name, purge } => {
|
||||
let name = crate::util::parse_ident(&name)?;
|
||||
render(crate::client::request(socket, HostRequest::Destroy { name, purge }).await?)
|
||||
}
|
||||
AgentsCmd::Rebuild { name } => {
|
||||
let name = crate::util::parse_ident(&name)?;
|
||||
render(crate::client::request(socket, HostRequest::Rebuild { name }).await?)
|
||||
}
|
||||
AgentsCmd::SetParent {
|
||||
|
|
@ -154,7 +159,12 @@ pub(crate) async fn run_agents(socket: &Path, cmd: AgentsCmd) -> Result<()> {
|
|||
parent,
|
||||
root,
|
||||
} => {
|
||||
let new_parent = if root { None } else { parent };
|
||||
let child = crate::util::parse_ident(&child)?;
|
||||
let new_parent = if root {
|
||||
None
|
||||
} else {
|
||||
parent.map(|p| crate::util::parse_ident(&p)).transpose()?
|
||||
};
|
||||
render(
|
||||
crate::client::request(socket, HostRequest::SetParent { child, new_parent })
|
||||
.await?,
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ pub(crate) async fn forge_create_user(
|
|||
daemon_request(
|
||||
socket,
|
||||
hive_host_sock::HostRequest::ForgeCreateUser {
|
||||
name: name.to_owned(),
|
||||
name: crate::util::parse_ident(name)?,
|
||||
password,
|
||||
},
|
||||
"forge",
|
||||
|
|
@ -45,7 +45,7 @@ pub(crate) async fn forge_reconcile_config(
|
|||
daemon_request(
|
||||
socket,
|
||||
HostRequest::ReconcileConfigStatus {
|
||||
agent: agent.to_owned(),
|
||||
agent: crate::util::parse_ident(agent)?,
|
||||
verbose,
|
||||
},
|
||||
"forge",
|
||||
|
|
@ -62,7 +62,7 @@ pub(crate) async fn forge_reconcile_config(
|
|||
daemon_request(
|
||||
socket,
|
||||
HostRequest::ReconcileConfigApply {
|
||||
agent: agent.to_owned(),
|
||||
agent: crate::util::parse_ident(agent)?,
|
||||
direction,
|
||||
},
|
||||
"forge",
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ pub(crate) async fn github_set_token(
|
|||
daemon_request(
|
||||
socket,
|
||||
hive_host_sock::HostRequest::SetAgentGithubToken {
|
||||
agent: agent.to_owned(),
|
||||
agent: crate::util::parse_ident(agent)?,
|
||||
token,
|
||||
},
|
||||
"github",
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ async fn matrix_create_user(
|
|||
matrix_request(
|
||||
socket,
|
||||
hive_host_sock::HostRequest::MatrixCreateUser {
|
||||
name: name.to_owned(),
|
||||
name: crate::util::parse_ident(name)?,
|
||||
password,
|
||||
},
|
||||
)
|
||||
|
|
@ -74,7 +74,7 @@ async fn matrix_promote_user(socket: &Path, name: &str) -> Result<()> {
|
|||
matrix_request(
|
||||
socket,
|
||||
hive_host_sock::HostRequest::MatrixPromoteUser {
|
||||
name: name.to_owned(),
|
||||
name: crate::util::parse_ident(name)?,
|
||||
},
|
||||
)
|
||||
.await
|
||||
|
|
@ -95,7 +95,7 @@ async fn matrix_reset_password(socket: &Path, name: &str) -> Result<()> {
|
|||
matrix_request(
|
||||
socket,
|
||||
hive_host_sock::HostRequest::MatrixResetPassword {
|
||||
name: name.to_owned(),
|
||||
name: crate::util::parse_ident(name)?,
|
||||
},
|
||||
)
|
||||
.await
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ pub(crate) async fn quota_show(socket: &Path, name: Option<&str>) -> Result<()>
|
|||
let resp = crate::client::request(
|
||||
socket,
|
||||
hive_host_sock::HostRequest::QuotaShow {
|
||||
name: name.map(str::to_owned),
|
||||
name: name.map(crate::util::parse_ident).transpose()?,
|
||||
},
|
||||
)
|
||||
.await
|
||||
|
|
@ -60,7 +60,7 @@ pub(crate) async fn quota_limit(socket: &Path, name: &str, size: &str) -> Result
|
|||
daemon_request(
|
||||
socket,
|
||||
hive_host_sock::HostRequest::QuotaLimit {
|
||||
name: name.to_owned(),
|
||||
name: crate::util::parse_ident(name)?,
|
||||
limit,
|
||||
},
|
||||
"quota",
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ async fn subvol_upgrade(socket: &Path, name: &str, yes: bool) -> Result<()> {
|
|||
let upgrade = daemon_request(
|
||||
socket,
|
||||
hive_host_sock::HostRequest::UpgradeSubvolume {
|
||||
name: name.to_owned(),
|
||||
name: crate::util::parse_ident(name)?,
|
||||
},
|
||||
"upgrade",
|
||||
)
|
||||
|
|
@ -170,7 +170,7 @@ async fn subvol_snapshot_create(socket: &Path, name: &str, label: String) -> Res
|
|||
daemon_request(
|
||||
socket,
|
||||
hive_host_sock::HostRequest::SnapshotSubvolume {
|
||||
name: name.to_owned(),
|
||||
name: crate::util::parse_ident(name)?,
|
||||
label,
|
||||
},
|
||||
"snapshot",
|
||||
|
|
@ -184,7 +184,7 @@ async fn subvol_snapshot_delete(socket: &Path, name: &str, label: &str) -> Resul
|
|||
daemon_request(
|
||||
socket,
|
||||
hive_host_sock::HostRequest::DeleteSnapshot {
|
||||
name: name.to_owned(),
|
||||
name: crate::util::parse_ident(name)?,
|
||||
label: label.to_owned(),
|
||||
},
|
||||
"snapshot delete",
|
||||
|
|
@ -211,7 +211,7 @@ async fn subvol_snapshot_send(
|
|||
daemon_request(
|
||||
socket,
|
||||
hive_host_sock::HostRequest::SendSnapshot {
|
||||
name: name.to_owned(),
|
||||
name: crate::util::parse_ident(name)?,
|
||||
label: label.to_owned(),
|
||||
parent: parent.map(str::to_owned),
|
||||
dest: dest.to_owned(),
|
||||
|
|
|
|||
|
|
@ -6,6 +6,16 @@ use std::path::Path;
|
|||
|
||||
use anyhow::{Context as _, Result, bail};
|
||||
|
||||
/// Parse a CLI-supplied agent/account name into a validated
|
||||
/// [`hive_types::Ident`], mapping the parse error to an `anyhow` error that
|
||||
/// names the offending input. Used at hivectl's `HostRequest` construction
|
||||
/// sites so the wire `Ident` fields are built from validated names (the daemon
|
||||
/// re-validates on deserialize; parsing here gives the operator an immediate,
|
||||
/// local error instead of a round-trip rejection).
|
||||
pub(crate) fn parse_ident(name: &str) -> Result<hive_types::Ident> {
|
||||
hive_types::Ident::parse(name).map_err(|e| anyhow::anyhow!("invalid agent name {name:?}: {e}"))
|
||||
}
|
||||
|
||||
/// Send a provisioning request to the daemon and print its result lines.
|
||||
/// The daemon owns the provisioning logic; hivectl just relays the outcome,
|
||||
/// prefixing any error with `label` (e.g. `forge` / `github`).
|
||||
|
|
@ -115,7 +125,7 @@ pub(crate) async fn query_hive_urls(socket: &Path) -> Option<hive_host_sock::Hiv
|
|||
/// "needs root" error fixes that first-run footgun, where running a
|
||||
/// privileged verb without sudo reported as a missing agent.
|
||||
pub(crate) fn agent_exists(name: &str) -> Result<bool> {
|
||||
let Ok(name) = hive_host_sock::Ident::parse(name) else {
|
||||
let Ok(name) = hive_types::Ident::parse(name) else {
|
||||
bail!("invalid agent name {name:?}");
|
||||
};
|
||||
let root = hive_host_sock::agent_state_dir(&name);
|
||||
|
|
|
|||
Loading…
Reference in a new issue