diff --git a/README.md b/README.md index c4091e0..ae179ba 100644 --- a/README.md +++ b/README.md @@ -1,382 +1,369 @@ # Systemd [![Puppet Forge](http://img.shields.io/puppetforge/v/camptocamp/systemd.svg)](https://forge.puppetlabs.com/camptocamp/systemd) [![Puppet Forge Downloads](http://img.shields.io/puppetforge/dt/camptocamp/systemd.svg)](https://forge.puppetlabs.com/camptocamp/systemd) [![Build Status](https://travis-ci.org/camptocamp/puppet-systemd.png?branch=master)](https://travis-ci.org/camptocamp/puppet-systemd) [![Puppet Forge Endorsement](https://img.shields.io/puppetforge/e/camptocamp/systemd.svg)](https://forge.puppetlabs.com/camptocamp/systemd) [![By Camptocamp](https://img.shields.io/badge/by-camptocamp-fb7047.svg)](http://www.camptocamp.com) ## Overview This module declares exec resources to create global sync points for reloading systemd. **Version 2 and newer of the module don't work with Hiera 3! You need to migrate your existing Hiera setup to Hiera 5** ## Usage and examples There are two ways to use this module. ### unit files -Let this module handle file creation and systemd reloading. +Let this module handle file creation. ```puppet systemd::unit_file { 'foo.service': source => "puppet:///modules/${module_name}/foo.service", } ~> service {'foo': ensure => 'running', } ``` -Or handle file creation yourself and trigger systemd. +This is equivalent to: ```puppet -include systemd::systemctl::daemon_reload - file { '/usr/lib/systemd/system/foo.service': ensure => file, owner => 'root', group => 'root', mode => '0644', source => "puppet:///modules/${module_name}/foo.service", } -~> Class['systemd::systemctl::daemon_reload'] - -service {'foo': - ensure => 'running', - subscribe => File['/usr/lib/systemd/system/foo.service'], +~> service {'foo': + ensure => 'running', } ``` You can also use this module to more fully manage the new unit. This example deploys the unit, reloads systemd and then enables and starts it. ```puppet systemd::unit_file { 'foo.service': source => "puppet:///modules/${module_name}/foo.service", enable => true, active => true, } ``` ### drop-in files Drop-in files are used to add or alter settings of a unit without modifying the unit itself. As for the unit files, the module can handle the file and -directory creation and systemd reloading: +directory creation: ```puppet systemd::dropin_file { 'foo.conf': unit => 'foo.service', source => "puppet:///modules/${module_name}/foo.conf", } ~> service {'foo': ensure => 'running', } ``` -Or handle file and directory creation yourself and trigger systemd: +This is equivalent to: ```puppet -include systemd::systemctl::daemon_reload - file { '/etc/systemd/system/foo.service.d': ensure => directory, owner => 'root', group => 'root', } file { '/etc/systemd/system/foo.service.d/foo.conf': ensure => file, owner => 'root', group => 'root', mode => '0644', source => "puppet:///modules/${module_name}/foo.conf", } -~> Class['systemd::systemctl::daemon_reload'] - -service {'foo': - ensure => 'running', - subscribe => File['/etc/systemd/system/foo.service.d/foo.conf'], +~> service {'foo': + ensure => 'running', } ``` -Sometimes it's desirable to reload the systemctl daemon before a service is refreshed (for example: -when overriding `ExecStart` or adding environment variables to the drop-in file). In that case, -use `daemon_reload => 'eager'` instead of the default `'lazy'`. Be aware that the daemon could be -reloaded multiple times if you have multiple `systemd::dropin_file` resources and any one of them -is using `'eager'`. - dropin-files can also be generated via hiera: ```yaml - systemd::dropin_files: my-foo.conf: unit: foo.service source: puppet:///modules/${module_name}/foo.conf - ``` ### tmpfiles Let this module handle file creation and systemd reloading ```puppet systemd::tmpfile { 'foo.conf': source => "puppet:///modules/${module_name}/foo.conf", } ``` Or handle file creation yourself and trigger systemd. ```puppet include systemd::tmpfiles file { '/etc/tmpfiles.d/foo.conf': ensure => file, owner => 'root', group => 'root', mode => '0644', source => "puppet:///modules/${module_name}/foo.conf", } ~> Class['systemd::tmpfiles'] ``` ### timer units Create a systemd timer unit and a systemd service unit to execute from that timer The following will create a timer unit and a service unit file. -The execution of `systemctl daemon-reload` will occur. When `active` and `enable` are set to `true` the puppet service `runoften.timer` will be declared, started and enabled. ```puppet systemd::timer{'runoften.timer': timer_source => "puppet:///modules/${module_name}/runoften.timer", service_source => "puppet:///modules/${module_name}/runoften.service", active => true, enable => true, } ``` A trivial daily run. In this case enable and active are both unset and so the service `daily.timer` is not declared by the `systemd::timer` type. ```puppet $_timer = @(EOT) [Timer] OnCalendar=daily RandomizedDelaySec=1d EOT $_service = @(EOT) [Service] Type=oneshot ExecStart=/usr/bin/touch /tmp/file EOT systemd::timer{'daily.timer': timer_content => $_timer, service_content => $_service, } service{'daily.timer': ensure => running, subscribe => Systemd::Timer['daily.timer'], } ``` If neither `service_content` or `service_source` are specified then no service unit will be created. The service unit name can also be specified. ```puppet $_timer = @(EOT) [Timer] OnCalendar=daily RandomizedDelaySec=1d Unit=touch-me-today.service EOT $_service = @(EOT) [Service] Type=oneshot ExecStart=/usr/bin/touch /tmp/file EOT systemd::timer{'daily.timer': timer_content => $_timer, service_unit => 'touch-me-today.service', service_content => $_service, active => true, enable => true, } ``` ### service limits Manage soft and hard limits on various resources for executed processes. ```puppet systemd::service_limits { 'foo.service': limits => { 'LimitNOFILE' => 8192, 'LimitNPROC' => 16384, } } ``` Or provide the configuration file yourself. Systemd reloading and restarting of the service are handled by the module. ```puppet systemd::service_limits { 'foo.service': source => "puppet:///modules/${module_name}/foo.conf", } ``` +### Daemon reloads + +Systemd caches unit files and their relations. This means it needs to reload, typically done via `systemctl daemon-reload`. Since Puppet 6.1.0 ([PUP-3483](https://tickets.puppetlabs.com/browse/PUP-3483)) takes care of this by calling `systemctl show $SERVICE -- --property=NeedDaemonReload` to determine if a reload is needed. Typically this works well and removes the need for `systemd::systemctl::daemon_reload` as provided prior to camptocamp/systemd 3.0.0. This avoids common circular dependencies. + +It does contain a workaround for [PUP-9473](https://tickets.puppetlabs.com/browse/PUP-9473) but there's no guarantee that this works in every case. + ### network systemd-networkd is able to manage your network configuration. We provide a defined resource which can write the interface configurations. systemd-networkd needs to be restarted to apply the configs. The defined resource can do this for you: ```puppet systemd::network{'eth0.network': source => "puppet:///modules/${module_name}/eth0.network", restart_service => true, } ``` ### Services Systemd provides multiple services. Currently you can manage `systemd-resolved`, `systemd-timesyncd`, `systemd-networkd`, `systemd-journald` and `systemd-logind` via the main class: ```puppet class{'systemd': manage_resolved => true, manage_networkd => true, manage_timesyncd => true, manage_journald => true, manage_udevd => true, manage_logind => true, } ``` $manage_networkd is required if you want to reload it for new `systemd::network` resources. Setting $manage_resolved will also manage your `/etc/resolv.conf`. When configuring `systemd::resolved` you could set `dns_stub_resolver` to false (default) to use a *standard* `/etc/resolved.conf`, or you could set it to `true` to use the local resolver provided by `systemd-resolved`. Systemd has introduced `DNS Over TLS` in the release 239. Currently two states are supported `no` and `opportunistic`. When enabled with `opportunistic` `systemd-resolved` will start a TCP-session to a DNS server with `DNS Over TLS` support. Note that there will be no host checking for `DNS Over TLS` due to missing implementation in `systemd-resolved`. It is possible to configure the default ntp servers in `/etc/systemd/timesyncd.conf`: ```puppet class{'systemd': manage_timesyncd => true, ntp_server => ['0.pool.ntp.org', '1.pool.ntp.org'], fallback_ntp_server => ['2.pool.ntp.org', '3.pool.ntp.org'], } ``` This requires [puppetlabs-inifile](https://forge.puppet.com/puppetlabs/inifile), which is only a soft dependency in this module (you need to explicitly install it). Both parameters accept a string or an array. ### Resource Accounting Systemd has support for different accounting option. It can track CPU/Memory/Network stats per process. This is explained in depth at [systemd-system.conf](https://www.freedesktop.org/software/systemd/man/systemd-system.conf.html). This defaults to off (default on most operating systems). You can enable this with the `$manage_accounting` parameter. The module provides a default set of working accounting options per operating system, but you can still modify them with `$accounting`: ```puppet class{'systemd': manage_accounting => true, accounting => { 'DefaultCPUAccounting' => 'yes', 'DefaultMemoryAccounting' => 'no', } } ``` ### 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. ```yaml systemd::journald_settings: Storage: auto MaxRetentionSec: 5day MaxLevelStore: ensure: absent ``` ### udevd configuration It allows you to manage the udevd configuration. You can set the udev.conf values via the `udev_log`, `udev_children_max`, `udev_exec_delay`, `udev_event_timeout`, `udev_resolve_names`, and `udev_timeout_signal` parameters. Additionally you can set custom udev rules with the `udev_rules` parameter. ```puppet class { 'systemd': manage_udevd => true, udev_rules => { 'example_raw.rules' => { 'rules' => [ 'ACTION=="add", KERNEL=="sda", RUN+="/bin/raw /dev/raw/raw1 %N"', 'ACTION=="add", KERNEL=="sdb", RUN+="/bin/raw /dev/raw/raw2 %N"', ], }, }, } ``` ### udev::rules configuration Custom udev rules can be defined for specific events. ```yaml systemd::udev::rule: ensure: present path: /etc/udev/rules.d selinux_ignore_defaults: false notify: "Service[systemd-udevd']" rules: - 'ACTION=="add", KERNEL=="sda", RUN+="/bin/raw /dev/raw/raw1 %N"' - 'ACTION=="add", KERNEL=="sdb", RUN+="/bin/raw /dev/raw/raw2 %N"', ``` ### logind configuration It also allows you to manage logind settings. You can manage logind settings through setting the `logind_settings` parameter. If you want a parameter to be removed, you can pass its value as params. ```yaml systemd::logind_settings: HandleSuspendKey: 'ignore' KillUserProcesses: 'no' RemoveIPC: ensure: absent UserTasksMax: 10000 ``` ### User linger A `loginctl_user` resource is available to manage user linger enablement: ```puppet loginctl_user { 'foo': linger => enabled, } ``` or as a hash via the `systemd::loginctl_users` parameter. diff --git a/REFERENCE.md b/REFERENCE.md index 1a06c26..1a03a37 100644 --- a/REFERENCE.md +++ b/REFERENCE.md @@ -1,1015 +1,1002 @@ # Reference ## Table of Contents ### Classes #### Public Classes * [`systemd`](#systemd): This module allows triggering systemd commands once for all modules -* [`systemd::systemctl::daemon_reload`](#systemdsystemctldaemon_reload): Reload the systemctl daemon * [`systemd::tmpfiles`](#systemdtmpfiles): Update the systemd temp files #### Private Classes * `systemd::journald`: This class manages and configures journald. https://www.freedesktop.org/software/systemd/man/journald.conf.html * `systemd::logind`: This class manages systemd's login manager configuration. https://www.freedesktop.org/software/systemd/man/logind.conf.html * `systemd::networkd`: This class provides an abstract way to trigger systemd-networkd * `systemd::resolved`: This class provides an abstract way to trigger resolved. Each parameters correspond to resolved.conf(5): https://www.freedesktop.org/software * `systemd::system`: This class provides a solution to enable accounting * `systemd::timesyncd`: This class provides an abstract way to trigger systemd-timesyncd ### Defined types * [`systemd::dropin_file`](#systemddropin_file): Creates a drop-in file for a systemd unit * [`systemd::network`](#systemdnetwork): -- Define: systemd::network Creates network config for systemd-networkd * [`systemd::service_limits`](#systemdservice_limits): Adds a set of custom limits to the service * Mutually exclusive with ``$limits`` * [`systemd::timer`](#systemdtimer): Create a timer and optionally a service unit to execute with the timer unit * [`systemd::tmpfile`](#systemdtmpfile): Creates a systemd tmpfile * Mutually exclusive with ``$limits`` * [`systemd::unit_file`](#systemdunit_file): Creates a systemd unit file ### Resource types * [`loginctl_user`](#loginctl_user): An arbitrary name used as the identity of the resource. ### Data types * [`Systemd::Dropin`](#systemddropin) * [`Systemd::JournaldSettings`](#systemdjournaldsettings): Matches Systemd journald config Struct * [`Systemd::JournaldSettings::Ensure`](#systemdjournaldsettingsensure) * [`Systemd::LogindSettings`](#systemdlogindsettings): Matches Systemd Login Manager Struct * [`Systemd::LogindSettings::Ensure`](#systemdlogindsettingsensure) * [`Systemd::ServiceLimits`](#systemdservicelimits): Matches Systemd Service Limit Struct * [`Systemd::Unit`](#systemdunit) ## Classes ### `systemd` This module allows triggering systemd commands once for all modules #### Parameters The following parameters are available in the `systemd` class. ##### `service_limits` Data type: `Hash[String,Hash[String, Any]]` May be passed a resource hash suitable for passing directly into the ``create_resources()`` function as called on ``systemd::service_limits`` ##### `manage_resolved` Data type: `Boolean` Manage the systemd resolver ##### `resolved_ensure` Data type: `Enum['stopped','running']` The state that the ``resolved`` service should be in ##### `dns` Data type: `Optional[Variant[Array[String],String]]` A space-separated list of IPv4 and IPv6 addresses to use as system DNS servers. DNS requests are sent to one of the listed DNS servers in parallel to suitable per-link DNS servers acquired from systemd-networkd.service(8) or set at runtime by external applications. requires puppetlabs-inifile ##### `fallback_dns` Data type: `Optional[Variant[Array[String],String]]` A space-separated list of IPv4 and IPv6 addresses to use as the fallback DNS servers. Any per-link DNS servers obtained from systemd-networkd take precedence over this setting. requires puppetlabs-inifile ##### `domains` Data type: `Optional[Variant[Array[String],String]]` A space-separated list of domains host names or IP addresses to be used systemd-resolved take precedence over this setting. ##### `llmnr` Data type: `Optional[Variant[Boolean,Enum['resolve']]]` Takes a boolean argument or "resolve". ##### `multicast_dns` Data type: `Optional[Variant[Boolean,Enum['resolve']]]` Takes a boolean argument or "resolve". ##### `dnssec` Data type: `Optional[Variant[Boolean,Enum['allow-downgrade']]]` Takes a boolean argument or "allow-downgrade". ##### `dnsovertls` Data type: `Optional[Variant[Boolean,Enum['opportunistic', 'no']]]` Takes a boolean argument or "opportunistic" ##### `cache` Data type: `Boolean` Takes a boolean argument. ##### `dns_stub_listener` Data type: `Optional[Variant[Boolean,Enum['udp','tcp']]]` Takes a boolean argument or one of "udp" and "tcp". ##### `use_stub_resolver` Data type: `Boolean` Takes a boolean argument. When "false" (default) it uses /var/run/systemd/resolve/resolv.conf as /etc/resolv.conf. When "true", it uses /var/run/systemd/resolve/stub-resolv.conf ##### `manage_networkd` Data type: `Boolean` Manage the systemd network daemon ##### `networkd_ensure` Data type: `Enum['stopped','running']` The state that the ``networkd`` service should be in ##### `manage_timesyncd` Data type: `Boolean` Manage the systemd tiemsyncd daemon ##### `timesyncd_ensure` Data type: `Enum['stopped','running']` The state that the ``timesyncd`` service should be in ##### `ntp_server` Data type: `Optional[Variant[Array,String]]` comma separated list of ntp servers, will be combined with interface specific addresses from systemd-networkd. requires puppetlabs-inifile ##### `fallback_ntp_server` Data type: `Optional[Variant[Array,String]]` A space-separated list of NTP server host names or IP addresses to be used as the fallback NTP servers. Any per-interface NTP servers obtained from systemd-networkd take precedence over this setting. requires puppetlabs-inifile ##### `manage_journald` Data type: `Boolean` Manage the systemd journald ##### `journald_settings` Data type: `Systemd::JournaldSettings` Config Hash that is used to configure settings in journald.conf ##### `manage_logind` Data type: `Boolean` Manage the systemd logind ##### `logind_settings` Data type: `Systemd::LogindSettings` Config Hash that is used to configure settings in logind.conf ##### `loginctl_users` Data type: `Hash` Config Hash that is used to generate instances of our type `loginctl_user`. Default value: `{}` ##### `dropin_files` Data type: `Hash` Configure dropin files via hiera with factory pattern Default value: `{}` ##### `manage_accounting` Data type: `Boolean` ##### `accounting` Data type: `Hash[String,String]` ##### `purge_dropin_dirs` Data type: `Boolean` -### `systemd::systemctl::daemon_reload` - -Reload the systemctl daemon - ### `systemd::tmpfiles` Update the systemd temp files * **See also** * systemd-tmpfiles(8) #### Parameters The following parameters are available in the `systemd::tmpfiles` class. ##### `operations` Data type: `Array[Enum['create','clean','remove']]` The operations to perform on the systemd tempfiles * All operations may be combined but you'll probably only ever want to use ``create`` Default value: `['create']` ## Defined types ### `systemd::dropin_file` Creates a drop-in file for a systemd unit * **See also** * systemd.unit(5) #### Parameters The following parameters are available in the `systemd::dropin_file` defined type. ##### `unit` Data type: `Systemd::Unit` ##### `filename` Data type: `Systemd::Dropin` Default value: `$name` ##### `ensure` Data type: `Enum['present', 'absent', 'file']` Default value: `'present'` ##### `path` Data type: `Stdlib::Absolutepath` Default value: `'/etc/systemd/system'` ##### `selinux_ignore_defaults` Data type: `Optional[Boolean]` Default value: ``false`` ##### `content` Data type: `Optional[Variant[String,Sensitive[String]]]` Default value: ``undef`` ##### `source` Data type: `Optional[String]` Default value: ``undef`` ##### `target` Data type: `Optional[Stdlib::Absolutepath]` Default value: ``undef`` ##### `owner` Data type: `String` Default value: `'root'` ##### `group` Data type: `String` Default value: `'root'` ##### `mode` Data type: `String` Default value: `'0444'` ##### `show_diff` Data type: `Boolean` Default value: ``true`` -##### `daemon_reload` - -Data type: `Enum['lazy', 'eager']` - - - -Default value: `'lazy'` - ### `systemd::network` -- Define: systemd::network Creates network config for systemd-networkd #### Parameters The following parameters are available in the `systemd::network` defined type. ##### `ensure` Data type: `Enum['file', 'absent']` Default value: `file` ##### `path` Data type: `Stdlib::Absolutepath` Default value: `'/etc/systemd/network'` ##### `content` Data type: `Optional[String]` Default value: ``undef`` ##### `source` Data type: `Optional[String]` Default value: ``undef`` ##### `target` Data type: `Optional[Stdlib::Absolutepath]` Default value: ``undef`` ##### `owner` Data type: `String` Default value: `'root'` ##### `group` Data type: `String` Default value: `'root'` ##### `mode` Data type: `String` Default value: `'0444'` ##### `show_diff` Data type: `Boolean` Default value: ``true`` ##### `restart_service` Data type: `Boolean` Default value: ``true`` ### `systemd::service_limits` Adds a set of custom limits to the service * Mutually exclusive with ``$limits`` * **See also** * systemd.exec(5) #### Parameters The following parameters are available in the `systemd::service_limits` defined type. ##### `$ensure` Whether to drop a file or remove it ##### `path` Data type: `Stdlib::Absolutepath` The path to the main systemd settings directory Default value: `'/etc/systemd/system'` ##### `selinux_ignore_defaults` Data type: `Optional[Boolean]` If Puppet should ignore the default SELinux labels. Default value: ``false`` ##### `limits` Data type: `Optional[Systemd::ServiceLimits]` A Hash of service limits matching the settings in ``systemd.exec(5)`` * Mutually exclusive with ``$source`` Default value: ``undef`` ##### `source` Data type: `Optional[String]` A ``File`` resource compatible ``source`` Default value: ``undef`` ##### `restart_service` Data type: `Boolean` Restart the managed service after setting the limits Default value: ``true`` ##### `ensure` Data type: `Enum['present', 'absent', 'file']` Default value: `'present'` ### `systemd::timer` Create a timer and optionally a service unit to execute with the timer unit * **See also** * https://www.freedesktop.org/software/systemd/man/systemd.timer.html * systemd.timer(5) #### Parameters The following parameters are available in the `systemd::timer` defined type. ##### `name` Data type: `Pattern['^.+\.timer$]` The target of the timer unit to create ##### `path` Data type: `Stdlib::Absolutepath` The main systemd configuration path Default value: `'/etc/systemd/system'` ##### `timer_content` Data type: `Optional[String[1]]` The full content of the timer unit file * Mutually exclusive with ``$timer_source`` Default value: ``undef`` ##### `timer_source` Data type: `Optional[String[1]]` The ``File`` resource compatible ``source`` * Mutually exclusive with ``$timer_content`` Default value: ``undef`` ##### `service_content` Data type: `Optional[String[1]]` The full content of the service unit file * Mutually exclusive with ``$service_source`` Default value: ``undef`` ##### `service_source` Data type: `Optional[String[1]]` The ``File`` resource compatible ``source`` * Mutually exclusive with ``$service_content`` Default value: ``undef`` ##### `owner` Data type: `String[1]` The owner to set on the dropin file Default value: `'root'` ##### `group` Data type: `String[1]` The group to set on the dropin file Default value: `'root'` ##### `mode` Data type: `Stdlib::Filemode` The mode to set on the dropin file Default value: `'0444'` ##### `show_diff` Data type: `Boolean` Whether to show the diff when updating dropin file Default value: ``true`` ##### `service_unit` Data type: `Optional[Systemd::Unit]` If set then the service_unit will have this name. If not set the service unit has the same name as the timer unit with s/.timer/.service/ Default value: ``undef`` ##### `active` Data type: `Optional[Boolean]` If set to true or false the timer service will be maintained. If true the timer service will be running and enabled, if false it will explictly stopped and disabled. Default value: ``undef`` ##### `enable` Data type: `Optional[Variant[Boolean, Enum['mask']]]` If set, will manage the state of the unit. Default value: ``undef`` ##### `ensure` Data type: `Enum['present', 'absent', 'file']` Default value: `'present'` ### `systemd::tmpfile` Creates a systemd tmpfile * Mutually exclusive with ``$limits`` * **See also** * systemd-tmpfiles(8) #### Parameters The following parameters are available in the `systemd::tmpfile` defined type. ##### `$ensure` Whether to drop a file or remove it ##### `path` Data type: `Stdlib::Absolutepath` The path to the main systemd tmpfiles directory Default value: `'/etc/tmpfiles.d'` ##### `content` Data type: `Optional[String]` The literal content to write to the file * Mutually exclusive with ``$source`` Default value: ``undef`` ##### `source` Data type: `Optional[String]` A ``File`` resource compatible ``source`` Default value: ``undef`` ##### `ensure` Data type: `Enum['present', 'absent', 'file']` Default value: `'file'` ##### `filename` Data type: `Systemd::Dropin` Default value: `$name` ### `systemd::unit_file` Creates a systemd unit file * **See also** * systemd.unit(5) #### Parameters The following parameters are available in the `systemd::unit_file` defined type. ##### `name` Data type: `Pattern['^[^/]+\.(service|socket|device|mount|automount|swap|target|path|timer|slice|scope)$']` The target unit file to create ##### `ensure` Data type: `Enum['present', 'absent', 'file']` The state of the unit file to ensure Default value: `'present'` ##### `path` Data type: `Stdlib::Absolutepath` The main systemd configuration path Default value: `'/etc/systemd/system'` ##### `content` Data type: `Optional[String]` The full content of the unit file * Mutually exclusive with ``$source`` Default value: ``undef`` ##### `source` Data type: `Optional[String]` The ``File`` resource compatible ``source`` * Mutually exclusive with ``$content`` Default value: ``undef`` ##### `target` Data type: `Optional[Stdlib::Absolutepath]` If set, will force the file to be a symlink to the given target * Mutually exclusive with both ``$source`` and ``$content`` Default value: ``undef`` ##### `owner` Data type: `String` The owner to set on the unit file Default value: `'root'` ##### `group` Data type: `String` The group to set on the unit file Default value: `'root'` ##### `mode` Data type: `String` The mode to set on the unit file Default value: `'0444'` ##### `show_diff` Data type: `Boolean` Whether to show the diff when updating unit file Default value: ``true`` ##### `enable` Data type: `Optional[Variant[Boolean, Enum['mask']]]` If set, will manage the unit enablement status. Default value: ``undef`` ##### `active` Data type: `Optional[Boolean]` If set, will manage the state of the unit. Default value: ``undef`` ## Resource types ### `loginctl_user` An arbitrary name used as the identity of the resource. #### Properties The following properties are available in the `loginctl_user` type. ##### `linger` Valid values: `enabled`, `disabled` Whether linger is enabled for the user. Default value: `disabled` #### Parameters The following parameters are available in the `loginctl_user` type. ##### `name` namevar An arbitrary name used as the identity of the resource. ##### `provider` The specific backend to use for this `loginctl_user` resource. You will seldom need to specify this --- Puppet will usually discover the appropriate provider for your platform. ## Data types ### `Systemd::Dropin` The Systemd::Dropin data type. Alias of `Pattern['^[^/]+\.conf$']` ### `Systemd::JournaldSettings` Matches Systemd journald config Struct Alias of `Struct[{ Optional['Storage'] => Variant[Enum['volatile','persistent','auto','none'],Systemd::JournaldSettings::Ensure], Optional['Compress'] => Variant[Enum['yes','no'], Pattern[/^[0-9]+(K|M|G)?$/],Systemd::JournaldSettings::Ensure], Optional['Seal'] => Variant[Enum['yes','no'],Systemd::JournaldSettings::Ensure], Optional['SplitMode'] => Variant[Enum['uid','none'],Systemd::JournaldSettings::Ensure], Optional['RateLimitInterval'] => Variant[Pattern[/^[0-9]+(s|min|h|ms|us)?$/],Systemd::JournaldSettings::Ensure], Optional['RateLimitIntervalSec'] => Variant[Pattern[/^[0-9]+(s|min|h|ms|us)?$/],Systemd::JournaldSettings::Ensure], Optional['RateLimitBurst'] => Variant[Integer[0], Pattern[/^[0-9]+$/],Systemd::JournaldSettings::Ensure], Optional['SystemMaxUse'] => Variant[Pattern[/^[0-9]+(K|M|G|T|P|E)?$/],Systemd::JournaldSettings::Ensure], Optional['SystemKeepFree'] => Variant[Pattern[/^[0-9]+(K|M|G|T|P|E)?$/],Systemd::JournaldSettings::Ensure], Optional['SystemMaxFileSize'] => Variant[Pattern[/^[0-9]+(K|M|G|T|P|E)?$/],Systemd::JournaldSettings::Ensure], Optional['SystemMaxFiles'] => Variant[Integer[0], Pattern[/^[0-9]+$/],Systemd::JournaldSettings::Ensure], Optional['RuntimeMaxUse'] => Variant[Pattern[/^[0-9]+(K|M|G|T|P|E)?$/],Systemd::JournaldSettings::Ensure], Optional['RuntimeKeepFree'] => Variant[Pattern[/^[0-9]+(K|M|G|T|P|E)?$/],Systemd::JournaldSettings::Ensure], Optional['RuntimeMaxFileSize'] => Variant[Pattern[/^[0-9]+(K|M|G|T|P|E)?$/],Systemd::JournaldSettings::Ensure], Optional['RuntimeMaxFiles'] => Variant[Integer[0], Pattern[/^[0-9]+$/],Systemd::JournaldSettings::Ensure], Optional['MaxFileSec'] => Variant[Pattern[/^[0-9]+(year|month|week|day|h|m)?$/],Systemd::JournaldSettings::Ensure], Optional['MaxRetentionSec'] => Variant[Pattern[/^[0-9]+(year|month|week|day|h|m)?$/],Systemd::JournaldSettings::Ensure], Optional['SyncIntervalSec'] => Variant[Pattern[/^[0-9]+(year|month|week|day|h|m)?$/],Systemd::JournaldSettings::Ensure], Optional['ForwardToSyslog'] => Variant[Enum['yes','no'],Systemd::JournaldSettings::Ensure], Optional['ForwardToKMsg'] => Variant[Enum['yes','no'],Systemd::JournaldSettings::Ensure], Optional['ForwardToConsole'] => Variant[Enum['yes','no'],Systemd::JournaldSettings::Ensure], Optional['ForwardToWall'] => Variant[Enum['yes','no'],Systemd::JournaldSettings::Ensure], Optional['MaxLevelStore'] => Variant[Enum['emerg','alert','crit','err','warning','notice','info','debug'],Integer[0,7],Systemd::JournaldSettings::Ensure], Optional['MaxLevelSyslog'] => Variant[Enum['emerg','alert','crit','err','warning','notice','info','debug'],Integer[0,7],Systemd::JournaldSettings::Ensure], Optional['MaxLevelKMsg'] => Variant[Enum['emerg','alert','crit','err','warning','notice','info','debug'],Integer[0,7],Systemd::JournaldSettings::Ensure], Optional['MaxLevelConsole'] => Variant[Enum['emerg','alert','crit','err','warning','notice','info','debug'],Integer[0,7],Systemd::JournaldSettings::Ensure], Optional['MaxLevelWall'] => Variant[Enum['emerg','alert','crit','err','warning','notice','info','debug'],Integer[0,7],Systemd::JournaldSettings::Ensure], Optional['ReadKMsg'] => Variant[Enum['yes','no'],Systemd::JournaldSettings::Ensure], Optional['TTYPath'] => Variant[Stdlib::Absolutepath,Systemd::JournaldSettings::Ensure], Optional['LineMax'] => Variant[Pattern[/^[0-9]+(K|M|G|T)?$/],Systemd::JournaldSettings::Ensure], }]` ### `Systemd::JournaldSettings::Ensure` The Systemd::JournaldSettings::Ensure data type. Alias of `Struct[{ 'ensure' => Enum['present','absent'] }]` ### `Systemd::LogindSettings` Matches Systemd Login Manager Struct Alias of `Struct[{ Optional['HandleHibernateKey'] => Variant[Enum['ignore','poweroff','reboot','halt','kexec','suspend','hibernate','hybrid-sleep','suspend-then-hibernate','lock'],Systemd::LogindSettings::Ensure], Optional['HandleLidSwitch'] => Variant[Enum['ignore','poweroff','reboot','halt','kexec','suspend','hibernate','hybrid-sleep','suspend-then-hibernate','lock'],Systemd::LogindSettings::Ensure], Optional['HandleLidSwitchDocked'] => Variant[Enum['ignore','poweroff','reboot','halt','kexec','suspend','hibernate','hybrid-sleep','suspend-then-hibernate','lock'],Systemd::LogindSettings::Ensure], Optional['HandleLidSwitchExternalPower'] => Variant[Enum['ignore','poweroff','reboot','halt','kexec','suspend','hibernate','hybrid-sleep','suspend-then-hibernate','lock'],Systemd::LogindSettings::Ensure], Optional['HandlePowerKey'] => Variant[Enum['ignore','poweroff','reboot','halt','kexec','suspend','hibernate','hybrid-sleep','suspend-then-hibernate','lock'],Systemd::LogindSettings::Ensure], Optional['HandleSuspendKey'] => Variant[Enum['ignore','poweroff','reboot','halt','kexec','suspend','hibernate','hybrid-sleep','suspend-then-hibernate','lock'],Systemd::LogindSettings::Ensure], Optional['HibernateKeyIgnoreInhibited'] => Variant[Enum['yes','no'],Systemd::LogindSettings::Ensure], Optional['HoldoffTimeoutSec'] => Variant[Integer,Systemd::LogindSettings::Ensure], Optional['IdleAction'] => Variant[Enum['ignore','poweroff','reboot','halt','kexec','suspend','hibernate','hybrid-sleep','suspend-then-hibernate','lock'],Systemd::LogindSettings::Ensure], Optional['IdleActionSec'] => Variant[Integer,Systemd::LogindSettings::Ensure], Optional['InhibitDelayMaxSec'] => Variant[Integer,Systemd::LogindSettings::Ensure], Optional['InhibitorsMax'] => Variant[Integer,Systemd::LogindSettings::Ensure], Optional['KillExcludeUsers'] => Variant[Array[String],Systemd::LogindSettings::Ensure], Optional['KillOnlyUsers'] => Variant[Array[String],Systemd::LogindSettings::Ensure], Optional['KillUserProcesses'] => Variant[Enum['yes','no'],Systemd::LogindSettings::Ensure], Optional['LidSwitchIgnoreInhibited'] => Variant[Enum['yes','no'],Systemd::LogindSettings::Ensure], Optional['NAutoVTs'] => Variant[Integer,Systemd::LogindSettings::Ensure], Optional['PowerKeyIgnoreInhibited'] => Variant[Enum['yes','no'],Systemd::LogindSettings::Ensure], Optional['RemoveIPC'] => Variant[Enum['yes','no'],Systemd::LogindSettings::Ensure], Optional['ReserveVT'] => Variant[Integer,Systemd::LogindSettings::Ensure], Optional['RuntimeDirectorySize'] => Variant[Integer,Pattern['^(\d+(K|M|G|T|P|E|%)?)$'],Systemd::LogindSettings::Ensure], Optional['SessionsMax'] => Variant[Integer,Pattern['^(infinity|(\d+(K|M|G|T|P|E|%)?))$'],Systemd::LogindSettings::Ensure], Optional['SuspendKeyIgnoreInhibited'] => Variant[Enum['yes','no'],Systemd::LogindSettings::Ensure], Optional['UserTasksMax'] => Variant[Integer,Pattern['^(infinity|(\d+(K|M|G|T|P|E|%)?))$'],Systemd::LogindSettings::Ensure] }]` ### `Systemd::LogindSettings::Ensure` The Systemd::LogindSettings::Ensure data type. Alias of `Struct[{ 'ensure' => Enum['present','absent'] }]` ### `Systemd::ServiceLimits` Matches Systemd Service Limit Struct Alias of `Struct[{ Optional['LimitCPU'] => Pattern['^\d+(s|m|h|d|w|M|y)?(:\d+(s|m|h|d|w|M|y)?)?$'], Optional['LimitFSIZE'] => Pattern['^(infinity|((\d+(K|M|G|T|P|E)(:\d+(K|M|G|T|P|E))?)))$'], Optional['LimitDATA'] => Pattern['^(infinity|((\d+(K|M|G|T|P|E)(:\d+(K|M|G|T|P|E))?)))$'], Optional['LimitSTACK'] => Pattern['^(infinity|((\d+(K|M|G|T|P|E)(:\d+(K|M|G|T|P|E))?)))$'], Optional['LimitCORE'] => Pattern['^(infinity|((\d+(K|M|G|T|P|E)(:\d+(K|M|G|T|P|E))?)))$'], Optional['LimitRSS'] => Pattern['^(infinity|((\d+(K|M|G|T|P|E)(:\d+(K|M|G|T|P|E))?)))$'], Optional['LimitNOFILE'] => Variant[Integer[-1],Pattern['^(infinity|\d+(:(infinity|\d+))?)$']], Optional['LimitAS'] => Pattern['^(infinity|((\d+(K|M|G|T|P|E)(:\d+(K|M|G|T|P|E))?)))$'], Optional['LimitNPROC'] => Integer[1], Optional['LimitMEMLOCK'] => Pattern['^(infinity|((\d+(K|M|G|T|P|E)(:\d+(K|M|G|T|P|E))?)))$'], Optional['LimitLOCKS'] => Integer[1], Optional['LimitSIGPENDING'] => Integer[1], Optional['LimitMSGQUEUE'] => Pattern['^(infinity|((\d+(K|M|G|T|P|E)(:\d+(K|M|G|T|P|E))?)))$'], Optional['LimitNICE'] => Variant[Integer[0,40], Pattern['^(-\+([0-1]?[0-9]|20))|([0-3]?[0-9]|40)$']], Optional['LimitRTPRIO'] => Integer[0], Optional['LimitRTTIME'] => Pattern['^\d+(ms|s|m|h|d|w|M|y)?(:\d+(ms|s|m|h|d|w|M|y)?)?$'], Optional['CPUAccounting'] => Boolean, Optional['CPUShares'] => Integer[2,262144], Optional['StartupCPUShares'] => Integer[2,262144], Optional['CPUQuota'] => Pattern['^([1-9][0-9]*)%$'], Optional['MemoryAccounting'] => Boolean, Optional['MemoryLow'] => Pattern['^(\d+(K|M|G|T)?)$'], Optional['MemoryHigh'] => Pattern['^(\d+(K|M|G|T)?)$'], Optional['MemoryMax'] => Pattern['^(\d+(K|M|G|T)?)$'], Optional['MemoryLimit'] => Pattern['^(\d+(K|M|G|T)?)$'], Optional['TasksAccounting'] => Boolean, Optional['TasksMax'] => Variant[Integer[1],Pattern['^(infinity|([1-9][0-9]?$|^100)%)$']], Optional['IOAccounting'] => Boolean, Optional['IOWeight'] => Integer[1,10000], Optional['StartupIOWeight'] => Integer[1,10000], Optional['IODeviceWeight'] => Array[Hash[Stdlib::Absolutepath, Integer[1,10000], 1, 1]], Optional['IOReadBandwidthMax'] => Array[Hash[Stdlib::Absolutepath, Pattern['^(\d+(K|M|G|T)?)$'], 1, 1]], Optional['IOWriteBandwidthMax'] => Array[Hash[Stdlib::Absolutepath, Pattern['^(\d+(K|M|G|T)?)$'], 1, 1]], Optional['IOReadIOPSMax'] => Array[Hash[Stdlib::Absolutepath, Pattern['^(\d+(K|M|G|T)?)$'], 1, 1]], Optional['IOWriteIOPSMax'] => Array[Hash[Stdlib::Absolutepath, Pattern['^(\d+(K|M|G|T)?)$'], 1, 1]], Optional['DeviceAllow'] => String[1], Optional['DevicePolicy'] => Enum['auto','closed','strict'], Optional['Slice'] => String[1], Optional['Delegate'] => Boolean, Optional['OOMScoreAdjust'] => Integer[-1000,1000] }]` ### `Systemd::Unit` The Systemd::Unit data type. Alias of `Pattern['^[^/]+\.(service|socket|device|mount|automount|swap|target|path|timer|slice|scope)$']` diff --git a/manifests/dropin_file.pp b/manifests/dropin_file.pp index ce14bba..f91cebe 100644 --- a/manifests/dropin_file.pp +++ b/manifests/dropin_file.pp @@ -1,110 +1,90 @@ # Creates a drop-in file for a systemd unit # # @api public # # @see systemd.unit(5) # # @attr name [Pattern['^[^/]+\.conf$']] # The target unit file to create # # @attr path # The main systemd configuration path # # @attr selinux_ignore_defaults # If Puppet should ignore the default SELinux labels. # # @attr content # The full content of the unit file # # * Mutually exclusive with ``$source`` # # @attr source # The ``File`` resource compatible ``source`` # # * Mutually exclusive with ``$content`` # # @attr target # If set, will force the file to be a symlink to the given target # # * Mutually exclusive with both ``$source`` and ``$content`` # # @attr owner # The owner to set on the dropin file # # @attr group # The group to set on the dropin file # # @attr mode # The mode to set on the dropin file # # @attr show_diff # Whether to show the diff when updating dropin file # -# @attr daemon_reload -# Set to `lazy` to defer execution of a systemctl daemon reload. -# Minimizes the number of times the daemon is reloaded. -# Set to `eager` to immediately reload after the dropin file is updated. -# Useful if the daemon needs to be reloaded before a service is refreshed. -# May cause multiple daemon reloads. -# define systemd::dropin_file ( Systemd::Unit $unit, Systemd::Dropin $filename = $name, Enum['present', 'absent', 'file'] $ensure = 'present', Stdlib::Absolutepath $path = '/etc/systemd/system', Optional[Boolean] $selinux_ignore_defaults = false, Optional[Variant[String,Sensitive[String]]] $content = undef, Optional[String] $source = undef, Optional[Stdlib::Absolutepath] $target = undef, String $owner = 'root', String $group = 'root', String $mode = '0444', Boolean $show_diff = true, - Enum['lazy', 'eager'] $daemon_reload = 'lazy', ) { include systemd if $target { $_ensure = 'link' } else { $_ensure = $ensure ? { 'present' => 'file', default => $ensure, } } if $ensure != 'absent' { ensure_resource('file', "${path}/${unit}.d", { ensure => directory, owner => 'root', group => 'root', recurse => $systemd::purge_dropin_dirs, purge => $systemd::purge_dropin_dirs, selinux_ignore_defaults => $selinux_ignore_defaults, }) } file { "${path}/${unit}.d/${filename}": ensure => $_ensure, content => $content, source => $source, target => $target, owner => $owner, group => $group, mode => $mode, selinux_ignore_defaults => $selinux_ignore_defaults, show_diff => $show_diff, } - - if $daemon_reload == 'lazy' { - File["${path}/${unit}.d/${filename}"] ~> Class['systemd::systemctl::daemon_reload'] - } else { - File["${path}/${unit}.d/${filename}"] ~> Exec["${unit}-systemctl-daemon-reload"] - - exec { "${unit}-systemctl-daemon-reload": - command => 'systemctl daemon-reload', - refreshonly => true, - path => $facts['path'], - } - } } diff --git a/manifests/init.pp b/manifests/init.pp index c0b2d0f..2d4dec8 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -1,190 +1,188 @@ # This module allows triggering systemd commands once for all modules # # @api public # # @param service_limits # May be passed a resource hash suitable for passing directly into the # ``create_resources()`` function as called on ``systemd::service_limits`` # # @param manage_resolved # Manage the systemd resolver # # @param resolved_ensure # The state that the ``resolved`` service should be in # # @param dns # A space-separated list of IPv4 and IPv6 addresses to use as system DNS servers. # DNS requests are sent to one of the listed DNS servers in parallel to suitable # per-link DNS servers acquired from systemd-networkd.service(8) or set at runtime # by external applications. requires puppetlabs-inifile # # @param fallback_dns # A space-separated list of IPv4 and IPv6 addresses to use as the fallback DNS # servers. Any per-link DNS servers obtained from systemd-networkd take # precedence over this setting. requires puppetlabs-inifile # # @param domains # A space-separated list of domains host names or IP addresses to be used # systemd-resolved take precedence over this setting. # # @param llmnr # Takes a boolean argument or "resolve". # # @param multicast_dns # Takes a boolean argument or "resolve". # # @param dnssec # Takes a boolean argument or "allow-downgrade". # # @param dnsovertls # Takes a boolean argument or "opportunistic" # # @param cache # Takes a boolean argument or "no-negative". # # @param dns_stub_listener # Takes a boolean argument or one of "udp" and "tcp". # # @param use_stub_resolver # Takes a boolean argument. When "false" (default) it uses /run/systemd/resolve/resolv.conf # as /etc/resolv.conf. When "true", it uses /run/systemd/resolve/stub-resolv.conf # @param manage_networkd # Manage the systemd network daemon # # @param networkd_ensure # The state that the ``networkd`` service should be in # # @param manage_timesyncd # Manage the systemd tiemsyncd daemon # # @param timesyncd_ensure # The state that the ``timesyncd`` service should be in # # @param ntp_server # comma separated list of ntp servers, will be combined with interface specific # addresses from systemd-networkd. requires puppetlabs-inifile # # @param fallback_ntp_server # A space-separated list of NTP server host names or IP addresses to be used # as the fallback NTP servers. Any per-interface NTP servers obtained from # systemd-networkd take precedence over this setting. requires puppetlabs-inifile # # @param manage_journald # Manage the systemd journald # # @param journald_settings # Config Hash that is used to configure settings in journald.conf # # @param manage_udevd # Manage the systemd udev daemon # # @param udev_log # The value of /etc/udev/udev.conf udev_log # # @param udev_children_max # The value of /etc/udev/udev.conf children_max # # @param udev_exec_delay # The value of /etc/udev/udev.conf exec_delay # # @param udev_event_timeout # The value of /etc/udev/udev.conf event_timeout # # @param udev_resolve_names # The value of /etc/udev/udev.conf resolve_names # # @param udev_timeout_signal # The value of /etc/udev/udev.conf timeout_signal # # @param udev_rules # Config Hash that is used to generate instances of our # `udev::rule` define. # # @param manage_logind # Manage the systemd logind # # @param logind_settings # Config Hash that is used to configure settings in logind.conf # # @param loginctl_users # Config Hash that is used to generate instances of our type # `loginctl_user`. # # @param dropin_files # Configure dropin files via hiera with factory pattern class systemd ( Hash[String,Hash[String, Any]] $service_limits, Boolean $manage_resolved, Enum['stopped','running'] $resolved_ensure, Optional[Variant[Array[String],String]] $dns, Optional[Variant[Array[String],String]] $fallback_dns, Optional[Variant[Array[String],String]] $domains, Optional[Variant[Boolean,Enum['resolve']]] $llmnr, Optional[Variant[Boolean,Enum['resolve']]] $multicast_dns, Optional[Variant[Boolean,Enum['allow-downgrade']]] $dnssec, Optional[Variant[Boolean,Enum['opportunistic', 'no']]] $dnsovertls, Optional[Variant[Boolean,Enum['no-negative']]] $cache, Optional[Variant[Boolean,Enum['udp','tcp']]] $dns_stub_listener, Boolean $use_stub_resolver, Boolean $manage_networkd, Enum['stopped','running'] $networkd_ensure, Boolean $manage_timesyncd, Enum['stopped','running'] $timesyncd_ensure, Optional[Variant[Array,String]] $ntp_server, Optional[Variant[Array,String]] $fallback_ntp_server, Boolean $manage_accounting, Hash[String,String] $accounting, Boolean $purge_dropin_dirs, Boolean $manage_journald, Systemd::JournaldSettings $journald_settings, Boolean $manage_udevd, Optional[Variant[Integer,String]] $udev_log, Optional[Integer] $udev_children_max, Optional[Integer] $udev_exec_delay, Optional[Integer] $udev_event_timeout, Optional[Enum['early', 'late', 'never']] $udev_resolve_names, Optional[Variant[Integer,String]] $udev_timeout_signal, Boolean $manage_logind, Systemd::LogindSettings $logind_settings, Hash $loginctl_users = {}, Hash $dropin_files = {}, Hash $udev_rules = {}, ) { - contain systemd::systemctl::daemon_reload - create_resources('systemd::service_limits', $service_limits) if $manage_resolved and $facts['systemd_internal_services'] and $facts['systemd_internal_services']['systemd-resolved.service'] { contain systemd::resolved } if $manage_networkd and $facts['systemd_internal_services'] and $facts['systemd_internal_services']['systemd-networkd.service'] { contain systemd::networkd } if $manage_timesyncd and $facts['systemd_internal_services'] and $facts['systemd_internal_services']['systemd-timesyncd.service'] { contain systemd::timesyncd } if $manage_udevd { contain systemd::udevd } if $manage_accounting { contain systemd::system } if $manage_journald { contain systemd::journald } if $manage_logind { contain systemd::logind } $dropin_files.each |$name, $resource| { systemd::dropin_file { $name: * => $resource, } } } diff --git a/manifests/service_limits.pp b/manifests/service_limits.pp index 4741ab2..53a6db7 100644 --- a/manifests/service_limits.pp +++ b/manifests/service_limits.pp @@ -1,81 +1,80 @@ # Adds a set of custom limits to the service # # @api public # # @see systemd.exec(5) # # @attr name [Pattern['^.+\.(service|socket|mount|swap)$']] # The name of the service that you will be modifying # # @param $ensure # Whether to drop a file or remove it # # @param path # The path to the main systemd settings directory # # @param selinux_ignore_defaults # If Puppet should ignore the default SELinux labels. # # @param limits # A Hash of service limits matching the settings in ``systemd.exec(5)`` # # * Mutually exclusive with ``$source`` # # @param source # A ``File`` resource compatible ``source`` # # * Mutually exclusive with ``$limits`` # # @param restart_service # Restart the managed service after setting the limits # define systemd::service_limits ( Enum['present', 'absent', 'file'] $ensure = 'present', Stdlib::Absolutepath $path = '/etc/systemd/system', Optional[Boolean] $selinux_ignore_defaults = false, Optional[Systemd::ServiceLimits] $limits = undef, Optional[String] $source = undef, Boolean $restart_service = true ) { include systemd if $name !~ Pattern['^.+\.(service|socket|mount|swap)$'] { fail('$name must match Pattern["^.+\.(service|socket|mount|swap)$"]') } if $limits and !empty($limits) { $_content = template("${module_name}/limits.erb") } else { $_content = undef } if $ensure != 'absent' { if ($limits and !empty($limits)) and $source { fail('You may not supply both limits and source parameters to systemd::service_limits') } elsif ($limits == undef or empty($limits)) and ($source == undef) { fail('You must supply either the limits or source parameter to systemd::service_limits') } } systemd::dropin_file { "${name}-90-limits.conf": ensure => $ensure, unit => $name, filename => '90-limits.conf', path => $path, selinux_ignore_defaults => $selinux_ignore_defaults, content => $_content, source => $source, } if $restart_service { exec { "restart ${name} because limits": command => "systemctl restart ${name}", path => $::path, refreshonly => true, subscribe => File["${path}/${name}.d/90-limits.conf"], - require => Class['systemd::systemctl::daemon_reload'], } } } diff --git a/manifests/system.pp b/manifests/system.pp index 7be125b..368048d 100644 --- a/manifests/system.pp +++ b/manifests/system.pp @@ -1,18 +1,17 @@ # @api private # # This class provides a solution to enable accounting # class systemd::system { assert_private() $systemd::accounting.each |$option, $value| { ini_setting { $option: ensure => 'present', path => '/etc/systemd/system.conf', section => 'Manager', setting => $option, value => $value, - notify => Class['systemd::systemctl::daemon_reload'], } } } diff --git a/manifests/systemctl/daemon_reload.pp b/manifests/systemctl/daemon_reload.pp deleted file mode 100644 index 61b9f52..0000000 --- a/manifests/systemctl/daemon_reload.pp +++ /dev/null @@ -1,10 +0,0 @@ -# Reload the systemctl daemon -# -# @api public -class systemd::systemctl::daemon_reload { - exec { 'systemctl-daemon-reload': - command => 'systemctl daemon-reload', - refreshonly => true, - path => $facts['path'], - } -} diff --git a/manifests/unit_file.pp b/manifests/unit_file.pp index a05db4e..f8029ce 100644 --- a/manifests/unit_file.pp +++ b/manifests/unit_file.pp @@ -1,110 +1,116 @@ # Creates a systemd unit file # # @api public # # @see systemd.unit(5) # # @param name [Pattern['^[^/]+\.(service|socket|device|mount|automount|swap|target|path|timer|slice|scope)$']] # The target unit file to create # # @param ensure # The state of the unit file to ensure # # @param path # The main systemd configuration path # # @param content # The full content of the unit file # # * Mutually exclusive with ``$source`` # # @param source # The ``File`` resource compatible ``source`` # # * Mutually exclusive with ``$content`` # # @param target # If set, will force the file to be a symlink to the given target # # * Mutually exclusive with both ``$source`` and ``$content`` # # @param owner # The owner to set on the unit file # # @param group # The group to set on the unit file # # @param mode # The mode to set on the unit file # # @param show_diff # Whether to show the diff when updating unit file # # @param enable # If set, will manage the unit enablement status. # # @param active # If set, will manage the state of the unit. # # @param restart # Specify a restart command manually. If left unspecified, a standard Puppet service restart happens. # define systemd::unit_file ( Enum['present', 'absent', 'file'] $ensure = 'present', Stdlib::Absolutepath $path = '/etc/systemd/system', Optional[String] $content = undef, Optional[String] $source = undef, Optional[Stdlib::Absolutepath] $target = undef, String $owner = 'root', String $group = 'root', String $mode = '0444', Boolean $show_diff = true, Optional[Variant[Boolean, Enum['mask']]] $enable = undef, Optional[Boolean] $active = undef, Optional[String] $restart = undef, ) { include systemd assert_type(Systemd::Unit, $name) if $target { $_ensure = 'link' } else { $_ensure = $ensure ? { 'present' => 'file', default => $ensure, } } file { "${path}/${name}": ensure => $_ensure, content => $content, source => $source, target => $target, owner => $owner, group => $group, mode => $mode, show_diff => $show_diff, - notify => Class['systemd::systemctl::daemon_reload'], } if $enable != undef or $active != undef { service { $name: ensure => $active, enable => $enable, restart => $restart, provider => 'systemd', } if $ensure == 'absent' { if $enable or $active { fail("Can't ensure the unit file is absent and activate/enable the service at the same time") } Service[$name] -> File["${path}/${name}"] } else { - Class['systemd::systemctl::daemon_reload'] -> Service[$name] File["${path}/${name}"] ~> Service[$name] } + } elsif $ensure == 'absent' { + # Work around https://tickets.puppetlabs.com/browse/PUP-9473 + exec { "${name}-systemctl-daemon-reload": + command => 'systemctl daemon-reload', + refreshonly => true, + path => $facts['path'], + subscribe => File["${path}/${name}"], + } } } diff --git a/metadata.json b/metadata.json index 30e5c08..d9a98f5 100644 --- a/metadata.json +++ b/metadata.json @@ -1,90 +1,90 @@ { "name": "camptocamp-systemd", "version": "2.12.0", "author": "camptocamp", "summary": "Puppet Systemd module", "license": "Apache-2.0", "source": "https://github.com/camptocamp/puppet-systemd", "project_page": "https://github.com/camptocamp/puppet-systemd", "issues_url": "https://github.com/camptocamp/puppet-systemd/issues", "dependencies": [ { "name": "puppetlabs/stdlib", "version_requirement": ">= 4.13.1 < 7.0.0" }, { "name": "puppetlabs/inifile", "version_requirement": ">= 1.6.0 < 5.0.0" } ], "operatingsystem_support": [ { "operatingsystem": "Debian", "operatingsystemrelease": [ "8", "9", "10" ] }, { "operatingsystem": "Ubuntu", "operatingsystemrelease": [ "16.04", "18.04" ] }, { "operatingsystem": "SLES", "operatingsystemrelease": [ "12", "15" ] }, { "operatingsystem": "RedHat", "operatingsystemrelease": [ "7", "8" ] }, { "operatingsystem": "VirtuozzoLinux", "operatingsystemrelease": [ "7" ] }, { "operatingsystem": "CentOS", "operatingsystemrelease": [ "7", "8" ] }, { "operatingsystem": "OracleLinux", "operatingsystemrelease": [ "7", "8" ] }, { "operatingsystem": "Archlinux" }, { "operatingsystem": "Fedora", "operatingsystemrelease": [ "30", "31" ] } ], "requirements": [ { "name": "puppet", - "version_requirement": ">= 4.10.10 < 7.0.0" + "version_requirement": ">= 6.1.0 < 7.0.0" } ], "pdk-version": "1.18.0", "template-url": "pdk-default#1.18.0", "template-ref": "tags/1.18.0-0-g095317c" } diff --git a/spec/classes/init_spec.rb b/spec/classes/init_spec.rb index 6c189ce..32224d7 100644 --- a/spec/classes/init_spec.rb +++ b/spec/classes/init_spec.rb @@ -1,446 +1,445 @@ require 'spec_helper' describe 'systemd' do context 'supported operating systems' do on_supported_os.each do |os, facts| context "on #{os}" do let(:facts) { facts } it { is_expected.to compile.with_all_deps } it { is_expected.to create_class('systemd') } - it { is_expected.to create_class('systemd::systemctl::daemon_reload') } it { is_expected.to contain_class('systemd::journald') } it { is_expected.to create_service('systemd-journald') } it { is_expected.to have_ini_setting_resource_count(0) } it { is_expected.not_to create_service('systemd-resolved') } it { is_expected.not_to create_service('systemd-networkd') } it { is_expected.not_to create_service('systemd-timesyncd') } context 'when enabling resolved and networkd' do let(:params) do { manage_resolved: true, manage_networkd: true, } end it { is_expected.to create_service('systemd-resolved').with_ensure('running') } it { is_expected.to create_service('systemd-resolved').with_enable(true) } it { is_expected.to create_service('systemd-networkd').with_ensure('running') } it { is_expected.to create_service('systemd-networkd').with_enable(true) } end context 'when enabling resolved with DNS values (string)' do let(:params) do { manage_resolved: true, dns: '8.8.8.8 8.8.4.4', fallback_dns: '2001:4860:4860::8888 2001:4860:4860::8844', } end it { is_expected.to create_service('systemd-resolved').with_ensure('running') } it { is_expected.to create_service('systemd-resolved').with_enable(true) } it { is_expected.to contain_ini_setting('dns') } it { is_expected.to contain_ini_setting('fallback_dns') } it { is_expected.not_to contain_ini_setting('domains') } it { is_expected.not_to contain_ini_setting('multicast_dns') } it { is_expected.not_to contain_ini_setting('llmnr') } it { is_expected.not_to contain_ini_setting('dnssec') } it { is_expected.not_to contain_ini_setting('dnsovertls') } it { is_expected.not_to contain_ini_setting('cache') } it { is_expected.not_to contain_ini_setting('dns_stub_listener') } end context 'when enabling resolved with DNS values (array)' do let(:params) do { manage_resolved: true, dns: ['8.8.8.8', '8.8.4.4'], fallback_dns: ['2001:4860:4860::8888', '2001:4860:4860::8844'], } end it { is_expected.to create_service('systemd-resolved').with_ensure('running') } it { is_expected.to create_service('systemd-resolved').with_enable(true) } it { is_expected.to contain_ini_setting('dns') } it { is_expected.to contain_ini_setting('fallback_dns') } it { is_expected.not_to contain_ini_setting('domains') } it { is_expected.not_to contain_ini_setting('multicast_dns') } it { is_expected.not_to contain_ini_setting('llmnr') } it { is_expected.not_to contain_ini_setting('dnssec') } it { is_expected.not_to contain_ini_setting('dnsovertls') } it { is_expected.not_to contain_ini_setting('cache') } it { is_expected.not_to contain_ini_setting('dns_stub_listener') } end context 'when enabling resolved with DNS values (full)' do let(:params) do { manage_resolved: true, dns: ['8.8.8.8', '8.8.4.4'], fallback_dns: ['2001:4860:4860::8888', '2001:4860:4860::8844'], domains: ['2001:4860:4860::8888', '2001:4860:4860::8844'], llmnr: true, multicast_dns: false, dnssec: false, dnsovertls: 'no', cache: true, dns_stub_listener: 'udp', } end it { is_expected.to create_service('systemd-resolved').with_ensure('running') } it { is_expected.to create_service('systemd-resolved').with_enable(true) } it { is_expected.to contain_ini_setting('dns') } it { is_expected.to contain_ini_setting('fallback_dns') } it { is_expected.to contain_ini_setting('domains') } it { is_expected.to contain_ini_setting('multicast_dns') } it { is_expected.to contain_ini_setting('llmnr') } it { is_expected.to contain_ini_setting('dnssec') } it { is_expected.to contain_ini_setting('dnsovertls') } it { is_expected.to contain_ini_setting('cache').with( path: '/etc/systemd/resolved.conf', value: 'yes', ) } it { is_expected.to contain_ini_setting('dns_stub_listener') } end context 'when enabling resolved with no-negative cache variant' do let(:params) do { manage_resolved: true, cache: 'no-negative', } end it { is_expected.to create_service('systemd-resolved').with_ensure('running') } it { is_expected.to create_service('systemd-resolved').with_enable(true) } it { is_expected.to contain_ini_setting('cache').with( path: '/etc/systemd/resolved.conf', value: 'no-negative', ) } end context 'when enabling timesyncd' do let(:params) do { manage_timesyncd: true, } end it { is_expected.to create_service('systemd-timesyncd').with_ensure('running') } it { is_expected.to create_service('systemd-timesyncd').with_enable(true) } it { is_expected.not_to create_service('systemd-resolved').with_ensure('running') } it { is_expected.not_to create_service('systemd-resolved').with_enable(true) } it { is_expected.not_to create_service('systemd-networkd').with_ensure('running') } it { is_expected.not_to create_service('systemd-networkd').with_enable(true) } end context 'when enabling timesyncd with NTP values (string)' do let(:params) do { manage_timesyncd: true, ntp_server: '0.pool.ntp.org 1.pool.ntp.org', fallback_ntp_server: '2.pool.ntp.org 3.pool.ntp.org', } end it { is_expected.to compile.with_all_deps } it { is_expected.to contain_ini_setting('ntp_server') } it { is_expected.to contain_ini_setting('fallback_ntp_server') } end context 'when enabling timesyncd with NTP values (array)' do let(:params) do { manage_timesyncd: true, ntp_server: ['0.pool.ntp.org', '1.pool.ntp.org'], fallback_ntp_server: ['2.pool.ntp.org', '3.pool.ntp.org'], } end it { is_expected.to compile.with_all_deps } it { is_expected.to contain_ini_setting('ntp_server') } it { is_expected.to contain_ini_setting('fallback_ntp_server') } end context 'when passing service limits' do let(:params) do { service_limits: { 'openstack-nova-compute.service' => { 'limits' => { 'LimitNOFILE' => 32_768 } } }, } end it { is_expected.to compile.with_all_deps } it { is_expected.to contain_systemd__service_limits('openstack-nova-compute.service').with_limits('LimitNOFILE' => 32_768) } end context 'when managing Accounting options' do let :params do { manage_accounting: true, } end it { is_expected.to contain_class('systemd::system') } case facts[:os]['family'] when 'Archlinux' accounting = ['DefaultCPUAccounting', 'DefaultIOAccounting', 'DefaultIPAccounting', 'DefaultBlockIOAccounting', 'DefaultMemoryAccounting', 'DefaultTasksAccounting'] when 'Debian' accounting = ['DefaultCPUAccounting', 'DefaultBlockIOAccounting', 'DefaultMemoryAccounting'] when 'RedHat' accounting = ['DefaultCPUAccounting', 'DefaultBlockIOAccounting', 'DefaultMemoryAccounting', 'DefaultTasksAccounting'] when 'Suse' accounting = ['DefaultCPUAccounting', 'DefaultBlockIOAccounting', 'DefaultMemoryAccounting', 'DefaultTasksAccounting'] end accounting.each do |account| it { is_expected.to contain_ini_setting(account) } end it { is_expected.to compile.with_all_deps } end context 'when enabling journald with options' do let(:params) do { manage_journald: true, journald_settings: { 'Storage' => 'auto', 'MaxRetentionSec' => '5day', 'MaxLevelStore' => { 'ensure' => 'absent', }, }, } end it { is_expected.to compile.with_all_deps } it { is_expected.to contain_service('systemd-journald').with( ensure: 'running', ) } it { is_expected.to have_ini_setting_resource_count(3) } it { is_expected.to contain_ini_setting('Storage').with( path: '/etc/systemd/journald.conf', section: 'Journal', notify: 'Service[systemd-journald]', value: 'auto', ) } it { is_expected.to contain_ini_setting('MaxRetentionSec').with( path: '/etc/systemd/journald.conf', section: 'Journal', notify: 'Service[systemd-journald]', value: '5day', ) } it { is_expected.to contain_ini_setting('MaxLevelStore').with( path: '/etc/systemd/journald.conf', section: 'Journal', notify: 'Service[systemd-journald]', ensure: 'absent', ) } end context 'when disabling journald' do let(:params) do { manage_journald: false, } end it { is_expected.to compile.with_all_deps } it { is_expected.not_to contain_service('systemd-journald') } end context 'when disabling udevd management' do let(:params) do { manage_udevd: false, } end it { is_expected.to compile.with_all_deps } it { is_expected.not_to contain_service('systemd-udevd') } it { is_expected.not_to contain_file('/etc/udev/udev.conf') } end context 'when working with udevd and no custom rules' do let(:params) do { manage_udevd: true, udev_log: 'daemon', udev_children_max: 1, udev_exec_delay: 2, udev_event_timeout: 3, udev_resolve_names: 'early', udev_timeout_signal: 'SIGKILL', } end it { is_expected.to compile.with_all_deps } it { is_expected.to contain_service('systemd-udevd') .with(enable: true, ensure: 'running') } it { is_expected.to contain_file('/etc/udev/udev.conf') .with(ensure: 'file', owner: 'root', group: 'root', mode: '0444') .with_content(%r{^udev_log=daemon$}) .with_content(%r{^children_max=1$}) .with_content(%r{^exec_delay=2$}) .with_content(%r{^event_timeout=3$}) .with_content(%r{^resolve_names=early$}) .with_content(%r{^timeout_signal=SIGKILL$}) } end context 'when working with udevd and a rule set' do let(:params) do { manage_udevd: true, udev_log: 'daemon', udev_children_max: 1, udev_exec_delay: 2, udev_event_timeout: 3, udev_resolve_names: 'early', udev_timeout_signal: 'SIGKILL', udev_rules: { 'example_raw.rules' => { 'rules' => [ '# I am a comment', 'ACTION=="add", KERNEL=="sda", RUN+="/bin/raw /dev/raw/raw1 %N"', 'ACTION=="add", KERNEL=="sdb", RUN+="/bin/raw /dev/raw/raw2 %N"', ], } }, } end it { is_expected.to compile.with_all_deps } it { is_expected.to contain_service('systemd-udevd') .with(enable: true, ensure: 'running') } it { is_expected.to contain_file('/etc/udev/udev.conf') .with(ensure: 'file', owner: 'root', group: 'root', mode: '0444') .with_content(%r{^udev_log=daemon$}) .with_content(%r{^children_max=1$}) .with_content(%r{^exec_delay=2$}) .with_content(%r{^event_timeout=3$}) .with_content(%r{^resolve_names=early$}) .with_content(%r{^timeout_signal=SIGKILL$}) } it { is_expected.to contain_systemd__udev__rule('example_raw.rules') .with(rules: [ '# I am a comment', 'ACTION=="add", KERNEL=="sda", RUN+="/bin/raw /dev/raw/raw1 %N"', 'ACTION=="add", KERNEL=="sdb", RUN+="/bin/raw /dev/raw/raw2 %N"', ]) } end context 'when enabling logind with options' do let(:params) do { manage_logind: true, logind_settings: { 'HandleSuspendKey' => 'ignore', 'KillUserProcesses' => 'no', 'KillExcludeUsers' => ['a', 'b'], 'RemoveIPC' => { 'ensure' => 'absent', }, 'UserTasksMax' => '10000', }, loginctl_users: { 'foo' => { 'linger' => 'enabled' }, }, } end it { is_expected.to compile.with_all_deps } it { is_expected.to contain_service('systemd-logind').with( ensure: 'running', ) } it { is_expected.to have_ini_setting_resource_count(5) } it { is_expected.to contain_ini_setting('HandleSuspendKey').with( path: '/etc/systemd/logind.conf', section: 'Login', notify: 'Service[systemd-logind]', value: 'ignore', ) } it { is_expected.to contain_ini_setting('KillUserProcesses').with( path: '/etc/systemd/logind.conf', section: 'Login', notify: 'Service[systemd-logind]', value: 'no', ) } it { is_expected.to contain_ini_setting('KillExcludeUsers').with( path: '/etc/systemd/logind.conf', section: 'Login', notify: 'Service[systemd-logind]', value: 'a b', ) } it { is_expected.to contain_ini_setting('RemoveIPC').with( path: '/etc/systemd/logind.conf', section: 'Login', notify: 'Service[systemd-logind]', ensure: 'absent', ) } it { is_expected.to contain_ini_setting('UserTasksMax').with( path: '/etc/systemd/logind.conf', section: 'Login', notify: 'Service[systemd-logind]', value: '10000', ) } it { is_expected.to contain_loginctl_user('foo').with(linger: 'enabled') } end context 'when passing dropin_files' do let(:params) do { dropin_files: { 'my-foo.conf' => { 'unit' => 'foo.service', 'content' => '[Service]\nReadWritePaths=/', }, }, } end it { is_expected.to contain_systemd__dropin_file('my-foo.conf').with_content('[Service]\nReadWritePaths=/') } end end end end end diff --git a/spec/classes/systemctl/daemon_reload_spec.rb b/spec/classes/systemctl/daemon_reload_spec.rb deleted file mode 100644 index ec5f00e..0000000 --- a/spec/classes/systemctl/daemon_reload_spec.rb +++ /dev/null @@ -1,15 +0,0 @@ -require 'spec_helper' - -describe 'systemd::systemctl::daemon_reload' do - context 'supported operating systems' do - on_supported_os.each do |os, facts| - context "on #{os}" do - let(:facts) { facts } - - it { is_expected.to compile.with_all_deps } - it { is_expected.to create_class('systemd::systemctl::daemon_reload') } - it { is_expected.to create_exec('systemctl-daemon-reload') } - end - end - end -end diff --git a/spec/defines/dropin_file_spec.rb b/spec/defines/dropin_file_spec.rb index 1906e06..2c38ac7 100644 --- a/spec/defines/dropin_file_spec.rb +++ b/spec/defines/dropin_file_spec.rb @@ -1,132 +1,116 @@ require 'spec_helper' describe 'systemd::dropin_file' do context 'supported operating systems' do on_supported_os.each do |os, facts| context "on #{os}" do let(:facts) { facts } let(:title) { 'test.conf' } let(:params) do { unit: 'test.service', content: 'random stuff', } end it { is_expected.to compile.with_all_deps } it { is_expected.to create_file("/etc/systemd/system/#{params[:unit]}.d").with( ensure: 'directory', recurse: 'true', purge: 'true', selinux_ignore_defaults: false, ) } it { is_expected.to create_file("/etc/systemd/system/#{params[:unit]}.d/#{title}").with( ensure: 'file', content: %r{#{params[:content]}}, mode: '0444', selinux_ignore_defaults: false, ) } context 'with selinux_ignore_defaults set to true' do let(:params) do super().merge(selinux_ignore_defaults: true) end it { is_expected.to create_file("/etc/systemd/system/#{params[:unit]}.d").with_selinux_ignore_defaults(true) } it { is_expected.to create_file("/etc/systemd/system/#{params[:unit]}.d/#{title}").with_selinux_ignore_defaults(true) } end - context 'with daemon_reload => lazy (default)' do - it { is_expected.to create_file("/etc/systemd/system/#{params[:unit]}.d/#{title}").that_notifies('Class[systemd::systemctl::daemon_reload]') } - - it { is_expected.not_to create_exec("#{params[:unit]}-systemctl-daemon-reload") } - end - - context 'with daemon_reload => eager' do - let(:params) do - super().merge(daemon_reload: 'eager') - end - - it { is_expected.to create_file("/etc/systemd/system/#{params[:unit]}.d/#{title}").that_notifies("Exec[#{params[:unit]}-systemctl-daemon-reload]") } - - it { is_expected.to create_exec("#{params[:unit]}-systemctl-daemon-reload") } - end - context 'with a bad unit type' do let(:title) { 'test.badtype' } it { expect { is_expected.to compile.with_all_deps }.to raise_error(%r{expects a match for Systemd::Dropin}) } end context 'with a bad unit type containing a slash' do let(:title) { 'test/bad.conf' } it { expect { is_expected.to compile.with_all_deps }.to raise_error(%r{expects a match for Systemd::Dropin}) } end context 'with another drop-in file with the same filename (and content)' do let(:default_params) do { filename: 'longer-timeout.conf', content: 'random stuff', } end # Create drop-in file longer-timeout.conf for unit httpd.service let(:pre_condition) do "systemd::dropin_file { 'httpd_longer-timeout': filename => '#{default_params[:filename]}', unit => 'httpd.service', content => '#{default_params[:context]}', }" end # # Create drop-in file longer-timeout.conf for unit ftp.service let(:title) { 'ftp_longer-timeout' } let(:params) do default_params.merge(unit: 'ftp.service') end it { is_expected.to create_file("/etc/systemd/system/#{params[:unit]}.d/#{params[:filename]}").with( ensure: 'file', content: %r{#{params[:content]}}, mode: '0444', ) } end context 'with sensitve content' do let(:title) { 'sensitive.conf' } let(:params) do { unit: 'sensitive.service', content: RSpec::Puppet::RawString.new("Sensitive('TEST_CONTENT')"), } end it { is_expected.to create_file("/etc/systemd/system/#{params[:unit]}.d/#{title}").with( ensure: 'file', content: sensitive('TEST_CONTENT'), ) } end end end end end diff --git a/spec/defines/unit_file_spec.rb b/spec/defines/unit_file_spec.rb index 4b43f5c..23e0e74 100644 --- a/spec/defines/unit_file_spec.rb +++ b/spec/defines/unit_file_spec.rb @@ -1,88 +1,86 @@ require 'spec_helper' describe 'systemd::unit_file' do context 'supported operating systems' do on_supported_os.each do |os, facts| context "on #{os}" do let(:facts) { facts } let(:title) { 'test.service' } let(:params) { { content: 'random stuff' } } it { is_expected.to compile.with_all_deps } it do is_expected.to create_file("/etc/systemd/system/#{title}") .with_ensure('file') .with_content(%r{#{params[:content]}}) .with_mode('0444') - .that_notifies('Class[systemd::systemctl::daemon_reload]') end context 'with a bad unit type' do let(:title) { 'test.badtype' } it { is_expected.to compile.and_raise_error(%r{expects a match for Systemd::Unit}) } end context 'with a bad unit type containing a slash' do let(:title) { 'test/unit.service' } it { is_expected.to compile.and_raise_error(%r{expects a match for Systemd::Unit}) } end context 'with enable => true and active => true' do let(:params) do super().merge( enable: true, active: true, ) end it { is_expected.to compile.with_all_deps } it do is_expected.to contain_service('test.service') .with_ensure(true) .with_enable(true) .with_provider('systemd') .that_subscribes_to("File[/etc/systemd/system/#{title}]") - .that_requires('Class[systemd::systemctl::daemon_reload]') end end context 'ensure => absent' do let(:params) { super().merge(ensure: 'absent') } context 'with enable => true' do let(:params) { super().merge(enable: true) } it { is_expected.to compile.and_raise_error(%r{Can't ensure the unit file is absent and activate}) } end context 'with active => true' do let(:params) { super().merge(active: true) } it { is_expected.to compile.and_raise_error(%r{Can't ensure the unit file is absent and activate}) } end context 'with enable => false and active => false' do let(:params) do super().merge( enable: false, active: false, ) end it { is_expected.to compile.with_all_deps } it do is_expected.to contain_service('test.service') .with_ensure(false) .with_enable(false) .with_provider('systemd') .that_comes_before("File[/etc/systemd/system/#{title}]") end end end end end end end