fix(image): fold permissions into the OS build id so they OTA - #208
Open
nicksinas wants to merge 1 commit into
Open
fix(image): fold permissions into the OS build id so they OTA#208nicksinas wants to merge 1 commit into
nicksinas wants to merge 1 commit into
Conversation
A rootfs change that only edits `permissions:` (users/groups/passwords)
builds fine but never lands over `avocado deploy` — the device logs
`OS already at target version, skipping OS bundle download` and no-ops.
AVOCADO_OS_BUILD_ID is a pure function of the rootfs rpmdb (uuid5 over
the sorted NEVRA set), and `permissions:` rewrites /etc/{passwd,shadow,
group} without touching the package DB. So an identical package set
produced an identical build id regardless of the auth-file bytes, and
the deploy-side gate short-circuited the update.
Fold a hash of the assembled auth files into the build id alongside the
NEVRA hash, via a shared `render_auth_files_hash` helper used by both the
rootfs and initramfs build scripts. The hash is `LC_ALL=C`-sorted so it
is independent of the order the permissions section appends entries in,
and tolerates a missing gshadow. Any permissions change now moves the id
and therefore OTAs; an unchanged block hashes identically, so there is no
spurious update churn.
Note: because the build-id formula changes, every existing image re-ids
once on the first rebuild after this lands, triggering a single OS OTA
even when nothing else changed. Steady state is churn-free thereafter.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
ENG-2437
Problem
A rootfs change that only edits
permissions:(users/groups/passwords) builds fine locally but never lands on a device overavocado deploy. The device logs:…and no-ops.
Root cause
AVOCADO_OS_BUILD_IDis a pure function of the rootfs rpmdb —uuid5(namespace, sha256(sorted NEVRA of every installed RPM)). Thepermissions:section rewrites/etc/{passwd,shadow,group}in the image work dir but never touches the package DB, so an identical package set yields an identical build id regardless of the auth-file bytes. The deploy-side gate compares build ids and short-circuits both the download and the apply of the OS bundle, so the change silently never ships.(Same class of blind spot existed for the initramfs build id.)
Fix
Fold a hash of the assembled auth files into the build id alongside the NEVRA hash:
uuid5(ns, "$PKG_HASH:$AUTH_HASH")uuid5(ns, "$INITRAMFS_PKG_HASH:$INITRAMFS_AUTH_HASH")AUTH_HASHis produced by a new shared helper,render_auth_files_hash, that lives beside the existingrender_hook_block/resolve_install_hooks/render_users_groups_scripthelpers and is imported byinitramfs::image— so rootfs and initramfs derive their build id the exact same way, from one implementation.LC_ALL=C sortmakes the digest independent of the order the permissions section appends entries in (theusers:/groups:maps have no guaranteed iteration order), so it's fully deterministic.2>/dev/nulltolerates a missinggshadow(minimal images) — absent files contribute nothing rather than aborting.Why this doesn't cause spurious updates
The id is a content hash: an unchanged
permissions:block hashes identically → same id → no OTA. It moves if and only if the auth-file content actually changes. This is the minimal correct mechanism — the deploy gate reads nothing butAVOCADO_OS_BUILD_ID, so a permissions-only change has to move the id to land.One-time migration note
Because the build-id formula changes (
$PKG_HASH→$PKG_HASH:$AUTH_HASH), every existing image re-ids once on the first rebuild after this lands, triggering a single OS OTA even when nothing else changed. Steady state is churn-free thereafter.Tests
test_render_auth_files_hash_snippet— exact-output unit test on the pure helper + reuse under the initramfs var names.test_build_id_folds_auth_files(rootfs and initramfs) — structural + ordering assertions (auth hash computed after the permissions section, folded into the uuid5 input).cargo fmt/cargo clippyclean on the changed files.Scope / follow-up
This is the correctness fix only. A separate
--forceoverride foravocado deploy(an escape hatch for any future rootfs change that doesn't move the id) was intentionally split out into its own PR — this fix largely subsumes thepermissions:case, so--forceis a nice-to-have rather than a dependency.Fixes ENG-2437.