From df387423521ff6d2a60b2e607c4a61adb3f1457a Mon Sep 17 00:00:00 2001 From: Steve Traylen Date: Thu, 12 Sep 2024 16:08:38 +0200 Subject: [PATCH] Support Mount units for manage_unit or dropin types Support addition `.mount` units in `systemd::manage_unit` and `systemd::manage_type`. e.g. ```puppet systemd::manage_unit { 'var-lib-sss-db.mount': ensure => $_use_ramdisk, unit_entry => { 'Description' => 'Mount a ram disk for sssd to use', }, mount_entry => { 'What' => 'tmpfs', 'Where' => '/var/lib/sss/db', 'Type' => 'tmpfs', 'Options' => "size=${ramdisk}M,mode=0700,uid=sssd,gid=sssd,rootcontext=system_u:object_r:sssd_var_lib_t:s0", }, } ``` * https://www.freedesktop.org/software/systemd/man/latest/systemd.mount.html --- REFERENCE.md | 67 ++++++++++++++++++++ manifests/manage_dropin.pp | 7 ++ manifests/manage_unit.pp | 28 ++++++++ spec/defines/manage_dropin_spec.rb | 19 ++++++ spec/defines/manage_unit_spec.rb | 28 ++++++++ spec/type_aliases/systemd_unit_mount_spec.rb | 42 ++++++++++++ templates/unit_file.epp | 2 + types/unit/mount.pp | 17 +++++ 8 files changed, 210 insertions(+) create mode 100644 spec/type_aliases/systemd_unit_mount_spec.rb create mode 100644 types/unit/mount.pp diff --git a/REFERENCE.md b/REFERENCE.md index 6cd610a7..339624ca 100644 --- a/REFERENCE.md +++ b/REFERENCE.md @@ -67,6 +67,7 @@ * [`Systemd::Unit::Amount`](#Systemd--Unit--Amount): Systemd definition of amount, often bytes or united bytes * [`Systemd::Unit::AmountOrPercent`](#Systemd--Unit--AmountOrPercent): Systemd definition of amount, often bytes or united bytes * [`Systemd::Unit::Install`](#Systemd--Unit--Install): Possible keys for the [Install] section of a unit file +* [`Systemd::Unit::Mount`](#Systemd--Unit--Mount): Possible keys for the [Mount] section of a unit file * [`Systemd::Unit::Path`](#Systemd--Unit--Path): Possible keys for the [Path] section of a unit file * [`Systemd::Unit::Percent`](#Systemd--Unit--Percent): Systemd definition of a percentage * [`Systemd::Unit::Service`](#Systemd--Unit--Service): Possible keys for the [Service] section of a unit file @@ -1031,6 +1032,7 @@ The following parameters are available in the `systemd::manage_dropin` defined t * [`timer_entry`](#-systemd--manage_dropin--timer_entry) * [`path_entry`](#-systemd--manage_dropin--path_entry) * [`socket_entry`](#-systemd--manage_dropin--socket_entry) +* [`mount_entry`](#-systemd--manage_dropin--mount_entry) ##### `unit` @@ -1174,6 +1176,14 @@ key value pairs for the [Socket] section of the unit file Default value: `undef` +##### `mount_entry` + +Data type: `Optional[Systemd::Unit::Mount]` + +key value pairs for the [Mount] section of the unit file + +Default value: `undef` + ### `systemd::manage_unit` Generate unit file from template @@ -1251,6 +1261,30 @@ systemd::manage_unit{'arcd@.service': } ``` +##### Mount a Filesystem and Use for a Service + +```puppet +systemd::manage_unit { 'var-lib-sss-db.mount': + ensure => present, + unit_entry => { + 'Description' => 'Mount sss tmpfs db', + }, + mount_entry => { + 'What' => 'tmpfs', + 'Where' => '/var/lib/sss/db', + 'Type' => 'tmpfs', + 'Options' => 'size=300M,mode=0700,uid=sssd,gid=sssd,rootcontext=system_u:object_r:sssd_var_lib_t:s0', + }, +} +systemd::manage_dropin { 'tmpfs-db.conf': + ensure => present, + unit => 'sssd.service', + unit_entry => { + 'RequiresMountsFor' => '/var/lib/sss/db', + }, +} +``` + ##### Remove a unit file ```puppet @@ -1284,6 +1318,7 @@ The following parameters are available in the `systemd::manage_unit` defined typ * [`timer_entry`](#-systemd--manage_unit--timer_entry) * [`path_entry`](#-systemd--manage_unit--path_entry) * [`socket_entry`](#-systemd--manage_unit--socket_entry) +* [`mount_entry`](#-systemd--manage_unit--mount_entry) ##### `name` @@ -1451,6 +1486,14 @@ kev value paors for [Socket] section of the unit file. Default value: `undef` +##### `mount_entry` + +Data type: `Optional[Systemd::Unit::Mount]` + +kev value pairs for [Mount] section of the unit file. + +Default value: `undef` + ### `systemd::modules_load` Creates a modules-load.d drop file @@ -2798,6 +2841,30 @@ Struct[{ }] ``` +### `Systemd::Unit::Mount` + +Possible keys for the [Mount] section of a unit file + +* **See also** + * https://www.freedesktop.org/software/systemd/man/latest/systemd.mount.html + +Alias of + +```puppet +Struct[{ + Optional['What'] => String[1], + Optional['Where'] => Stdlib::Unixpath, + Optional['Type'] => String[1], + Optional['Options'] => String[1], + Optional['SloppyOptions'] => Boolean, + Optional['LazyUnmount'] => Boolean, + Optional['ReadWriteOnly'] => Boolean, + Optional['ForceUnmount'] => Boolean, + Optional['DirectoryMode'] => Stdlib::Filemode, + Optional['TimeoutSec'] => String[0], + }] +``` + ### `Systemd::Unit::Path` Possible keys for the [Path] section of a unit file diff --git a/manifests/manage_dropin.pp b/manifests/manage_dropin.pp index 140c79bb..8df9da9c 100644 --- a/manifests/manage_dropin.pp +++ b/manifests/manage_dropin.pp @@ -88,6 +88,7 @@ # @param timer_entry key value pairs for [Timer] section of the unit file # @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 # define systemd::manage_dropin ( Systemd::Unit $unit, @@ -108,6 +109,7 @@ Optional[Systemd::Unit::Timer] $timer_entry = undef, Optional[Systemd::Unit::Path] $path_entry = undef, Optional[Systemd::Unit::Socket] $socket_entry = undef, + Optional[Systemd::Unit::Mount] $mount_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") @@ -125,6 +127,10 @@ fail("Systemd::Manage_dropin[${name}]: for unit ${unit} slice_entry is only valid for slice units") } + if $mount_entry and $unit !~ Pattern['^[^/]+\.mount'] { + fail("Systemd::Manage_dropin[${name}]: for unit ${unit} mount_entry is only valid for mount units") + } + systemd::dropin_file { $name: ensure => $ensure, filename => $filename, @@ -145,6 +151,7 @@ 'timer_entry' => $timer_entry, 'path_entry' => $path_entry, 'socket_entry' => $socket_entry, + 'mount_entry' => $mount_entry, }), } } diff --git a/manifests/manage_unit.pp b/manifests/manage_unit.pp index 51e7d063..c406a5ca 100644 --- a/manifests/manage_unit.pp +++ b/manifests/manage_unit.pp @@ -63,6 +63,27 @@ # }, # } # +# @example Mount a Filesystem and Use for a Service +# systemd::manage_unit { 'var-lib-sss-db.mount': +# ensure => present, +# unit_entry => { +# 'Description' => 'Mount sss tmpfs db', +# }, +# mount_entry => { +# 'What' => 'tmpfs', +# 'Where' => '/var/lib/sss/db', +# 'Type' => 'tmpfs', +# 'Options' => 'size=300M,mode=0700,uid=sssd,gid=sssd,rootcontext=system_u:object_r:sssd_var_lib_t:s0', +# }, +# } +# systemd::manage_dropin { 'tmpfs-db.conf': +# ensure => present, +# unit => 'sssd.service', +# unit_entry => { +# 'RequiresMountsFor' => '/var/lib/sss/db', +# }, +# } +# # @example Remove a unit file # systemd::manage_unit { 'my.service': # ensure => 'absent', @@ -96,6 +117,7 @@ # @param timer_entry key value pairs for [Timer] section of the unit file # @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. # define systemd::manage_unit ( Enum['present', 'absent'] $ensure = 'present', @@ -118,6 +140,7 @@ Optional[Systemd::Unit::Timer] $timer_entry = undef, Optional[Systemd::Unit::Path] $path_entry = undef, Optional[Systemd::Unit::Socket] $socket_entry = undef, + Optional[Systemd::Unit::Mount] $mount_entry = undef, ) { assert_type(Systemd::Unit, $name) @@ -137,6 +160,10 @@ fail("Systemd::Manage_unit[${name}]: slice_entry is only valid for slice units") } + if $mount_entry and $name !~ Pattern['^[^/]+\.mount'] { + fail("Systemd::Manage_unit[${name}]: mount_entry is only valid for mount units") + } + if $ensure != 'absent' and $name =~ Pattern['^[^/]+\.service'] and !$service_entry { fail("Systemd::Manage_unit[${name}]: service_entry is required for service units") } @@ -162,6 +189,7 @@ 'timer_entry' => $timer_entry, 'path_entry' => $path_entry, 'socket_entry' => $socket_entry, + 'mount_entry' => $mount_entry, }), } } diff --git a/spec/defines/manage_dropin_spec.rb b/spec/defines/manage_dropin_spec.rb index fcf333c9..08ff4791 100644 --- a/spec/defines/manage_dropin_spec.rb +++ b/spec/defines/manage_dropin_spec.rb @@ -153,6 +153,25 @@ } end + context 'on a mount' do + let(:params) do + { + unit: 'var-lib-sss-db.mount', + mount_entry: { + 'SloppyOptions' => true, + } + } + end + + it { is_expected.to compile.with_all_deps } + + it { + is_expected.to contain_systemd__dropin_file('foobar.conf'). + with_unit('var-lib-sss-db.mount'). + with_content(%r{^SloppyOptions=true$}) + } + end + context 'on a slice' do let(:params) do { diff --git a/spec/defines/manage_unit_spec.rb b/spec/defines/manage_unit_spec.rb index fb404b37..0e283030 100644 --- a/spec/defines/manage_unit_spec.rb +++ b/spec/defines/manage_unit_spec.rb @@ -99,6 +99,34 @@ end end + context 'on a mount' do + let(:title) { 'var-lib-sss-db.mount' } + + let(:params) do + { + unit_entry: { + Description: 'Mount sssd dir', + }, + mount_entry: { + 'What' => 'tmpfs', + 'Where' => '/var/lib/sss/db', + 'Type' => 'tmpfs', + 'Options' => 'size=300M', + }, + } + end + + it { is_expected.to compile.with_all_deps } + + it { + is_expected.to contain_systemd__unit_file('var-lib-sss-db.mount'). + with_content(%r{^\[Mount\]$}). + with_content(%r{^What=tmpfs$}). + with_content(%r{^Where=/var/lib/sss/db$}). + with_content(%r{^Options=size=300M$}) + } + end + context 'on a timer' do let(:title) { 'winter.timer' } diff --git a/spec/type_aliases/systemd_unit_mount_spec.rb b/spec/type_aliases/systemd_unit_mount_spec.rb new file mode 100644 index 00000000..76e0437e --- /dev/null +++ b/spec/type_aliases/systemd_unit_mount_spec.rb @@ -0,0 +1,42 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'Systemd::Unit::Mount' 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' => 'nfs://example.org/exports/home' }) } + it { is_expected.to allow_value({ 'What' => '/dev/vda1' }) } + end + + context 'with a key of Where can have a path to mount on' do + it { is_expected.to allow_value({ 'Where' => '/mnt/foo' }) } + it { is_expected.to allow_value({ 'Where' => '/mnt/foo/file.txt' }) } + end + + context 'with a key of Type can have a path to mount on' do + it { is_expected.to allow_value({ 'Type' => 'tmpfs' }) } + it { is_expected.to allow_value({ 'Type' => 'ext2' }) } + end + + context 'with a key of Options can have a path to mount on' do + it { is_expected.to allow_value({ 'Options' => 'size=300M,mode=0700,uid=sssd,gid=sssd,root' }) } + end + + context 'with a key of DirectoryMode can have a mode of' do + it { is_expected.to allow_value({ 'DirectoryMode' => '0700' }) } + 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 + + %w[SloppyOptions LazyUnmount ReadWriteOnly ForceUnmount].each do |assert| + context "with a key of #{assert} can have values of a path" do + it { is_expected.to allow_value({ assert => false }) } + it { is_expected.to allow_value({ assert => true }) } + end + end +end diff --git a/templates/unit_file.epp b/templates/unit_file.epp index 483281f0..59cfa7ec 100644 --- a/templates/unit_file.epp +++ b/templates/unit_file.epp @@ -6,6 +6,7 @@ Optional[Hash] $timer_entry, Optional[Hash] $path_entry, Optional[Hash] $socket_entry, + Optional[Hash] $mount_entry, | -%> <%- @@ -20,6 +21,7 @@ 'Path', 'Socket', 'Install', + 'Mount', ] # Directives which are pair of items to be expressed as a space seperated pair. diff --git a/types/unit/mount.pp b/types/unit/mount.pp new file mode 100644 index 00000000..5a9cf24c --- /dev/null +++ b/types/unit/mount.pp @@ -0,0 +1,17 @@ +# @summary Possible keys for the [Mount] section of a unit file +# @see https://www.freedesktop.org/software/systemd/man/latest/systemd.mount.html +# +type Systemd::Unit::Mount = Struct[ + { + Optional['What'] => String[1], + Optional['Where'] => Stdlib::Unixpath, + Optional['Type'] => String[1], + Optional['Options'] => String[1], + Optional['SloppyOptions'] => Boolean, + Optional['LazyUnmount'] => Boolean, + Optional['ReadWriteOnly'] => Boolean, + Optional['ForceUnmount'] => Boolean, + Optional['DirectoryMode'] => Stdlib::Filemode, + Optional['TimeoutSec'] => String[0], + } +]