You want to manage a package from multiple places.
# Assumes you've already installed the puppetlabs-stdlib module
class strace {
notify { 'In strace': }
ensure_packages(['strace'], { ensure => 'present' })
}
class debug_tools {
# install lots of debug tools, and then strace
notify { 'In debug_tools': }
ensure_packages(['strace'], { ensure => 'present' })
}
include strace
include debug_tools
Notice: /Stage[main]/Strace/Notify[In strace]/message: defined 'message' as 'In strace'
Notice: /Stage[main]/Strace/Package[strace]/ensure: created
Notice: /Stage[main]/Debug_tools/Notify[In debug_tools]/message: defined 'message' as 'In debug_tools'
Notice: Applied catalog in 19.46 seconds
By default Puppet only allows you to manage a resource once. When you declare the same resource in additional locations an evaluation error will be raised.
class debug_tools {
# lots of other debug tools and then...
package { 'strace': ensure => 'present' }
}
class strace {
package { 'strace': ensure => 'present' }
}
include debug_tools
include strace
Error: Evaluation Error: Error while evaluating a Resource Statement,
Duplicate declaration: Package[strace] is already declared in file
/mypath/multi-fail.pp:3; cannot redeclare at /mypath.pp:9 at
/mypath/multi-fail.pp:9:3 on node puppet134
There are a few ways to work around this, and while historically
virtual resources were
used for even simple cases, such as managing a package in more than one
place, the ensure_packages
function provided by the Puppet stdlib
module is an excellent, easier, alternative.
$ sudo /opt/puppetlabs/bin/puppet module install puppetlabs-stdlib
Notice: Preparing to install into /etc/puppetlabs/code/environments/production/site...
/etc/puppetlabs/code/environments/production/site
puppetlabs-stdlib (v4.13.1)
# Assumes you've already installed the puppetlabs-stdlib module
class strace {
notify { 'In strace': }
ensure_packages(['strace'], { ensure => 'present' })
}
class debug_tools {
# install lots of debug tools, and then strace
notify { 'In debug_tools': }
ensure_packages(['strace'], { ensure => 'present' })
}
include strace
include debug_tools
Notice: /Stage[main]/Strace/Notify[In strace]/message: defined 'message' as 'In strace'
Notice: /Stage[main]/Strace/Package[strace]/ensure: created
Notice: /Stage[main]/Debug_tools/Notify[In debug_tools]/message: defined 'message' as 'In debug_tools'
Notice: Applied catalog in 19.46 seconds
Adopting this approach does require all the modules and classes you use
to cooperate in their declarations. Mixing package
resources and an
ensure_packages
for example will still raise errors:
class strace {
notify { 'In strace': }
ensure_packages(['strace'], { ensure => 'present' })
}
class debug_tools {
notify { 'In debug_tools': }
package { 'strace': ensure => 'present' }
}
include strace
include debug_tools
Error: Evaluation Error: Error while evaluating a Resource Statement,
Duplicate declaration: Package[strace] is already declared in file
/mypath/multi-pass.pp:4; cannot redeclare at /mypath/multi-pass.pp:12
at /mypath/multi-pass.pp:12:3 on node puppet165
One slightly annoying edge case to be aware of is the value of the ensure
property. Although Puppet allows you to use a number of values, most often
'installed' and 'present', ensure_packages
is a little simpler and will
consider these to be completely different parameters and cause the catalog to
fail in the same ways as above.
# This example will fail as the ensure property is set differently
class strace {
notify { 'In strace': }
ensure_packages(['strace'], { ensure => 'present' })
}
class debug_tools {
notify { 'In debug_tools': }
ensure_packages(['strace'], { ensure => 'installed' })
}
include strace
include debug_tools