20260924 - Repair node state before install and write .env atomically - #42
Conversation
Two kinds of node drift have failed retina-node installs and then failed their rollbacks the same way, leaving the radar stack stopped: a NUL-filled manifests/.env left by a power cut, and a stray container holding one of the project's fixed container_names. The docker-compose Update Module only finds either after it has stopped the running stack. ArtifactInstall_Enter_10_retina_preflight runs before the module, sets a corrupt .env aside and parks any non-project container on a project name. It repairs and never aborts, because an aborted install sends the module's rollback down its "rollback after a commit" branch, which moves the live current/ out of the way. Nothing is deleted and it always exits 0. The config-merger rewrote the live .env in place with shutil.copy and no fsync, seconds after every boot. It now replaces .env, tar1090.env and retina-tracker.yaml through write_file_atomic(): temp file, fsync, rename, fsync the directory. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Mender will not run a state script without the executable bit, so without this the preflight would be skipped silently on every node. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Josh Test Node result,
|
The docker-compose Update Module starts the new stack from new/manifests, which it copies out of the artifact and which has no .env, so tar1090 is interpolated with a 0,0 receiver location and adsb.lol off. The config-merger writes the real .env a moment too late, and nothing interpolates again until the stack next starts. On most releases the owl-os reboot that follows hides this; on a retina-node-only update it lasts until the next restart. Seen on Josh Test Node with v0.4.7.0-dev, and on Fairforest B, where the v0.17.0 reboot two minutes after the v0.4.6.0 install corrected it. ArtifactCommit_Leave_10_retina_env_reload runs `up -d --no-deps tar1090` in current/manifests once the install is committed. It touches no other service, is a no-op when tar1090 already matches (checked on Josh Test Node), and never fails the deployment. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
tar1090 reload (46e8f0a), Josh Test Node result,
|
Phase 1 of ClickUp OTA deployments miss part of the fleet on every release (123zgec4tmx). Draft until the Josh Test Node result from the
v0.4.7.0-devtest build is in the ticket.Why
Two kinds of node drift have failed retina-node installs and then failed their rollbacks the same way, leaving the radar stack stopped. The docker-compose Update Module only finds either after it has stopped the running stack.
manifests/.env(ret9573ecda, v0.4.5.0 and v0.4.6.0). The config-merger rewrote.envin place withshutil.copyand no fsync, seconds after every boot, and a power cut then left it zeroed. Compose refuses to load the project, including therun config-mergerthat would regenerate it, so the node cannot recover by itself.container_name(Josh Test Node, v0.4.6.0 twice): a hand-runblah2:specfoldheldblah2.What
scripts/mender-state-scripts/ArtifactInstall_Enter_10_retina_preflight, shipped in the artifact, runs before the module. It sets a corrupt.envaside and parks non-project containers on project names (restartno, stopped, renamed). It repairs and never aborts: an aborted install sends the module's rollback down its "rollback after a commit" branch, which moves the livecurrent/aside. Nothing is deleted, it always exits 0, and each repair is logged to stderr and/data/mender-docker-compose/preflight.log(capped at 200 lines).config-merger:write_file_atomic()(temp file, fsync, rename, fsync the directory) for both compose.envcopies,tar1090.envandretina-tracker.yaml.scripts/test/.Expected result once released
ret9573ecda installs at its next online window with a
set aside ... NUL bytesline in its deployment log. A node with a stray container installs with aparked containerline. Every clean node logs nothing from the preflight and installs exactly as before.Risks
Runs as root on every node before install. A false positive on
.envrenames a good file and tar1090 starts with default location settings until the config-merger rewrites it on the next start. Parking could stop a container someone wanted: it is stopped and renamed, not removed.Evidence so far
core.fileMode=falsecheckout and fixed in defca52..envand stray container: both repaired, project container untouched, second run silent, live stack unchanged.v0.4.7.0-dev(branch20260924-ota-preflight-dev, which adds only the self-referentialCONFIG_MERGER_Vpin and is not for main): the script inside a real Mender install, whether its stderr reaches the deployment log, and themanifests.tarpayload path.🤖 Generated with Claude Code