Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,25 @@ class { 'systemd':
}
```

### User Services

User services can be managed

```puppet

systemd::user_service { 'hour.service':
ensure => true,
enable => true,
user => 'higgs',
}
```

This will run `systemctl --user enable hour.service` and `systemctl --user start hour.service` as the user higgs.

On Debian 12 and RHEL9 the `runuser` command is used for `systemd::user_service` which can be installed with
the `runuser => true` parameter to the main class. Newer operating systems use `run0` which is always available with `systemd`.


### journald configuration

It also allows you to manage journald settings. You can manage journald settings through setting the `journald_settings` parameter. If you want a parameter to be removed, you can pass its value as params.
Expand Down
57 changes: 57 additions & 0 deletions REFERENCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
### Functions

* [`systemd::escape`](#systemd--escape): Escape strings as systemd-escape does.
* [`systemd::systemctl_user`](#systemd--systemctl_user): Construct command array for running `systemctl --user` for particular arguments
* [`systemd::systemd_escape`](#systemd--systemd_escape): Escape strings by call the `systemd-escape` command in the background.

### Data types
Expand Down Expand Up @@ -269,6 +270,7 @@ The following parameters are available in the `systemd` class:
* [`system_settings`](#-systemd--system_settings)
* [`manage_user_conf`](#-systemd--manage_user_conf)
* [`user_settings`](#-systemd--user_settings)
* [`install_runuser`](#-systemd--install_runuser)

##### <a name="-systemd--default_target"></a>`default_target`

Expand Down Expand Up @@ -896,6 +898,14 @@ the settings.

Default value: `{}`

##### <a name="-systemd--install_runuser"></a>`install_runuser`

Data type: `Boolean`

If true, the util-linux package is installed, for runuser command.

Default value: `false`

### <a name="systemd--tmpfiles"></a>`systemd::tmpfiles`

Update the systemd temp files
Expand Down Expand Up @@ -2793,6 +2803,9 @@ Manage a user service running under systemd --user
##### Enable a service for all users

```puppet
class { 'systemd':
install_runuser => true,
}
systemd::user_service { 'systemd-tmpfiles-clean.timer':
enable => true,
global => true,
Expand Down Expand Up @@ -2972,6 +2985,50 @@ Data type: `Boolean`

Use path (-p) ornon-path style escaping.

### <a name="systemd--systemctl_user"></a>`systemd::systemctl_user`

Type: Puppet Language

Construct command array for running `systemctl --user` for particular arguments

#### Examples

##### Start a user service with an exec

```puppet
exec { 'start_service':
command => systemd::systemctl_user('santa', 'start myservice.service'),
}
```

#### `systemd::systemctl_user(String[1] $user, Array[String[1],1] $arguments)`

The systemd::systemctl_user function.

Returns: `Array` Array Array of command and arguments

##### Examples

###### Start a user service with an exec

```puppet
exec { 'start_service':
command => systemd::systemctl_user('santa', 'start myservice.service'),
}
```

##### `user`

Data type: `String[1]`

User instance of `systemd --user` to connect to.

##### `arguments`

Data type: `Array[String[1],1]`

Arguments to run after `systemctl --user`

### <a name="systemd--systemd_escape"></a>`systemd::systemd_escape`

Type: Ruby 4.x API
Expand Down
29 changes: 29 additions & 0 deletions functions/systemctl_user.pp
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# @summary Construct command array for running `systemctl --user` for particular arguments
# @param user User instance of `systemd --user` to connect to.
# @param arguments Arguments to run after `systemctl --user`
#
# @return Array Array of command and arguments
# @example Start a user service with an exec
# exec { 'start_service':
# command => systemd::systemctl_user('santa', 'start myservice.service'),
# }
function systemd::systemctl_user(String[1] $user, Array[String[1],1] $arguments) >> Array {
# Why is runuser being used here for older systemds?
# More obvious command arrays to return would be:
# * ['run0','--user',$user,'systemctl','--user'] + $arguments
# * ['systemctl', '--user', '--machine', "${user}@.host"] + $arguments
# * ['systemd-run','--wait','--pipe', 'systemctl', '--user', '--machine', "${user}@.host"] + $arguments
# However none of these work when puppet is run as a background service. They only work with
# puppet apply in the foreground. Reason is unclear, possibly polkit blocking access
# https://github.com/voxpupuli/puppet-systemd/issues/459

$_cmd_array = Integer($facts['systemd_version']) < 256 ? {
true => [
'runuser', '-u', $user, '--' ,'/usr/bin/bash', '-c',
"env XDG_RUNTIME_DIR=/run/user/\$(id -u) /usr/bin/systemctl --user ${arguments.join(' ')}",
],
default => ['run0','--user',$user,'/usr/bin/systemctl','--user'] + $arguments,
}

return $_cmd_array
}
2 changes: 1 addition & 1 deletion manifests/daemon_reload.pp
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
}

