also looking at this
test(fleet): prove the database and hostname halves of a transfer on real machines
#184Refs #167. Closes the last two untested paths in the server-transfer feature — and one of them turned up a real fragility.
The database (7 cases)
This is the part of a move with the least margin for error: the tree and the units can be re-shipped by a deploy, the rows cannot. It's also what a unit test can say least about, because the claim that matters isn't "the right string was built" but "pg_dump wrote something psql could read back into a database that setup had just created".
So Postgres is stood up on two boxes and the actual builders the move composes are driven end to end — buildDatabaseSetupScript, buildBackupScript, buildBackupRestoreScript — with the rows read back out of the target.
One detail worth calling out: the seed runs as the app role, because that's who runs migrations in practice. My first version seeded as the superuser, and the ownership assertion failed — correctly, because in that setup the app couldn't read its own data on the source either. Fixing the seed turned that case into a real check: pg_dump records ownership, and a restore that lost it would leave the app facing a database full of tables it can't read, which is indistinguishable from an empty database until someone reads the logs.
Local trust auth isn't a concession to the test — it's what the pantry Postgres the drivers provision configures, and it's why pgAdminCommand omits -h for a co-located engine.
The hostname (6 cases) — and a fix
Three of the four records server:rename updates are data, properly unit-tested. The fourth is shell, and it's the one with somewhere to go wrong: hostnamectl isn't always present, /etc/hosts may or may not already carry a 127.0.1.1 line, and getting either wrong leaves a box whose own name doesn't resolve — which surfaces later as sudo hanging, not as a failed rename.
Running it found that sed -i cannot rewrite /etc/hosts when the file is a bind mount — every container — and would equally fail on a hard-linked file, because sed -i renames a temp file over the target:
sed: cannot rename /etc/sedFQn5eY: Device or resource busyRewritten to write the content back in place, which keeps the inode and works in both cases. That's a real fix the harness found, not a concession to it. Both paths are covered: hostnamectl present, and the /etc/hostname fallback.
The container gets CAP_SYS_ADMIN because setting a hostname needs it and containers drop it by default — a real box's root has it, so without it the test would be asserting a restriction the target environment doesn't have.
Results
Full suite 4282 pass, 0 fail. Lint and typecheck clean.
If you see integration tests skipping or a mid-run failure, that's the local Docker daemon dropping (it did so several times during this work), not the tests — they're skipped by design when Docker is unavailable.
Where that leaves the feature
Every path a server transfer touches is now exercised against real machines: tree and symlinks, systemd units, background work, the health gate, TLS material, the drained-source guard, the on-box database, and the hostname.
4 changed files on the files tab, with 0 review threads.