feat(LinuxTentacleE2E): Phase 12.M.L.A.5 — sudoers + service-user happy path E2E
Summary
THE prerequisite for the in-UI upgrade flow. The 11 upgrade-flow E2E tests in J.L.E.7-19 use a custom systemd unit running as the test user, but production runs the agent as the dedicated squid-tentacle system user. All upgrade-path sudo calls (systemd-run --scope, apt-get install, dpkg -i, mv to /var/lib/squid-tentacle/...) require the matching sudoers file installed correctly.
Why ship-blocking
Without this E2E pin, regressions in any of the following ship silently. Operator's first upgrade attempt is the catch site — by then the broken installer has deployed to the fleet:
- Sudoers heredoc breaks (e.g. unescaped backtick — caught by a real prod incident pinned by
InstallTentacleSudoersTestsunit; this test confirms the unit's pin actually flows through the.sh's heredoc + visudo chain end-to-end) -
visudo -cremoved/replaced with no validation → bad sudoers gets written → first upgrade prompts for password and hangs forever -
SERVICE_USERdetection regresses → sudoers block skipped even though useradd succeeded → upgrade prompts for password -
useraddflag drift (e.g.--no-create-homedropped) →/home/pollution; test catches viagetent passwdoutput check
Coverage layering
| Layer | Pin |
|---|---|
Unit (InstallTentacleSudoersTests) |
Validates GENERATED sudoers content |
| E2E (this PR) | Confirms WHOLE CHAIN: .sh's heredoc renders → temp file passes visudo -c → moves to /etc/sudoers.d/ → operator log line |
Test mechanism
Re-run install with CREATE_USER=yes (overrides the fixture default CREATE_USER=no), assert the production install path.
Assertions
| Assertion | What it pins |
|---|---|
exitCode == 0 |
useradd + visudo + sudoers install all succeeded |
getent passwd squid-tentacle returns user |
useradd ran (not idempotent skip) |
getent stdout does NOT contain /home/squid-tentacle
|
--no-create-home flag preserved |
/etc/sudoers.d/squid-tentacle-upgrade exists |
Sudoers file actually written |
| File mode is 0440 | visudo requires this mode to load the file; wrong mode = silent skip |
File contains squid-tentacle ALL=(root) NOPASSWD:
|
Rule rendered for the right user |
File contains /usr/bin/systemd-run --scope
|
The ONE hard privilege the upgrade flow depends on |
stdout logs Created system user: squid-tentacle
|
useradd actually fired |
stdout logs Installed upgrade sudoers rule
|
visudo accepted the content |
stdout does NOT log Warning: generated sudoers rule failed validation
|
No regression to silent-failure path |
Cleanup matrix
Existing matrix already handled /etc/sudoers.d/squid-tentacle-upgrade removal. J.M.L.A.5 adds userdel squid-tentacle to fixture's Dispose so the system user doesn't leak across test classes / CI runs.
Fidelity tier
.sh + real useradd + real visudo + real /etc/sudoers.d/. Heaviest install test because it actually mutates the system identity DB.
Test class is in LinuxTentacleHostStateCollection (serializes against upgrade + service-fixture tests on shared host state).
Expected runtime: ~5-10s.
Test plan
-
Linux E2E workflow runs (manual workflow_dispatchafter merge) -
A11h_SudoersAndServiceUserInstalled_VisudoValidatespasses within ~15s -
No regression on existing 24 Linux E2E tests -
userdelcleanup runs cleanly (visible in test logs as a normal Dispose call, no warnings)