layout — guide
Class:
guide· audience: a techie provisioning a target's directories. The what is inlayout-design.md.
Lay out a target
use skidbladnir::layout::Layout;
let layout = Layout::dated("/var/lib/nordisk", "/var/log/nordisk", "/opt/nordisk");
let (software, data, log) = layout.prepare_product("holger")?; // creates all three, idempotent
// software = /opt/nordisk/<YYYYMMDD>/holger data = /var/lib/nordisk/holger log = /var/log/nordisk/holger
prepare_product is safe to call again on an update — it never clobbers existing data/ or log/.
Activate a generation (atomic upgrade)
// after unpacking this generation's files under software/<version>/…
layout.activate()?; // atomic: current → <version>
assert_eq!(layout.active_version().as_deref(), Some(layout.version.as_str()));
The service's unit points through current, so activation is the instant the new generation goes live — no daemon churn, no path rewrite.
Upgrade to a new generation
let next = Layout::dated("/var/lib/nordisk", "/var/log/nordisk", "/opt/nordisk"); // new YYYYMMDD
let (sw, _data, _log) = next.prepare_product("holger")?; // data/log preserved from before
// … unpack the new files under sw …
next.activate()?; // current now points at the new version
Roll back
Rollback is just re-activating an older layout — the previous generation was never deleted:
old_layout.activate()?; // current → the previous <version>
Gotchas
activate()needs the temp symlink andcurrentto be on the same filesystem — the atomicrename(2)is what makes the swap tear-free.- The symlink target is the relative version name, so you can move the whole
software_dirwithout breakingcurrent. data/andlog/live outside the versionedsoftware/tree on purpose — that is why an update swaps binaries while state survives.