You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Updated 2026-07-07 with a root-cause investigation. The original framing
("stopped but still enabled", "does not disable an already-enabled unit")
was inaccurate — the units are static. Corrected analysis below.
Summary
In manifests/set_schedule.pp the timer is declared via systemd::timer (set_schedule.pp:71-76):
systemd::timer { 'puppet_aide.timer':
active => ($method == 'systemd'), # false in root/etc (cron) modesenable => ($method == 'systemd'), # false ← intent: disable the timer
}
In cron modes the observed state on AlmaLinux 9/10 is:
ensure => stopped is enforced; enable => false is not.
Root cause
Neither unit has an [Install] section. The heredocs (set_schedule.pp:57-69) contain only [Timer]/OnCalendar= and [Service]/Type=oneshot — no [Install] WantedBy=. A systemd unit with no [Install] section is static and cannot be enabled or disabled.
A real disable is declared.systemd::timer → systemd::unit_file emits service { 'puppet_aide.timer': ensure => false, enable => false, provider => 'systemd' } (puppet-systemd manifests/unit_file.pp), so Puppet does run systemctl disable — but that is a no-op on a static unit.
The provider reports static as enabled.systemctl is-enabled exits 0 for a static unit, and the systemd service provider returns :true whenever the exit code is 0 (OpenVox/Puppet lib/puppet/provider/service/systemd.rb, enabled?: return :true if code == 0). So puppet resource service always shows enable: 'true', and enable => false can never converge.
Consequence: the enable parameter is effectively inert for these units in every mode, not just cron modes.
Impact (re-assessed)
The original "AIDE scheduled twice after a reboot" concern most likely does not occur: a static timer has no WantedBy=timers.target, so systemd does not pull it in at boot — it will not auto-start. The enable: 'true' is a provider reporting artifact for static units, not real boot-persistence.
There is, however, a latent bug in the opposite direction that is arguably more serious: in the default systemd scheduling mode, enable => true on a static timer is also a no-op (the provider already sees :true and takes no action; active => true is what starts it). A timer that is running now will not be re-activated on the next boot because it is not wired into timers.target — so AIDE's scheduled check may silently stop running after a reboot in the default mode. (Needs beaker verification with an actual reboot; the acceptance suite never reboots, so it does not currently catch this.)
Fix
Give the timer an [Install] section so it becomes a real, enable/disable-able unit:
systemd mode:enable => true creates the timers.target symlink → the timer genuinely persists across reboots.
cron modes:enable => false removes the symlink → is-enabled returns disabled (exit 1) → the provider reports :false.
The oneshot service should stay static (timer-triggered services are not enabled directly), so the service enable assertion should be dropped rather than restored — the meaningful signal lives on the timer.
Follow-up in the acceptance suite
Once the module fix lands, in spec/acceptance/suites/default/05_schedule_spec.rb:
Add a systemd-mode assertion that the timer is genuinely enabled (WantedBy symlink present), and consider a reboot-based beaker test to lock in boot-persistence.
Where it was found
The enable => 'false' assertions in 05_schedule_spec.rb were dead (expect { … } with no matcher chained) until revived during test hardening; they then failed on AlmaLinux 9/10. They were relaxed to the deterministic guarantee (ensure => 'stopped') in #172 to keep that PR test-only and green; this issue tracks the module-side fix.
Summary
In
manifests/set_schedule.ppthe timer is declared viasystemd::timer(set_schedule.pp:71-76):In cron modes the observed state on AlmaLinux 9/10 is:
ensure => stoppedis enforced;enable => falseis not.Root cause
[Install]section. The heredocs (set_schedule.pp:57-69) contain only[Timer]/OnCalendar=and[Service]/Type=oneshot— no[Install] WantedBy=. A systemd unit with no[Install]section is static and cannot be enabled or disabled.systemd::timer→systemd::unit_fileemitsservice { 'puppet_aide.timer': ensure => false, enable => false, provider => 'systemd' }(puppet-systemdmanifests/unit_file.pp), so Puppet does runsystemctl disable— but that is a no-op on a static unit.systemctl is-enabledexits0for astaticunit, and the systemd service provider returns:truewhenever the exit code is0(OpenVox/Puppetlib/puppet/provider/service/systemd.rb,enabled?:return :true if code == 0). Sopuppet resource servicealways showsenable: 'true', andenable => falsecan never converge.Consequence: the
enableparameter is effectively inert for these units in every mode, not just cron modes.Impact (re-assessed)
The original "AIDE scheduled twice after a reboot" concern most likely does not occur: a static timer has no
WantedBy=timers.target, so systemd does not pull it in at boot — it will not auto-start. Theenable: 'true'is a provider reporting artifact for static units, not real boot-persistence.There is, however, a latent bug in the opposite direction that is arguably more serious: in the default
systemdscheduling mode,enable => trueon a static timer is also a no-op (the provider already sees:trueand takes no action;active => trueis what starts it). A timer that is running now will not be re-activated on the next boot because it is not wired intotimers.target— so AIDE's scheduled check may silently stop running after a reboot in the default mode. (Needs beaker verification with an actual reboot; the acceptance suite never reboots, so it does not currently catch this.)Fix
Give the timer an
[Install]section so it becomes a real, enable/disable-able unit:Then:
enable => truecreates thetimers.targetsymlink → the timer genuinely persists across reboots.enable => falseremoves the symlink →is-enabledreturnsdisabled(exit 1) → the provider reports:false.The oneshot service should stay static (timer-triggered services are not enabled directly), so the service
enableassertion should be dropped rather than restored — the meaningful signal lives on the timer.Follow-up in the acceptance suite
Once the module fix lands, in
spec/acceptance/suites/default/05_schedule_spec.rb:enable => 'false'assertion in the root/etc contexts (relaxed in Harden and repair the acceptance suite #172).WantedBysymlink present), and consider a reboot-based beaker test to lock in boot-persistence.Where it was found
The
enable => 'false'assertions in05_schedule_spec.rbwere dead (expect { … }with no matcher chained) until revived during test hardening; they then failed on AlmaLinux 9/10. They were relaxed to the deterministic guarantee (ensure => 'stopped') in #172 to keep that PR test-only and green; this issue tracks the module-side fix.🤖 Generated with Claude Code