Fixing Duplicate Resource Definitions for Defaulted Parameterised Defines in Puppet
Recently I have been working on a puppet module which defines a new resource which in turn requires a certain directory to exist, as so:
mything/init.pp
define mything ($log_dir='/var/log/mythings') {
notify { "${name} installed!": }
file { $log_dir:
ensure => directory
}
file { "${log_dir}/${name}":
ensure => directory,
require => File[$log_dir]
}
}
As you can see the log directory is parameterised with a default, combining flexibility with ease of use.
As it happens there’s no reason why multiple of these mythings shouldn’t be installed on the same host, as so:
mything { "thing1": }
mything { "thing2": }
But of course that causes puppet to bomb out:
Duplicate definition: File[/var/log/mythings] is already defined
The solution I’ve found is to realise a virtual resource defined in an unparameterised class, as so:
mything/init.pp
define mything ($log_dir='/var/log/mythings') {
notify { "${name} installed!": }
include mything::defaultlogging
File <| title == $log_dir |>
file { "${log_dir}/${name}":
ensure => directory,
require => File[$log_dir]
}
}
mything/defaultlogging.pp
class mything::defaultlogging {
@file { '/var/log/mythings':
ensure => directory
}
}
Now the following works:
mything { "thing1": }
mything { "thing2": }
If we want to override and use a different log directory as follows:
mything { "thing3":
log_dir => '/var/log/otherthing'
}
we get this error:
Could not find dependency File[/var/log/otherthing] for File[/var/log/otherthing/thing3] at /etc/puppet/modules/mything/manifests/init.pp:12
This just means we need to define the new log directory as so:
$other_log_dir='/var/log/otherthing'
@file { $other_log_dir:
ensure => directory
}
mything { "thing3":
log_dir => $other_log_dir
}
and all is good. Importantly, applying this manifest will not create the
default /var/log/mythings
directory.