From c7f75954bf741b82df888bbcfb83f61c345826ba Mon Sep 17 00:00:00 2001 From: Thomas Bellman <bellman@lysator.liu.se> Date: Wed, 14 Aug 2024 20:41:15 +0200 Subject: [PATCH] Support per-path parameters in systemd::tmpfiles. This adds the ability to give per-path parameters when configuring systemd-tmpfiles(8). The $paths parameter to systemd::tmpfiles can now be a hash of hashes, mapping from paths to hashes of parameters overriding the parameters given directly to systemd::tmpfiles, e.g. systemd::tmpfiles { 'smurf': type => 'd', mode => '0750', owner => 'gargamel', paths => { '/run/alldefaults' => {}, '/run/file' => { 'type' => 'f', 'group' => 'smurfs' }, }; } which will generate d /run/alldefaults 0750 gargamel - - f /run/file 0750 gargamel smurfs - in /etc/tmpfiles.d/smurf.conf. The original API, where you specify the $paths parameter as a simple list of paths, or just a single string, is still available, as that is easier to use for many simple cases. --- manifests/tmpfiles.pp | 78 ++++++++++++++++++++++++++++++------- templates/tmpfiles.conf.erb | 30 ++++++++++---- 2 files changed, 86 insertions(+), 22 deletions(-) diff --git a/manifests/tmpfiles.pp b/manifests/tmpfiles.pp index e86700b..18eb954 100644 --- a/manifests/tmpfiles.pp +++ b/manifests/tmpfiles.pp @@ -12,27 +12,76 @@ * config file, so e.g. any directory the config file says should be created, * will be. * + * Example: + * + * systemd::tmpfiles { + * 'smurf': + * type => 'd', mode => '0750', owner => 'gargamel', + * paths => { + * '/run/alldefaults' => {}, + * '/run/file' => { 'type' => 'f', 'group' => 'smurfs' }, + * }; + * } + * + * This will generate the entries + * + * d /run/alldefaults 0750 gargamel - - + * f /run/file 0750 gargamel smurfs - + * + * in /etc/tmpfiles.d/smurf.conf. Since the maxage parameter is not + * specified either in the "defaults", or in the hashes for either of the + * paths, it will default to "-". + * * Note that there is basically no verification that the parameter values * are syntactically correct, so it is possible to create config files * that are not valid. */ define systemd::tmpfiles( - # Path(s) to manage. Can be a single path, or a (possibly nested) - # list of paths. If more than one path is given, the same type, - # permissions, and maxage is applied to them all. + + # Path(s) to manage, and their parameters. + # + # Simple case, this is a path or a (nested) list of paths to put + # into the tmpfiles.d config file. The 'type', 'mode', 'owner', + # 'group', 'maxage' and 'argument' parameters will apply equally to + # all paths. # - # If specified, then at least $type must also be specified. + # Alternatively, this can be a hash of hashes, mapping from paths to + # a hash of parameter values for each path, e.g. # - $paths = [], + # paths => { + # '/run/foo' => { 'type' => 'd', 'mode' => '0700' }, + # '/run/bar' => { 'type' => 'f', 'owner' => 'zork' }, + # } + # + # In this case, the resource parameters will act as defaults for + # parameters missing in a specific path's parameter hash. + # + # The 'type' parameter must be specified for every path, either in + # its parameter hash, or as the $type parameter on the resource. + # All other parameters defaults to "-" or nothing. + # + # One limitation is that you can only have one entry per path. If + # you e.g. need one "d" entry and one "a" (ACL) entry for the same + # path, you must either use the $content parameter, forgoing some of + # the abstraction here, or you have to use more than one resource, + # putting the entries in different tmpfiles.d config files. + # + $paths = {}, - # The entry type for the paths in $paths. All path entries will - # share the same type. + # The entry type for the paths in $paths, unless overridden in the + # path-specific parameter hash. + # + # The entry type must be specified for all paths, either in the + # path's parameter hash in $paths, or using this parameter. # $type = undef, - # The mode, uid, gid, age, and argument fields, respectively, of the - # tmpfiles.d config entries for $paths. All entries will share the - # same settings. + # The values for the mode, uid, gid, age, and argument fields, + # respectively, of the tmpfiles.d config entries for $paths, unless + # overridden in the path-specific parameter hash in. + # + # If a parameter is not specified, either here or in the parameter + # hash, it defaults to "-" (or to "" for the $argument parameter). # $mode = undef, $owner = undef, @@ -62,13 +111,12 @@ define systemd::tmpfiles( case $ensure { 'present': { - if (($paths != []) and ((! $type) or ($type == ""))) { - fail("${resource_ref}: paths parameter set, but not type") - } - if (($type) and ($paths == [])) { + if (($type) and ($paths == [] or $paths == {})) { fail("${resource_ref}: type parameter set, but no paths") } - if (($paths == []) and ($content == '' or $content == [])) { + if (($paths == [] or $paths == {}) and + ($content == '' or $content == [])) + { fail("${resource_ref}: both paths and content are empty") } contain systemd::tmpfiles::trigger diff --git a/templates/tmpfiles.conf.erb b/templates/tmpfiles.conf.erb index 9d2a895..687aa4e 100644 --- a/templates/tmpfiles.conf.erb +++ b/templates/tmpfiles.conf.erb @@ -8,15 +8,31 @@ <% if not comment_lines.empty? -%> <% %> <% end -%> -<% [@paths].flatten.each do |path| +<% if @paths.respond_to?('each_pair') # Is a hash (of hashes) + path_params = @paths + else + path_params = [@paths].flatten.collect { |path| [path, {}] } + end + + path_params.sort.each do |path,params| + if ! params.is_a?(Hash) + raise(Puppet::ParseError, + "#{resource_ref}: value not a hash for path #{path}") + end + type = (params['type'] || @type) + if ! type + raise(Puppet::ParseError, + "#{resource_ref}: No type for path #{path}") + end + fields = [ path ] - fields << (@mode || '-') - fields << (@owner || '-') - fields << (@group || '-') - fields << (@maxage || '-') - fields << (@argument || '') + fields << (params['mode'] || @mode || '-') + fields << (params['owner'] || @owner || '-') + fields << (params['group'] || @group || '-') + fields << (params['maxage'] || @maxage || '-') + fields << (params['argument'] || @argument || '') -%> -<%= sprintf('%-2s %s', @type, fields.join("\t")).rstrip() %> +<%= sprintf('%-2s %s', type, fields.join("\t")).rstrip() %> <% end -%> <% [@content].flatten.each do |chunk| -%> <%= chunk %> -- GitLab