Skip to content

Commit

Permalink
Support management of Swap unit files
Browse files Browse the repository at this point in the history
Let `.swap` unit files be managed with `systemd::manage_dropin`
and `systemd::manage_unit`.

For example:

```puppet
systemd::manage_unit{'swapfile.swap':
  ensure        => 'present,
  active        => true,
  enable        => true,
  unit_entry    => {
    'Description' => 'Enable a swapfile at /swapfile',
  }
  swap_entry    => {
    'What' => '/swapfile',
  }
  install_entry => {
    'WantedBy' => 'multi-user.target',
  },
}
```

* https://www.freedesktop.org/software/systemd/man/latest/systemd.swap.html
  • Loading branch information
traylenator committed Nov 26, 2024
1 parent 9f2451a commit f9d42e5
Show file tree
Hide file tree
Showing 8 changed files with 212 additions and 0 deletions.
74 changes: 74 additions & 0 deletions REFERENCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@
* [`Systemd::Unit::Service::Exec`](#Systemd--Unit--Service--Exec): Possible strings for ExecStart, ExecStartPrep, ...
* [`Systemd::Unit::Slice`](#Systemd--Unit--Slice): Possible keys for the [Slice] section of a unit file
* [`Systemd::Unit::Socket`](#Systemd--Unit--Socket): Possible keys for the [Socket] section of a unit file
* [`Systemd::Unit::Swap`](#Systemd--Unit--Swap): Possible keys for the [Swap] 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
Expand Down Expand Up @@ -1125,6 +1126,7 @@ The following parameters are available in the `systemd::manage_dropin` defined t
* [`path_entry`](#-systemd--manage_dropin--path_entry)
* [`socket_entry`](#-systemd--manage_dropin--socket_entry)
* [`mount_entry`](#-systemd--manage_dropin--mount_entry)
* [`swap_entry`](#-systemd--manage_dropin--swap_entry)

##### <a name="-systemd--manage_dropin--unit"></a>`unit`

Expand Down Expand Up @@ -1276,6 +1278,14 @@ key value pairs for the [Mount] section of the unit file

Default value: `undef`

##### <a name="-systemd--manage_dropin--swap_entry"></a>`swap_entry`

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

key value pairs for the [Swap] section of the unit file

Default value: `undef`

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

Generate unit file from template
Expand Down Expand Up @@ -1377,6 +1387,43 @@ systemd::manage_dropin { 'tmpfs-db.conf':
}
```

##### Create and Mound a Swap File

```puppet
systemd::manage_unit{'swapfile.swap':
ensure => present,
enable => true,
active => true,
unit_entry => {
'Description' => 'Mount /swapfile as a swap file',
'After' => 'mkswap.service',
'Requires' => 'mkswap.service',
},
swap_entry => {
'What' => '/swapfile',
},
install_entry => {
'WantedBy' => 'multi-user.target',
},
require => Systemd::Manage_unit['mkswap.service'],
}
systemd::manage_unit{'mkswap.service':
ensure => present,
unit_entry => {
'Description' => 'Format a swapfile at /swapfile',
'ConditionPathExists' => '!/swapfile',
},
service_entry => {
'type' => 'oneshot',
'ExecStart' => [
'/usr/bin/dd if=/dev/zero of=/swapfile bs=1024 count=1000',
'/usr/sbin/mkswap /swapfile',
],
},
}
```

##### Remove a unit file

```puppet
Expand Down Expand Up @@ -1411,6 +1458,7 @@ The following parameters are available in the `systemd::manage_unit` defined typ
* [`path_entry`](#-systemd--manage_unit--path_entry)
* [`socket_entry`](#-systemd--manage_unit--socket_entry)
* [`mount_entry`](#-systemd--manage_unit--mount_entry)
* [`swap_entry`](#-systemd--manage_unit--swap_entry)

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

Expand Down Expand Up @@ -1586,6 +1634,14 @@ kev value pairs for [Mount] section of the unit file.

Default value: `undef`

##### <a name="-systemd--manage_unit--swap_entry"></a>`swap_entry`

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

kev value pairs for [Swap] section of the unit file.

Default value: `undef`

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

Creates a modules-load.d drop file
Expand Down Expand Up @@ -3435,6 +3491,24 @@ Struct[{
}]
```

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

Possible keys for the [Swap] section of a unit file

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

Alias of

```puppet
Struct[{
Optional['What'] => String[1],
Optional['Options'] => String[1],
Optional['Priority'] => Integer,
Optional['TimeoutSec'] => Variant[Integer[0],String[0]]
}]
```

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

Possible keys for the [Timer] section of a unit file
Expand Down
7 changes: 7 additions & 0 deletions manifests/manage_dropin.pp
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@
# @param path_entry key value pairs for [Path] section of the unit file
# @param socket_entry key value pairs for the [Socket] section of the unit file
# @param mount_entry key value pairs for the [Mount] section of the unit file
# @param swap_entry key value pairs for the [Swap] section of the unit file
#
define systemd::manage_dropin (
Systemd::Unit $unit,
Expand All @@ -110,6 +111,7 @@
Optional[Systemd::Unit::Path] $path_entry = undef,
Optional[Systemd::Unit::Socket] $socket_entry = undef,
Optional[Systemd::Unit::Mount] $mount_entry = undef,
Optional[Systemd::Unit::Swap] $swap_entry = undef,
) {
if $timer_entry and $unit !~ Pattern['^[^/]+\.timer'] {
fail("Systemd::Manage_dropin[${name}]: for unit ${unit} timer_entry is only valid for timer units")
Expand All @@ -131,6 +133,10 @@
fail("Systemd::Manage_dropin[${name}]: for unit ${unit} mount_entry is only valid for mount units")
}

if $swap_entry and $unit !~ Pattern['^[^/]+\.swap'] {
fail("Systemd::Manage_dropin[${name}]: for unit ${unit} mount_entry is only valid for swap units")
}

systemd::dropin_file { $name:
ensure => $ensure,
filename => $filename,
Expand All @@ -152,6 +158,7 @@
'path_entry' => $path_entry,
'socket_entry' => $socket_entry,
'mount_entry' => $mount_entry,
'swap_entry' => $swap_entry,
}),
}
}
41 changes: 41 additions & 0 deletions manifests/manage_unit.pp
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,40 @@
# },
# }
#
# @example Create and Mound a Swap File
#
# systemd::manage_unit{'swapfile.swap':
# ensure => present,
# enable => true,
# active => true,
# unit_entry => {
# 'Description' => 'Mount /swapfile as a swap file',
# 'After' => 'mkswap.service',
# 'Requires' => 'mkswap.service',
# },
# swap_entry => {
# 'What' => '/swapfile',
# },
# install_entry => {
# 'WantedBy' => 'multi-user.target',
# },
# require => Systemd::Manage_unit['mkswap.service'],
# }
# systemd::manage_unit{'mkswap.service':
# ensure => present,
# unit_entry => {
# 'Description' => 'Format a swapfile at /swapfile',
# 'ConditionPathExists' => '!/swapfile',
# },
# service_entry => {
# 'type' => 'oneshot',
# 'ExecStart' => [
# '/usr/bin/dd if=/dev/zero of=/swapfile bs=1024 count=1000',
# '/usr/sbin/mkswap /swapfile',
# ],
# },
# }
#
# @example Remove a unit file
# systemd::manage_unit { 'my.service':
# ensure => 'absent',
Expand Down Expand Up @@ -118,6 +152,7 @@
# @param path_entry key value pairs for [Path] section of the unit file.
# @param socket_entry kev value paors for [Socket] section of the unit file.
# @param mount_entry kev value pairs for [Mount] section of the unit file.
# @param swap_entry kev value pairs for [Swap] section of the unit file.
#
define systemd::manage_unit (
Enum['present', 'absent'] $ensure = 'present',
Expand All @@ -141,6 +176,7 @@
Optional[Systemd::Unit::Path] $path_entry = undef,
Optional[Systemd::Unit::Socket] $socket_entry = undef,
Optional[Systemd::Unit::Mount] $mount_entry = undef,
Optional[Systemd::Unit::Swap] $swap_entry = undef,
) {
assert_type(Systemd::Unit, $name)

Expand All @@ -164,6 +200,10 @@
fail("Systemd::Manage_unit[${name}]: mount_entry is only valid for mount units")
}

if $swap_entry and $name !~ Pattern['^[^/]+\.swap'] {
fail("Systemd::Manage_unit[${name}]: swap_entry is only valid for swap units")
}

if $ensure != 'absent' and $name =~ Pattern['^[^/]+\.service'] and !$service_entry {
fail("Systemd::Manage_unit[${name}]: service_entry is required for service units")
}
Expand All @@ -190,6 +230,7 @@
'path_entry' => $path_entry,
'socket_entry' => $socket_entry,
'mount_entry' => $mount_entry,
'swap_entry' => $swap_entry,
}),
}
}
20 changes: 20 additions & 0 deletions spec/defines/manage_dropin_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,26 @@
end
end

context 'on a swap unit' do
let(:params) do
{
unit: 'file.swap',
swap_entry: {
'Priority' => 10,
}
}
end

it { is_expected.to compile.with_all_deps }

it {
is_expected.to contain_systemd__dropin_file('foobar.conf').
with_unit('file.swap').
with_content(%r{^\[Swap\]$}).
with_content(%r{^Priority=10$})
}
end

context 'on a timer' do
let(:params) do
{
Expand Down
29 changes: 29 additions & 0 deletions spec/defines/manage_unit_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,35 @@
}
end

context 'on a swap' do
let(:title) { 'file.swap' }

let(:params) do
{
unit_entry: {
Description: 'Add swap from a file',
},
swap_entry: {
'What' => '/file',
'TimeoutSec' => 100,
'Options' => 'trim',
'Priority' => 10,
},
}
end

it { is_expected.to compile.with_all_deps }

it {
is_expected.to contain_systemd__unit_file('file.swap').
with_content(%r{^\[Swap\]$}).
with_content(%r{^What=/file$}).
with_content(%r{^TimeoutSec=100$}).
with_content(%r{^Options=trim$}).
with_content(%r{^Priority=10$})
}
end

context 'on a timer' do
let(:title) { 'winter.timer' }

Expand Down
28 changes: 28 additions & 0 deletions spec/type_aliases/systemd_unit_swap_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# frozen_string_literal: true

require 'spec_helper'

describe 'Systemd::Unit::Swap' do
context 'with a key of What can have thing to mount' do
it { is_expected.to allow_value({ 'What' => '/tmpfs' }) }
it { is_expected.to allow_value({ 'What' => '/dev/vda1' }) }
end

context 'with a key of Options' do
it { is_expected.to allow_value({ 'Options' => 'trim' }) }
end

context 'with a key of Priority' do
it { is_expected.to allow_value({ 'Priority' => 10 }) }
end

context 'with a key of TimeoutSec can have a mode of' do
it { is_expected.to allow_value({ 'TimeoutSec' => '100' }) }
it { is_expected.to allow_value({ 'TimeoutSec' => '5min 20s' }) }
it { is_expected.to allow_value({ 'TimeoutSec' => '' }) }
end

context 'with a key of Where' do
it { is_expected.not_to allow_value({ 'Where' => '/mnt/foo' }) }
end
end
2 changes: 2 additions & 0 deletions templates/unit_file.epp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
Optional[Hash] $path_entry,
Optional[Hash] $socket_entry,
Optional[Hash] $mount_entry,
Optional[Hash] $swap_entry,
| -%>
<%-

Expand All @@ -22,6 +23,7 @@
'Socket',
'Install',
'Mount',
'Swap',
]

# Directives which are pair of items to be expressed as a space seperated pair.
Expand Down
11 changes: 11 additions & 0 deletions types/unit/swap.pp
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# @summary Possible keys for the [Swap] section of a unit file
# @see https://www.freedesktop.org/software/systemd/man/latest/systemd.swap.html
#
type Systemd::Unit::Swap = Struct[
{
Optional['What'] => String[1],
Optional['Options'] => String[1],
Optional['Priority'] => Integer,
Optional['TimeoutSec'] => Variant[Integer[0],String[0]]
}
]

0 comments on commit f9d42e5

Please sign in to comment.