host.sock: give HostResponse a wire-schema version, warn on mismatch

This commit is contained in:
damocles 2026-09-07 12:46:58 +02:00 committed by mara
commit a32f37c3ba
2 changed files with 87 additions and 2 deletions

View file

@ -69,12 +69,53 @@ pub async fn request(socket: &Path, req: HostRequest) -> Result<HostResponse> {
bail!("server closed connection without responding");
}
let resp: HostResponse = serde_json::from_str(line.trim())?;
if let Some(hint) = version_mismatch_hint(resp.version) {
eprintln!("{hint}");
}
Ok(resp)
}
/// Message to print (stderr, non-fatal) when the daemon's `HostResponse`
/// wire version differs from what this `hivectl` build was compiled
/// against. `None` when they match. Split out from the print site so it's
/// unit-testable, same pattern as `connect_hint` above — a mismatch is not
/// a request failure (most fields still decode fine across a one-version
/// skew), just something the operator should know before trusting a
/// response that might be missing a field this build expects.
fn version_mismatch_hint(daemon_version: u32) -> Option<String> {
(daemon_version != hive_host_sock::HOST_SOCK_VERSION).then(|| {
format!(
"warning: hive-c0re host.sock wire version {daemon_version} does not match \
hivectl's {} upgrade hivectl or the daemon; some response fields may be \
missing or misread",
hive_host_sock::HOST_SOCK_VERSION
)
})
}
#[cfg(test)]
mod tests {
use super::{ErrorKind, Path, connect_hint};
use super::{ErrorKind, Path, connect_hint, version_mismatch_hint};
/// A daemon on the same version this `hivectl` was built against gets
/// no warning — the common case, and the only one that must stay silent.
#[test]
fn matching_version_has_no_hint() {
assert!(version_mismatch_hint(hive_host_sock::HOST_SOCK_VERSION).is_none());
}
/// A mismatch names both versions, so the operator knows which side
/// (hivectl or the daemon) is behind, not just that they disagree.
#[test]
fn mismatched_version_names_both_numbers() {
let other = hive_host_sock::HOST_SOCK_VERSION + 1;
let h = version_mismatch_hint(other).expect("versions differ");
assert!(h.contains(&other.to_string()), "{h}");
assert!(
h.contains(&hive_host_sock::HOST_SOCK_VERSION.to_string()),
"{h}"
);
}
fn hint(kind: ErrorKind) -> String {
connect_hint(kind, Path::new("/run/hyperhive/host.sock"))