diff --git a/packaging/linux/rpm/template.go b/packaging/linux/rpm/template.go index 5447e7a53..478fd00d1 100644 --- a/packaging/linux/rpm/template.go +++ b/packaging/linux/rpm/template.go @@ -460,20 +460,11 @@ func (w *specWrapper) BuildSteps() fmt.Stringer { } func systemdPreUnScript(unitName string, cfg dalec.SystemdUnitConfig) string { - // if service isn't explicitly specified as enabled in the spec, - // then we don't need to do anything in the preun script if !cfg.Enable { return "" } - // should be equivalent to the systemd_preun scriptlet in the rpm spec, - // but without the use of a .preset file - return fmt.Sprintf(` -if [ $1 -eq 0 ]; then - # complete uninstallation - systemctl disable --now %s -fi -`, unitName) + return fmt.Sprintf("%%systemd_preun %s\n", unitName) } func (w *specWrapper) PreUn() fmt.Stringer { @@ -497,30 +488,35 @@ func (w *specWrapper) PreUn() fmt.Stringer { } func systemdPostScript(unitName string, cfg dalec.SystemdUnitConfig) string { - // if service isn't explicitly specified as enabled in the spec, - // then we don't need to do anything in the post script if !cfg.Enable { return "" } - // should be equivalent to the systemd_post scriptlet in the rpm spec, - // but without the use of a .preset file - s := ` -if [ $1 -eq 1 ]; then - # initial installation` + // Use systemctl enable directly instead of %systemd_post because + // %systemd_post calls "systemctl preset" which defers to system preset + // policy. All RPM distros have "disable *" as a catch-all in their preset + // files, so third-party services would never be enabled via preset. + // This behavior may change in the future to respect system presets instead. + // See https://github.com/project-dalec/dalec/issues/1017#issuecomment-4181051908 + // + // The "|| :" ensures a non-zero exit (e.g. systemd not running in a + // chroot/Kickstart/container) does not abort the scriptlet. + // Only enable on initial install ($1 == 1), not upgrades. + s := fmt.Sprintf(`if [ $1 -eq 1 ]; then + systemctl enable %s || : +fi +`, unitName) - // Enable/start service when package is installed if cfg.Start { - s = s + fmt.Sprintf(` - systemctl enable --now %s`, unitName) - } else { - s = s + fmt.Sprintf(` - systemctl enable %s`, unitName) - } - - s = s + ` + // Only start on initial install ($1 == 1), not upgrades, to avoid + // restarting a service the user intentionally stopped. + // Guard behind a check for a running systemd so this is safe + // in chroot/Kickstart/container environments. + s += fmt.Sprintf(`if [ $1 -eq 1 ] && [ -d /run/systemd/system ]; then + systemctl start %s || : fi -` +`, unitName) + } return s } diff --git a/packaging/linux/rpm/template_test.go b/packaging/linux/rpm/template_test.go index e0ef05455..b89d7a59a 100644 --- a/packaging/linux/rpm/template_test.go +++ b/packaging/linux/rpm/template_test.go @@ -290,15 +290,14 @@ func TestTemplate_Artifacts(t *testing.T) { assert.Equal(t, w.Post().String(), `%post - if [ $1 -eq 1 ]; then - # initial installation - systemctl enable test2.service + systemctl enable test2.service || : fi - if [ $1 -eq 1 ]; then - # initial installation - systemctl enable --now test3.service + systemctl enable test3.service || : +fi +if [ $1 -eq 1 ] && [ -d /run/systemd/system ]; then + systemctl start test3.service || : fi `) @@ -339,16 +338,8 @@ fi assert.Equal(t, w.PreUn().String(), `%preun - -if [ $1 -eq 0 ]; then - # complete uninstallation - systemctl disable --now test2.service -fi - -if [ $1 -eq 0 ]; then - # complete uninstallation - systemctl disable --now test3.service -fi +%systemd_preun test2.service +%systemd_preun test3.service `) })