$_title = "${module_name}-${name}-systemctl-user-${user}-daemon-reload"
$_command = ['systemd-run', '--pipe', '--wait', '--user', '--machine', "${user}@.host", 'systemctl', '--user', 'daemon-reload']
$_command = systemd::systemctl_user($user, ['daemon-reload'])
} else {
$_title = "${module_name}-${name}-systemctl-daemon-reload"
$_command = ['systemctl', 'daemon-reload']
Expand Down
5 changes: 5 additions & 0 deletions manifests/init.pp
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,10 @@
# Config Hash that is used to configure settings in user.conf
# NOTE: It's currently impossible to have multiple entries of the same key in
# the settings.
#
# @param install_runuser
# If true, the util-linux package is installed, for runuser command.
#
class systemd (
Optional[Pattern['^.+\.target$']] $default_target = undef,
Hash[String,String] $accounting = {},
Expand Down Expand Up @@ -331,6 +335,7 @@
Systemd::ServiceManagerSettings $system_settings = {},
Boolean $manage_user_conf = false,
Systemd::ServiceManagerSettings $user_settings = {},
Boolean $install_runuser = false,
) {
contain systemd::install

Expand Down
6 changes: 6 additions & 0 deletions manifests/install.pp
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,10 @@
ensure => present,
}
}

