From 4e3d0a1606693cbb839670d013ad4d23ef4b00ab Mon Sep 17 00:00:00 2001 From: Steve Traylen Date: Wed, 28 Feb 2024 10:06:21 +0100 Subject: [PATCH] Support reload `systemd --user` for non-zero UIDs Support calling the `systemd --user` for a particular uid. A `uid` must be used rather than the probably more convenient username since the `$XDG_RUNTIME_DIR` for the user must be known. This change assumes that XDG_RUNTIME_DIR is `/run/user/` for all uids. Example run: ```puppet notify{'junk': notify => Systemd::Daemon_reload['foobar'], } systemd::daemon_reload{'foobar': uid => 1000, } ``` results in ``` Notice: Compiled catalog for fedora. in environment production in 0.05 seconds Notice: junk Notice: /Stage[main]/Main/Notify[junk]/message: defined 'message' as 'junk' Notice: /Stage[main]/Main/Systemd::Daemon_reload[foobar]/Exec[systemd-foobar-systemctl-user-1000-daemon-reload]: Triggered 'refresh' from 1 event Notice: Applied catalog in 0.17 seconds ``` and a journal (debug on) of ``` Feb 28 11:44:34 fedora systemd[1]: user@1000.service: Got notification message from PID 1877 (RELOADING=1, MONOTONIC_USEC=5874581103) Feb 28 11:44:34 fedora systemd[1]: user@1000.service: Changed running -> reload-notify Feb 28 11:44:34 fedora systemd[1]: user@1000.service: Installed new job user@1000.service/nop as 6151 ... --- REFERENCE.md | 34 +++++++++++++++++++++++++++- manifests/daemon_reload.pp | 42 ++++++++++++++++++++++++++++++++--- spec/defines/daemon_reload.rb | 28 +++++++++++++++++++++-- 3 files changed, 98 insertions(+), 6 deletions(-) diff --git a/REFERENCE.md b/REFERENCE.md index d38a01ba..ed5ecd0b 100644 --- a/REFERENCE.md +++ b/REFERENCE.md @@ -622,12 +622,35 @@ Default value: `['create']` Run systemctl daemon-reload +#### Examples + +##### Force reload the system systemd + +```puppet +notify{ 'fake event to notify from': + notify => Systemd::Daemon_reload['special'] +} +systemd::daemon_reload{ 'special': } +``` + +##### Force reload a systemd --user + +```puppet +notify{ 'fake event to notify from': + notify => Systemd::Daemon_reload['user'] +} +systemd::daemon_reload{ 'user': + uid => 1234, +} +``` + #### Parameters The following parameters are available in the `systemd::daemon_reload` defined type: * [`name`](#-systemd--daemon_reload--name) * [`enable`](#-systemd--daemon_reload--enable) +* [`uid`](#-systemd--daemon_reload--uid) ##### `name` @@ -638,11 +661,20 @@ A globally unique name for the resource Data type: `Boolean` Enable the reload exec - * Added in case users want to disable the reload globally using a resource collector Default value: `true` +##### `uid` + +Data type: `Optional[Integer[1]]` + +Specify uid of `systemd --user` to reload. When `uid` is left `undef` the system +systemd instance will be reloaded. It is assumed that the `XDG_RUNTIME_DIR` for +the user is `/run/user/`. + +Default value: `undef` + ### `systemd::dropin_file` Creates a drop-in file for a systemd unit diff --git a/manifests/daemon_reload.pp b/manifests/daemon_reload.pp index b7c3bac2..12522c22 100644 --- a/manifests/daemon_reload.pp +++ b/manifests/daemon_reload.pp @@ -7,15 +7,51 @@ # # @param enable # Enable the reload exec -# # * Added in case users want to disable the reload globally using a resource collector # +# @param uid +# Specify uid of `systemd --user` to reload. When `uid` is left `undef` the system +# systemd instance will be reloaded. It is assumed that the `XDG_RUNTIME_DIR` for +# the user is `/run/user/`. +# +# @example Force reload the system systemd +# notify{ 'fake event to notify from': +# notify => Systemd::Daemon_reload['special'] +# } +# systemd::daemon_reload{ 'special': } +# +# @example Force reload a systemd --user +# notify{ 'fake event to notify from': +# notify => Systemd::Daemon_reload['user'] +# } +# systemd::daemon_reload{ 'user': +# uid => 1234, +# } +# define systemd::daemon_reload ( Boolean $enable = true, + Optional[Integer[1]] $uid = undef, ) { if $enable { - exec { "${module_name}-${name}-systemctl-daemon-reload": - command => 'systemctl daemon-reload', + # For a `systemd --user` instance XDG_RUNTIME_DIR must be set so dbus + # can be found. + + if $uid { + $_title = "${module_name}-${name}-systemctl-user-${uid}-daemon-reload" + $_user = String($uid) # exec seems unhappy with integers. + $_env = "XDG_RUNTIME_DIR=/run/user/${uid}" + $_command = ['systemctl', '--user', 'daemon-reload'] + } else { + $_title = "${module_name}-${name}-systemctl-daemon-reload" + $_user = undef + $_env = undef + $_command = ['systemctl', 'daemon-reload'] + } + + exec { $_title: + command => $_command, + environment => $_env, + user => $_user, refreshonly => true, path => $facts['path'], } diff --git a/spec/defines/daemon_reload.rb b/spec/defines/daemon_reload.rb index e2dd5bbb..3366dabe 100644 --- a/spec/defines/daemon_reload.rb +++ b/spec/defines/daemon_reload.rb @@ -14,8 +14,10 @@ context 'with defaults' do it do expect(subject).to contain_exec("systemd-#{title}-systemctl-daemon-reload"). - with_command('systemctl daemon-reload'). - with_refreshonly(true) + with_command(%w[systemctl daemon-reload]). + with_refreshonly(true). + without_environment. + without_user end end @@ -28,6 +30,28 @@ expect(subject).not_to contain_exec("systemd-#{title}-systemctl-daemon-reload") end end + + context 'when a non-zero uid is specified' do + let(:params) do + { 'uid' => 1234 } + end + + it do + expect(subject).to contain_exec("systemd-#{title}-systemctl-user-1234-daemon-reload"). + with_command(%w[systemctl --user daemon-reload]). + with_environment('XDG_RUNTIME_DIR=/run/user/1234'). + with_user(1234). + with_refreshonly(true) + end + end + + context 'when the uid is 0 (root)' do + let(:params) do + { 'uid' => 0 } + end + + it { is_expected.to compile.and_raise_error(%r{Undef or Integer\[1\]}) } + end end end end