hivectl: say which of the three socket failures actually happened
`hivectl open forge` on a host where the daemon is fine and the socket is fine printed "could not reach the hive-c0re daemon for URLs — is hive-c0re running?". It was running. The operator was not in `hive-admin` in that shell, and the connect got EACCES. The message was a guess, not a diagnosis, because `query_hive_urls` returned `Option` and threw the cause away with `.ok()`. Three different failures — not in the group, no socket at all, nobody listening — all arrived as the same sentence, and only one of the three is fixed by looking at the daemon. Classify the connect error in `client::request`, which every daemon-assisted verb goes through, and keep the io error as the anyhow cause so the output reads fix-first. EACCES names `hive-admin`, `services.hyperhive.adminUsers`, and — the part that actually bites — the re-login, since secondary group membership is only applied at login, so a shell opened before the grant still cannot connect. ENOENT and ECONNREFUSED point at the units instead. Then stop discarding it: `query_hive_urls` returns `Result<Option<_>>`, `open` and `require_hive_domain` propagate, and `daemon_request` drops its own "connect to daemon socket" context, which only buried the actionable line under a vaguer one. `wg init`'s domain lookup stays best-effort by an explicit `.ok().flatten()` rather than by accident. Same footgun `agent_exists` was already fixed for: a permission error collapsed into a value that reads as a different, wrong story.
This commit is contained in:
parent
053bbb1bb7
commit
f108c72f25
4 changed files with 139 additions and 28 deletions
|
|
@ -5,7 +5,7 @@ use std::path::Path;
|
|||
|
||||
use anyhow::{Context as _, Result};
|
||||
|
||||
use crate::cli::{DEFAULT_HOST_SOCKET, OpenTarget};
|
||||
use crate::cli::OpenTarget;
|
||||
use crate::util::query_hive_urls;
|
||||
|
||||
/// `open <home|forge|matrix>` — resolve the surface URL from the daemon,
|
||||
|
|
@ -13,12 +13,12 @@ use crate::util::query_hive_urls;
|
|||
/// core (headless / SSH hosts where no browser opener exists); the open
|
||||
/// is convenience on top, so a missing/failed `xdg-open` is not an error.
|
||||
pub(crate) async fn open_url(socket: &Path, target: OpenTarget) -> Result<()> {
|
||||
let urls = query_hive_urls(socket).await.with_context(|| {
|
||||
format!(
|
||||
"could not reach the hive-c0re daemon for URLs — is hive-c0re running? \
|
||||
(the socket is at {DEFAULT_HOST_SOCKET})"
|
||||
)
|
||||
})?;
|
||||
// The connect error is already actionable (`client::request` classifies
|
||||
// it), so propagate it rather than restating a guess about the cause.
|
||||
let urls = query_hive_urls(socket)
|
||||
.await
|
||||
.context("could not read this hive's URLs from the daemon")?
|
||||
.context("the daemon reported no URLs — `services.hyperhive.domain` is unset")?;
|
||||
let (url, hint) = match target {
|
||||
OpenTarget::Home => (
|
||||
urls.home,
|
||||
|
|
|
|||
Loading…
Reference in a new issue