diff --git a/README.md b/README.md index a6467e6..f8811c5 100644 --- a/README.md +++ b/README.md @@ -227,11 +227,11 @@ autofs::mounts: mapfile: '/etc/auto.home' ``` -### Map Files +### Map Files and Multi-mount Map Files The module also provides two compatible, built-in mechanisms for managing Autofs map files: by setting the `mapfiles` parameter of the `autofs` -class, and by declaration of `autofs::mapfile` resources. As with entries +class, and by declaration of `autofs::mapfile` or `autofs::multi-mapfile`resources. As with entries in the master map, using these is not obligatory. In fact, they are applicable only to map files written in the default (sun) map format; some other mechanism must be chosen if map files in some other format are @@ -319,6 +319,41 @@ The resulting content of file `/mnt/data` would be dataA -ro remote.com:/exports/dataA dataB -rw,noexec remote.com:/exports/dataB ``` +#### Multi-mount mapping +The `autofs::multi_mapfile` and `autofs::multi_mapping` resouces are declared simlarily to a standard mapping. Ordering defaults to a numeric 10 instead of alpha-numeric ordering. Ordering 0 and 999999 are reserved for the root path and last line of the mapfile. + +The root_path mount should always be order > 0 and less than all other mount points. + +Only one multi-mount is supported per mapfile. + +```puppet +autofs::multi_mapfile [ '/mnt/data': + root_path => '/data' +} + +autofs::multi_mapping { '/mnt/dataRoot': + mapfile => '/mnt/data', + key => '/', + options => 'ro', + fs => 'remote.com:/exports/dataRoot', + order => '1' +} + +autofs::multi_mapping { '/mnt/dataB': + mapfile => '/mnt/data', + key => '/dataB', + options => 'rw', + fs => 'remote.com:/exports/dataB' +} +``` +The resulting content of file `/mnt/data` would be + +``` +/data \ + / -ro remote.com:/exports/dataRoot \ + /dataB -rw remote.com:/exports/dataB \ + +``` #### Removing Entries @@ -485,8 +520,7 @@ described by the corresponding map file. Defaults to the `title` of this `auto Data type: Stdlib::Absolutepath or Autofs::MapEntry -This parameter designates the automount map serving this mount. Autofs supports a variety of options -here, but most commonly this is either an absolute path to a map file or the special string `-hosts`. +This parameter designates the automount map serving this mount. Autofs supports a variety of options here, but most commonly this is either an absolute path to a map file or the special string `-hosts`. #### `options` @@ -711,3 +745,7 @@ Authors * Vox Pupuli: [voxpupuli@groups.io](mailto:voxpupuli@groups.io) * David Hollinger: [david.hollinger@moduletux.com](mailto:david.hollinger@moduletux.com) + \ No newline at end of file diff --git a/REFERENCE.md b/REFERENCE.md index 2c6c9b9..4496ba6 100644 --- a/REFERENCE.md +++ b/REFERENCE.md @@ -21,6 +21,9 @@ _Private Classes_ * [`autofs::mapfile`](#autofsmapfile): Defined type to manage overall autofs map files * [`autofs::mapping`](#autofsmapping): Defined type to manage a single filesystem mapping in a single map file. +* [`autofs::multi_mapfile`](#autofsmapfile): Defined type to manage overall autofs map files with multi-mounts +* [`autofs::multi_mapping`](#autofsmapping): Defined type to manage a single filesystem mapping in a multi-mount map +file. * [`autofs::mount`](#autofsmount): Defined type to manage mount point definitions in the Autofs master map. @@ -686,3 +689,6 @@ non-empty string or an array of such strings Alias of `Variant[Pattern[/\A\S+\z/], Array[Pattern[/\A\S+\z/]]]` + \ No newline at end of file diff --git a/manifests/multi_mapfile.pp b/manifests/multi_mapfile.pp new file mode 100644 index 0000000..ea1877f --- /dev/null +++ b/manifests/multi_mapfile.pp @@ -0,0 +1,103 @@ +# @summary Defined type to manage autofs map files with a single multi-mount entry +# +# @see https://voxpupuli.org/puppet-autofs Home +# @see https://voxpupuli.org/puppet-autofs/puppet_classes/autofs.html puppet_classes::autofs +# @see https://www.github.com/voxpupuli/puppet-autofs Github +# @see https://forge.puppet.com/puppet/autofs Puppet Forge +# +# @author Vox Pupuli +# @author David Hollinger III +# @author Chip Schweiss +# +# @param ensure Whether the mapfile should be present on the target system +# @param path An absolute path to the map file +# @param mappings an array of mappings to enroll in the file. Additional +# mappings can be specified for this mapfile via autofs::mapping resources +# @param replace Whether to replace the contents of any an existing file +# at the specified path +# @param execute Whether to make the mapfile executable or not +# +define autofs::multi_mapfile ( + Enum['present', 'absent'] $ensure = 'present', + Stdlib::Absolutepath $path = $title, + Array[Autofs::Fs_mapping] $multi_mappings = [], + Optional[Autofs::Options] $options = undef, + Boolean $replace = true, + Boolean $execute = false, + Pattern[/\A\S+\z/] $root_path, +) { + include 'autofs' + + unless $autofs::package_ensure == 'absent' { + if $autofs::reload_command { + Concat { + before => Service[$autofs::service_name], + notify => Exec['automount-reload'], + } + } else { + Concat { + notify => Service[$autofs::service_name], + } + } + } + + $mapfile_mode = $execute ? { + true => '0755', + false => '0644' + } + + concat { $path: + ensure => $ensure, + owner => $autofs::map_file_owner, + group => $autofs::map_file_group, + mode => $mapfile_mode, + replace => $replace, + order => 'numeric', + require => Class['autofs::package'], + warn => template('autofs/mapfile.banner.erb'), + } + + if $ensure == 'present' { + + # Format the options string, relying to some extent on the + # $options parameter, if specified, to indeed match the + # Autofs::Options data type + if ($options =~ Undef) or ($options =~ Array[Any,0,0]) { # an empty array + $formatted_options = '' + } else { + $prelim_options = $options ? { + Array => join($options, ','), # a non-empty array + String => $options, + default => fail('Unexpected value for parameter $options') + } + $formatted_options = $prelim_options ? { + # even though the user *shouldn't* provide the hyphen, we accommodate + # them doing so. But only at the head of the option list, not + # internally. + '' => '', + /\A-/ => $prelim_options, + default => "-${prelim_options}", + } + } + + concat::fragment { "autofs::multi_mapping/${title}_root-_path": + target => "$path", + content => "${root_path} ${formatted_options} \\\n", + order => 0, + } + + concat::fragment { "autofs::multi_mapping/${title}_endline": + target => "$path", + content => "\n", + order => 999999, + } + + $multi_mappings.each |$mapping| { + autofs::multi_mapping { "${path}:${mapping[key]}": + ensure => 'present', + mapfile => $path, + * => $mapping, + } + } + } +} diff --git a/manifests/multi_mapping.pp b/manifests/multi_mapping.pp new file mode 100644 index 0000000..7b98cc8 --- /dev/null +++ b/manifests/multi_mapping.pp @@ -0,0 +1,99 @@ +# @summary Defined type to manage a multi-mapping filesystem mapping in a single map +# file. +# +# When ensured 'present', a autofs::mapfile resource managing the overall +# target map file must also be present in the catalog. This resource +# implements Autofs's 'sun' map format, which is the default. +# +# It is not supported to declare multiple autofs::mappings with the +# same key, targetting the same map file, and ensured 'present'. +# +# @see https://voxpupuli.org/puppet-autofs Home +# @see https://voxpupuli.org/puppet-autofs/puppet_classes/autofs.html puppet_classes::autofs +# @see https://www.github.com/voxpupuli/puppet-autofs Github +# @see https://forge.puppet.com/puppet/autofs Puppet Forge +# +# @author Vox Pupuli +# @author David Hollinger III +# @author Chip Schweiss +# +# @param ensure Whether the mapping should be present in the target mapfile; +# ensuring 'absent' is not meaningfully different from omitting the +# resource declaration altogether +# @param fs the remote filesystem to mount +# @param key the autofs key for this mappingr. For indirect maps it is the +# basename of the mountpoint directory for $fs (not to be confused with +# an _autofs_ mount point, which is the parent directory). For direct +# maps it is the absolute path to the mountpoint directory. +# @param mapfile the absolute path to the file containing the Autofs map +# to which this mapping belongs +# @param options a comma-delimited mount options string or an array of +# individual mount options; neither individual options nor the overall +# option list should be specified with a leading hyphen (-); that is +# part of the map file format, not of the options themselves, and +# it is provided by this resource +# @param order an integer describing the relative order of the mapping +# represented by this resource within the target map file (default 10). +# The order matters only if the same kay is enrolled more than once +# in the map, in which case only the first is effective. +# +# @example Options given as a string +# autofs::mapping{ '/etc/auto.data_data': +# mapfile => '/etc/auto.data', +# key => 'data', +# options => 'rw,sync,suid', +# fs => 'storage_host.my.com:/path/to/data' +# } +# +# @example Options given as an array +# autofs::mapping{ '/etc/auto.data_data': +# mapfile => '/etc/auto.data', +# key => 'data', +# options => ['ro', 'noexec', 'nodev'], +# fs => 'storage_host.my.com:/path/to/data' +# } +# +# @example No options +# autofs::mapping{ '/etc/auto.data_data': +# mapfile => '/etc/auto.data', +# key => 'data', +# fs => 'storage_host.my.com:/path/to/data' +# } +# +define autofs::multi_mapping ( + Stdlib::Absolutepath $mapfile, + Pattern[/\A\S+\z/] $key, + Pattern[/\S/] $fs, + Enum['present', 'absent'] $ensure = 'present', + Optional[Autofs::Options] $options = undef, + Integer $order = 10, +) { + unless $ensure == 'absent' { + # Format the options string, relying to some extent on the + # $options parameter, if specified, to indeed match the + # Autofs::Options data type + if ($options =~ Undef) or ($options =~ Array[Any,0,0]) { # an empty array + $formatted_options = '' + } else { + $prelim_options = $options ? { + Array => join($options, ','), # a non-empty array + String => $options, + default => fail('Unexpected value for parameter $options') + } + $formatted_options = $prelim_options ? { + # even though the user *shouldn't* provide the hyphen, we accommodate + # them doing so. But only at the head of the option list, not + # internally. + /\A-/ => $prelim_options, + default => "-${prelim_options}", + } + } + + # Declare an appropriate fragment of the target map file + concat::fragment { "autofs::multi_mapping/${title}": + target => $mapfile, + content => " ${key} ${formatted_options} ${fs} \\\n", + order => $order, + } + } +}