diff --git a/manifests/init.pp b/manifests/init.pp index 07a6aff..89925a1 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -1,153 +1,153 @@ # 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. +# 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 /var/run/systemd/resolve/resolv.conf # as /etc/resolv.conf. When "true", it uses /var/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_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, - Boolean $cache, + 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_logind, Systemd::LogindSettings $logind_settings, Hash $loginctl_users = {}, Hash $dropin_files = {}, ) { 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_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/spec/classes/init_spec.rb b/spec/classes/init_spec.rb index a255295..059cb60 100644 --- a/spec/classes/init_spec.rb +++ b/spec/classes/init_spec.rb @@ -1,327 +1,350 @@ 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') } + 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 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