diff --git a/README.md b/README.md index 49e9c0f..5c709a4 100644 --- a/README.md +++ b/README.md @@ -1,193 +1,203 @@ # Systemd [![Puppet Forge](http://img.shields.io/puppetforge/v/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) ## 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. ```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. ```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'], } ``` +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: ```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: ```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'], } ``` ### 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'] ``` ### 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", } ``` ### 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` and `systemd-networkd` via the main class: ```puppet class{'systemd': manage_resolved => true, manage_networkd => true, manage_timesyncd => 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`. 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, 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', } } ``` diff --git a/manifests/unit_file.pp b/manifests/unit_file.pp index d20f048..3c0406e 100644 --- a/manifests/unit_file.pp +++ b/manifests/unit_file.pp @@ -1,60 +1,78 @@ # Creates a systemd unit file # # @api public # # @see systemd.unit(5) # # @attr name [Pattern['^.+\.(service|socket|device|mount|automount|swap|target|path|timer|slice|scope)$']] # The target unit file to create # # * Must not contain ``/`` # # @attr path # The main systemd configuration path # # @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 enable +# If set, will manage the unit enablement status. +# +# @attr active +# If set, will manage the state of the unit. +# 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, + 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, + Optional[Variant[Boolean, Enum['mask']]] $enable = undef, + Optional[Boolean] $active = 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 => 'root', group => 'root', mode => '0444', notify => Class['systemd::systemctl::daemon_reload'], } + + if $enable != undef or $active != undef { + service { $name: + ensure => $active, + enable => $enable, + provider => 'systemd', + subscribe => File["${path}/${name}"], + require => Class['systemd::systemctl::daemon_reload'], + } + } } diff --git a/spec/defines/unit_file_spec.rb b/spec/defines/unit_file_spec.rb index d8d30b9..d151d45 100644 --- a/spec/defines/unit_file_spec.rb +++ b/spec/defines/unit_file_spec.rb @@ -1,37 +1,55 @@ 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 { is_expected.to create_file("/etc/systemd/system/#{title}").with( :ensure => 'file', :content => /#{params[:content]}/, :mode => '0444' ) } it { is_expected.to create_file("/etc/systemd/system/#{title}").that_notifies('Class[systemd::systemctl::daemon_reload]') } context 'with a bad unit type' do let(:title) { 'test.badtype' } it { expect{ is_expected.to compile.with_all_deps }.to raise_error(/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 contain_service('test.service').with( + :ensure => true, + :enable => true, + :provider => 'systemd' + ) } + + it { is_expected.to contain_service('test.service').that_subscribes_to("File[/etc/systemd/system/#{title}]") } + it { is_expected.to contain_service('test.service').that_requires('Class[systemd::systemctl::daemon_reload]') } + end end end end end