if $systemd::install_runuser {
package { 'util-linux':
ensure => installed,
}
}
}
26 changes: 12 additions & 14 deletions manifests/user_service.pp
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
# @summary Manage a user service running under systemd --user
#
# @example Enable a service for all users
# class { 'systemd':
# install_runuser => true,
# }
# systemd::user_service { 'systemd-tmpfiles-clean.timer':
# enable => true,
# global => true,
Expand Down Expand Up @@ -74,31 +77,26 @@
}
} else { # per user services

$_systemctl_user = [
'systemd-run', '--pipe', '--wait', '--user', '--machine', "${user}@.host",
'systemctl', '--user',
]

# To accept notifies of this type.
exec { "try-reload-or-restart-${user}-${unit}":
command => $_systemctl_user + ['try-reload-or-restart', $unit],
command => systemd::systemctl_user($user, ['try-reload-or-restart', $unit]),
refreshonly => true,
path => $facts['path'],
}

if $_ensure {
$_ensure_title = "Start user service ${unit} for user ${user}"
$_ensure_command = $_systemctl_user + ['start', $unit]
$_ensure_unless = [$_systemctl_user + ['is-active', $unit]]
$_ensure_command = systemd::systemctl_user($user, ['start',$unit])
$_ensure_unless = [systemd::systemctl_user($user, ['is-active',$unit])]
$_ensure_onlyif = undef

# Don't reload just after starting
Exec["try-reload-or-restart-${user}-${unit}"] -> Exec[$_ensure_title]
} else {
$_ensure_title = "Stop user service ${unit} for user ${user}"
$_ensure_command = $_systemctl_user + ['stop', $unit]
$_ensure_command = systemd::systemctl_user($user, ['stop', $unit])
$_ensure_unless = undef
$_ensure_onlyif = [$_systemctl_user + ['is-active', $unit]]
$_ensure_onlyif = [systemd::systemctl_user($user, ['is-active',$unit])]
}

exec { $_ensure_title:
Expand All @@ -110,8 +108,8 @@

if $enable {
$_enable_title = "Enable user service ${unit} for user ${user}"
$_enable_command = $_systemctl_user + ['enable', $unit]
$_enable_unless = [$_systemctl_user + ['is-enabled', $unit]]
$_enable_command = systemd::systemctl_user($user, ['enable', $unit])
$_enable_unless = [systemd::systemctl_user($user, ['is-enabled', $unit])]
$_enable_onlyif = undef

# Puppet does this for services so lets copy that logic
Expand All @@ -121,9 +119,9 @@
}
} else {
$_enable_title = "Disable user service ${unit} for user ${user}"
$_enable_command = $_systemctl_user + ['disable', $unit]
$_enable_command = systemd::systemctl_user($user, ['disable', $unit])
$_enable_unless = undef
$_enable_onlyif = [$_systemctl_user + ['is-enabled', $unit]]
$_enable_onlyif = [systemd::systemctl_user($user, ['is-enabled', $unit])]
}

exec { $_enable_title:
Expand Down
10 changes: 9 additions & 1 deletion spec/acceptance/user_service_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@

# systemd-logind.service must be running.
class{ 'systemd':
manage_logind => true,
manage_logind => true,
install_runuser => true,
}

user { 'higgs' :
Expand All @@ -21,6 +22,13 @@
linger => enabled,
}

# https://github.com/voxpupuli/puppet-systemd/issues/578
exec{'/usr/bin/sleep 10 && touch /tmp/sleep-only-once':
creates => '/tmp/sleep-only-once',
require => Loginctl_user['higgs'],
before => File['/home/higgs/.config'],
}

# Assumes home directory was created as /home/higgs
file{['/home/higgs/.config', '/home/higgs/.config/systemd','/home/higgs/.config/systemd/user']:
ensure => directory,
Expand Down Expand Up @@ -57,7 +65,7 @@
PUPPET
end

it 'works idempotently with no errors' do

Check warning on line 68 in spec/acceptance/user_service_spec.rb

View workflow job for this annotation

GitHub Actions / Puppet / OpenVox 8 - Debian 11

systemd::user_service create and start a user unit works idempotently with no errors Skipped: we know old OSes do not work

Check warning on line 68 in spec/acceptance/user_service_spec.rb

View workflow job for this annotation

GitHub Actions / Puppet / OpenVox 8 - Ubuntu 22.04

systemd::user_service create and start a user unit works idempotently with no errors Skipped: we know old OSes do not work

Check warning on line 68 in spec/acceptance/user_service_spec.rb

View workflow job for this annotation

GitHub Actions / Puppet / OpenVox 8 - AlmaLinux 8

systemd::user_service create and start a user unit works idempotently with no errors Skipped: we know old OSes do not work

Check warning on line 68 in spec/acceptance/user_service_spec.rb

View workflow job for this annotation

GitHub Actions / Puppet / OpenVox 8 - OracleLinux 8

systemd::user_service create and start a user unit works idempotently with no errors Skipped: we know old OSes do not work

Check warning on line 68 in spec/acceptance/user_service_spec.rb

View workflow job for this annotation

GitHub Actions / Puppet / OpenVox 8 - Rocky 8

systemd::user_service create and start a user unit works idempotently with no errors Skipped: we know old OSes do not work
skip 'we know old OSes do not work' if
((fact('os.name') == 'Debian') && (fact('os.release.major') == '11')) ||
((fact('os.name') == 'Ubuntu') && (fact('os.release.major') == '22.04')) ||
Expand All @@ -67,7 +75,7 @@
end

describe 'hour.service user unit' do
it 'is running' do

Check warning on line 78 in spec/acceptance/user_service_spec.rb

View workflow job for this annotation

GitHub Actions / Puppet / OpenVox 8 - Debian 11

systemd::user_service create and start a user unit hour.service user unit is running Skipped: we know old OSes do not work

Check warning on line 78 in spec/acceptance/user_service_spec.rb

View workflow job for this annotation

GitHub Actions / Puppet / OpenVox 8 - Ubuntu 22.04

systemd::user_service create and start a user unit hour.service user unit is running Skipped: we know old OSes do not work

Check warning on line 78 in spec/acceptance/user_service_spec.rb

View workflow job for this annotation

GitHub Actions / Puppet / OpenVox 8 - AlmaLinux 8

systemd::user_service create and start a user unit hour.service user unit is running Skipped: we know old OSes do not work

Check warning on line 78 in spec/acceptance/user_service_spec.rb

View workflow job for this annotation

GitHub Actions / Puppet / OpenVox 8 - OracleLinux 8

systemd::user_service create and start a user unit hour.service user unit is running Skipped: we know old OSes do not work

Check warning on line 78 in spec/acceptance/user_service_spec.rb

View workflow job for this annotation

GitHub Actions / Puppet / OpenVox 8 - Rocky 8

systemd::user_service create and start a user unit hour.service user unit is running Skipped: we know old OSes do not work
skip 'we know old OSes do not work' if
((fact('os.name') == 'Debian') && (fact('os.release.major') == '11')) ||
((fact('os.name') == 'Ubuntu') && (fact('os.release.major') == '22.04')) ||
Expand All @@ -77,7 +85,7 @@
expect(result.stdout.strip).to eq('active')
end

it 'is enabled' do

Check warning on line 88 in spec/acceptance/user_service_spec.rb

View workflow job for this annotation

GitHub Actions / Puppet / OpenVox 8 - Debian 11

systemd::user_service create and start a user unit hour.service user unit is enabled Skipped: we know old OSes do not work

Check warning on line 88 in spec/acceptance/user_service_spec.rb

View workflow job for this annotation

GitHub Actions / Puppet / OpenVox 8 - Ubuntu 22.04

systemd::user_service create and start a user unit hour.service user unit is enabled Skipped: we know old OSes do not work

Check warning on line 88 in spec/acceptance/user_service_spec.rb

View workflow job for this annotation

GitHub Actions / Puppet / OpenVox 8 - AlmaLinux 8

systemd::user_service create and start a user unit hour.service user unit is enabled Skipped: we know old OSes do not work

Check warning on line 88 in spec/acceptance/user_service_spec.rb

View workflow job for this annotation

GitHub Actions / Puppet / OpenVox 8 - OracleLinux 8

systemd::user_service create and start a user unit hour.service user unit is enabled Skipped: we know old OSes do not work

Check warning on line 88 in spec/acceptance/user_service_spec.rb

View workflow job for this annotation

GitHub Actions / Puppet / OpenVox 8 - Rocky 8

systemd::user_service create and start a user unit hour.service user unit is enabled Skipped: we know old OSes do not work
skip 'we know old OSes do not work' if
((fact('os.name') == 'Debian') && (fact('os.release.major') == '11')) ||
((fact('os.name') == 'Ubuntu') && (fact('os.release.major') == '22.04')) ||
Expand Down
9 changes: 9 additions & 0 deletions spec/classes/init_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
it { is_expected.not_to contain_package('systemd-timesyncd') }
it { is_expected.not_to contain_package('systemd-resolved') }
it { is_expected.not_to contain_package('systemd-container') }
it { is_expected.not_to contain_package('util-linux') }
it { is_expected.not_to contain_class('systemd::coredump') }
it { is_expected.not_to contain_class('systemd::oomd') }
it { is_expected.not_to contain_exec('systemctl set-default multi-user.target') }
Expand Down Expand Up @@ -1188,6 +1189,14 @@
it { is_expected.to contain_systemd__dropin_file('coredump_backtrace.conf').with_content(%r{^ExecStart=.*--backtrace$}) }
end
end

context 'with install_runuser true' do
let :params do
{ install_runuser: true }
end

it { is_expected.to contain_package('util-linux').with_ensure('installed') }
end
end
end
end
Expand Down
4 changes: 2 additions & 2 deletions spec/defines/daemon_reload_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
context 'supported operating systems' do
on_supported_os.each do |os, facts|
context "on #{os}" do
let(:facts) { facts }
let(:facts) { facts.merge(systemd_version: '256') }
let(:title) { 'irregardless' }

it { is_expected.to compile.with_all_deps }
Expand Down Expand Up @@ -36,7 +36,7 @@

it {
is_expected.to contain_exec('systemd-irregardless-systemctl-user-steve-daemon-reload').
with_command(['systemd-run', '--pipe', '--wait', '--user', '--machine', 'steve@.host', 'systemctl', '--user', 'daemon-reload']).
with_command(['run0', '--user', 'steve', '/usr/bin/systemctl', '--user', 'daemon-reload']).
with_refreshonly(true)
}

Expand Down
Loading
Loading