fix(container): root stat fallback makes volume ownership drift authoritative

The direct metadata read can be denied in the service's rootless context even
when the directory is already correctly owned, which kept the reconciler
calling sudo chown on the same Postgres volume every minute. A root
fallback gives the guard a reliable answer on deployed nodes while remaining
much cheaper than a recursive chown.

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
archipelago
2026-08-07 19:59:48 -04:00
co-authored by Claude
parent 3cd210f282
commit db8937f9e9
@@ -291,6 +291,14 @@ async fn chown_for_rootless_container(uid_gid: &str, path: &str) -> Result<()> {
if ownership_already_correct(path, &host_uid_gid) {
return Ok(());
}
// Some rootless-service contexts can read the directory entry but fail
// Rust's metadata lookup through an ACL/namespace boundary. Ask the
// host's root view before falling through to an expensive `chown -R`.
// This is still cheap compared with recursively walking Postgres on every
// reconcile and makes the drift gate authoritative on deployed nodes.
if ownership_already_correct_from_host(path, &host_uid_gid).await {
return Ok(());
}
if uid > 0 && uid < 100_000 {
let output = tokio::process::Command::new("podman")
@@ -353,6 +361,17 @@ fn ownership_already_correct(path: &str, host_uid_gid: &str) -> bool {
md.uid() == uid && md.gid() == gid
}
async fn ownership_already_correct_from_host(path: &str, host_uid_gid: &str) -> bool {
let Ok(out) = tokio::process::Command::new("sudo")
.args(["stat", "-c", "%u:%g", path])
.output()
.await
else {
return false;
};
out.status.success() && String::from_utf8_lossy(&out.stdout).trim() == host_uid_gid
}
/// `(container-id, mount-dest)` pairs whose in-container chown returned a hard,
/// permanent failure (e.g. "Operation not permitted" on a mount that can't be
/// re-owned from inside the userns). Remembered for the life of the process so