Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add a cron like wrapper for timers #419

Merged
merged 3 commits into from
Mar 4, 2024
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
183 changes: 177 additions & 6 deletions REFERENCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
* [`systemd::network`](#systemd--network): Creates network config for systemd-networkd
* [`systemd::service_limits`](#systemd--service_limits): Adds a set of custom limits to the service
* [`systemd::timer`](#systemd--timer): Create a timer and optionally a service unit to execute with the timer unit
* [`systemd::timer_wrapper`](#systemd--timer_wrapper): Helper to define timer and accompanying services for a given task (cron like interface).
* [`systemd::tmpfile`](#systemd--tmpfile): Creates a systemd tmpfile
* [`systemd::udev::rule`](#systemd--udev--rule): Adds a custom udev rule
* [`systemd::unit_file`](#systemd--unit_file): Creates a systemd unit file
Expand Down Expand Up @@ -67,6 +68,7 @@
* [`Systemd::Unit::Service::Exec`](#Systemd--Unit--Service--Exec): Possible strings for ExecStart, ExecStartPrep, ...
* [`Systemd::Unit::Socket`](#Systemd--Unit--Socket): Possible keys for the [Socket] section of a unit file
* [`Systemd::Unit::Timer`](#Systemd--Unit--Timer): Possible keys for the [Timer] section of a unit file
* [`Systemd::Unit::Timespan`](#Systemd--Unit--Timespan): Timer specification for systemd time spans, e.g. timers.
* [`Systemd::Unit::Unit`](#Systemd--Unit--Unit): Possible keys for the [Unit] section of a unit file

## Classes
Expand Down Expand Up @@ -1677,6 +1679,166 @@ Call `systemd::daemon_reload`

Default value: `true`

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

Helper to define timer and accompanying services for a given task (cron like interface).

#### Examples

##### Create a timer that runs every 5 minutes

```puppet
systemd::timer_wrapper { 'my_timer':
ensure => 'present',
command => '/usr/bin/echo "Hello World"',
on_calendar => '*:0/5',
}
```

##### Create a timer with overrides for the service and timer

```puppet
systemd::timer_wrapper { 'my_timer':
ensure => 'present',
command => '/usr/bin/echo "Hello World"',
on_calendar => '*:0/5',
service_overrides => { 'Group' => 'nobody' },
timer_overrides => { 'OnBootSec' => '10' },
}
```

##### Create a timer with overrides for the service_unit and timer_unit

```puppet
systemd::timer_wrapper { 'my_timer':
ensure => 'present',
command => '/usr/bin/echo "Hello World"',
on_calendar => '*:0/5',
service_unit_overrides => { 'Wants' => 'network-online.target' },
timer_unit_overrides => { 'Description' => 'Very special timer' },
}
```

#### Parameters

The following parameters are available in the `systemd::timer_wrapper` defined type:

* [`ensure`](#-systemd--timer_wrapper--ensure)
* [`command`](#-systemd--timer_wrapper--command)
* [`user`](#-systemd--timer_wrapper--user)
* [`on_active_sec`](#-systemd--timer_wrapper--on_active_sec)
* [`on_boot_sec`](#-systemd--timer_wrapper--on_boot_sec)
* [`on_start_up_sec`](#-systemd--timer_wrapper--on_start_up_sec)
* [`on_unit_active_sec`](#-systemd--timer_wrapper--on_unit_active_sec)
* [`on_unit_inactive_sec`](#-systemd--timer_wrapper--on_unit_inactive_sec)
* [`on_calendar`](#-systemd--timer_wrapper--on_calendar)
* [`service_overrides`](#-systemd--timer_wrapper--service_overrides)
* [`timer_overrides`](#-systemd--timer_wrapper--timer_overrides)
* [`service_unit_overrides`](#-systemd--timer_wrapper--service_unit_overrides)
* [`timer_unit_overrides`](#-systemd--timer_wrapper--timer_unit_overrides)

##### <a name="-systemd--timer_wrapper--ensure"></a>`ensure`

Data type: `Enum['present', 'absent']`

whether the timer and service should be present or absent

##### <a name="-systemd--timer_wrapper--command"></a>`command`

Data type: `Optional[Systemd::Unit::Service::Exec]`

the command for the systemd servie to execute

Default value: `undef`

##### <a name="-systemd--timer_wrapper--user"></a>`user`

Data type: `Optional[String[1]]`

the user to run the command as

Default value: `undef`

##### <a name="-systemd--timer_wrapper--on_active_sec"></a>`on_active_sec`

Data type: `Optional[Systemd::Unit::Timespan]`

run service relative to the time when the timer was activated

Default value: `undef`

##### <a name="-systemd--timer_wrapper--on_boot_sec"></a>`on_boot_sec`

Data type: `Optional[Systemd::Unit::Timespan]`

run service relative to when the machine was booted

Default value: `undef`

##### <a name="-systemd--timer_wrapper--on_start_up_sec"></a>`on_start_up_sec`

Data type: `Optional[Systemd::Unit::Timespan]`

run service relative to when the service manager was started

Default value: `undef`

##### <a name="-systemd--timer_wrapper--on_unit_active_sec"></a>`on_unit_active_sec`

Data type: `Optional[Systemd::Unit::Timespan]`

run service relative to when the unit was last activated

Default value: `undef`

##### <a name="-systemd--timer_wrapper--on_unit_inactive_sec"></a>`on_unit_inactive_sec`

Data type: `Optional[Systemd::Unit::Timespan]`

run service relative to when the unit was last deactivated

Default value: `undef`

##### <a name="-systemd--timer_wrapper--on_calendar"></a>`on_calendar`

Data type: `Optional[Systemd::Unit::Timespan]`

the calendar event expressions time to run the service

Default value: `undef`

##### <a name="-systemd--timer_wrapper--service_overrides"></a>`service_overrides`

Data type: `Systemd::Unit::Service`

override for the`[Service]` section of the service

Default value: `{}`

##### <a name="-systemd--timer_wrapper--timer_overrides"></a>`timer_overrides`

Data type: `Systemd::Unit::Timer`

override for the`[Timer]` section of the timer

Default value: `{}`

##### <a name="-systemd--timer_wrapper--service_unit_overrides"></a>`service_unit_overrides`

Data type: `Systemd::Unit::Unit`

override for the`[Unit]` section of the service

Default value: `{}`

##### <a name="-systemd--timer_wrapper--timer_unit_overrides"></a>`timer_unit_overrides`

Data type: `Systemd::Unit::Unit`

override for the `[Unit]` section of the timer

Default value: `{}`

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

Creates a systemd tmpfile
Expand Down Expand Up @@ -2578,12 +2740,12 @@ Alias of

```puppet
Struct[{
Optional['OnActiveSec'] => Variant[Integer[0],String,Array[Variant[Integer[0],String]]],
Optional['OnBootSec'] => Variant[Integer[0],String,Array[Variant[Integer[0],String]]],
Optional['OnStartUpSec'] => Variant[Integer[0],String,Array[Variant[Integer[0],String]]],
Optional['OnUnitActiveSec'] => Variant[Integer[0],String,Array[Variant[Integer[0],String]]],
Optional['OnUnitInactiveSec'] => Variant[Integer[0],String,Array[Variant[Integer[0],String]]],
Optional['OnCalendar'] => Variant[Integer[0],String,Array[Variant[Integer[0],String]]],
Optional['OnActiveSec'] => Systemd::Unit::Timespan,
Optional['OnBootSec'] => Systemd::Unit::Timespan,
Optional['OnStartUpSec'] => Systemd::Unit::Timespan,
Optional['OnUnitActiveSec'] => Systemd::Unit::Timespan,
Optional['OnUnitInactiveSec'] => Systemd::Unit::Timespan,
Optional['OnCalendar'] => Systemd::Unit::Timespan,
Optional['AccuracySec'] => Variant[Integer[0],String],
Optional['RandomizedDelaySec'] => Variant[Integer[0],String],
Optional['FixedRandomDelay'] => Boolean,
Expand All @@ -2596,6 +2758,15 @@ Struct[{
}]
```

### <a name="Systemd--Unit--Timespan"></a>`Systemd::Unit::Timespan`

Timer specification for systemd time spans, e.g. timers.

* **See also**
* https://www.freedesktop.org/software/systemd/man/systemd.time.html

Alias of `Variant[Integer[0], String, Array[Variant[Integer[0],String]]]`

### <a name="Systemd--Unit--Unit"></a>`Systemd::Unit::Unit`

Possible keys for the [Unit] section of a unit file
Expand Down
113 changes: 113 additions & 0 deletions manifests/timer_wrapper.pp
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
# @summary
# Helper to define timer and accompanying services for a given task (cron like interface).
# @param ensure whether the timer and service should be present or absent
# @param command the command for the systemd servie to execute
# @param user the user to run the command as
# @param on_active_sec run service relative to the time when the timer was activated
# @param on_boot_sec run service relative to when the machine was booted
# @param on_start_up_sec run service relative to when the service manager was started
# @param on_unit_active_sec run service relative to when the unit was last activated
# @param on_unit_inactive_sec run service relative to when the unit was last deactivated
# @param on_calendar the calendar event expressions time to run the service
# @param service_overrides override for the`[Service]` section of the service
# @param timer_overrides override for the`[Timer]` section of the timer
# @param service_unit_overrides override for the`[Unit]` section of the service
# @param timer_unit_overrides override for the `[Unit]` section of the timer
# @example Create a timer that runs every 5 minutes
# systemd::timer_wrapper { 'my_timer':
# ensure => 'present',
# command => '/usr/bin/echo "Hello World"',
# on_calendar => '*:0/5',
# }
# @example Create a timer with overrides for the service and timer
# systemd::timer_wrapper { 'my_timer':
# ensure => 'present',
# command => '/usr/bin/echo "Hello World"',
# on_calendar => '*:0/5',
# service_overrides => { 'Group' => 'nobody' },
# timer_overrides => { 'OnBootSec' => '10' },
# }
# @example Create a timer with overrides for the service_unit and timer_unit
# systemd::timer_wrapper { 'my_timer':
# ensure => 'present',
# command => '/usr/bin/echo "Hello World"',
# on_calendar => '*:0/5',
# service_unit_overrides => { 'Wants' => 'network-online.target' },
# timer_unit_overrides => { 'Description' => 'Very special timer' },
# }
define systemd::timer_wrapper (
Enum['present', 'absent'] $ensure,
Optional[Systemd::Unit::Service::Exec] $command = undef,
Optional[String[1]] $user = undef,
Optional[Systemd::Unit::Timespan] $on_active_sec = undef,
Optional[Systemd::Unit::Timespan] $on_boot_sec = undef,
Optional[Systemd::Unit::Timespan] $on_start_up_sec = undef,
Optional[Systemd::Unit::Timespan] $on_unit_active_sec = undef,
Optional[Systemd::Unit::Timespan] $on_unit_inactive_sec = undef,
Optional[Systemd::Unit::Timespan] $on_calendar = undef,
Systemd::Unit::Service $service_overrides = {},
Systemd::Unit::Timer $timer_overrides = {},
Systemd::Unit::Unit $timer_unit_overrides = {},
Systemd::Unit::Unit $service_unit_overrides = {},
) {
$_timer_spec = {
'OnActiveSec' => $on_active_sec,
'OnBootSec' => $on_boot_sec,
'OnStartUpSec' => $on_start_up_sec,
'OnUnitActiveSec' => $on_unit_active_sec,
'OnUnitInactiveSec' => $on_unit_inactive_sec,
'OnCalendar' => $on_calendar,
}.filter |$k, $v| { $v =~ NotUndef }
TheMeier marked this conversation as resolved.
Show resolved Hide resolved

if $ensure == 'present' {
if $_timer_spec == {} {
fail('At least one of on_active_sec,
on_boot_sec,
on_start_up_sec,
on_unit_active_sec,
on_unit_inactive_sec,
or on_calendar must be set'
)
}
if ! $command {
TheMeier marked this conversation as resolved.
Show resolved Hide resolved
fail('command must be set')
}
}

$service_ensure = $ensure ? { 'absent' => false, default => true, }
TheMeier marked this conversation as resolved.
Show resolved Hide resolved
$unit_name = systemd::escape($title)

systemd::manage_unit { "${unit_name}.service":
ensure => $ensure,
unit_entry => $service_unit_overrides,
TheMeier marked this conversation as resolved.
Show resolved Hide resolved
service_entry => {
'ExecStart' => $command, # if ensure present command is defined is checked above
'User' => $user, # defaults apply
'Type' => 'oneshot',
}.filter |$key, $val| { $val =~ NotUndef } + $service_overrides,
}
systemd::manage_unit { "${unit_name}.timer":
TheMeier marked this conversation as resolved.
Show resolved Hide resolved
ensure => $ensure,
unit_entry => $timer_unit_overrides,
timer_entry => $_timer_spec + $timer_overrides,
install_entry => {
'WantedBy' => 'timers.target',
},
}

service { "${unit_name}.timer":
ensure => $service_ensure,
enable => $service_ensure,
}

if $ensure == 'present' {
Systemd::Manage_unit["${unit_name}.service"]
-> Systemd::Manage_unit["${unit_name}.timer"]
-> Service["${unit_name}.timer"]
} else {
# Ensure the timer is stopped and disabled before the service
Service["${unit_name}.timer"]
-> Systemd::Manage_unit["${unit_name}.timer"]
-> Systemd::Manage_unit["${unit_name}.service"]
}
}
Loading