
In the past, several of my
Puppet modules have
been tightly coupled. A perfect example is
Apache and
Munin. When I
install Apache, I want munin graphs set up. As a result my apache class
has the following snippet in it:
munin::plugin "apache_accesses":
munin::plugin "apache_processes":
munin::plugin "apache_volume":
This should make sure that these three plugins are installed and that
munin-node is restarted to pick them up. The define was implemented like
this:
define munin::plugin (
$enable = true,
$plugin_name = false,
)
include munin::node
file "/etc/munin/plugins/$name":
ensure => $enable ?
true => $plugin_name ?
false => "/usr/share/munin/plugins/$name",
default => "/usr/share/munin/plugins/$plugin_name"
,
default => absent
,
links => manage,
require => Package["munin-node"],
notify => Service["munin-node"],
(Note: this is a slight simplification of the define). As you can
see, the define includes
munin::node, as it needs the definition of the
munin-node service and package. As a result of this, installing Apache
drags in munin-node on your server too. It would be much nicer if the
apache class only installed the munin plugins if you also install munin
on the server.
It turns out that is is possible, using
virtual
resources. Virtual resources allow you to define resources in one
place, but not make them happen unless you realise them. Using this, we
can make the file resource in the
munin::plugin virtual and realise it
in our
munin::node class. Our new
munin::plugin looks like:
define munin::plugin (
$enable = true,
$plugin_name = false,
)
# removed "include munin::node"
# Added @ in front of the resource to declare it as virtual
@file "/etc/munin/plugins/$name":
ensure => $enable ?
true => $plugin_name ?
false => "/usr/share/munin/plugins/$name",
default => "/usr/share/munin/plugins/$plugin_name"
,
default => absent
,
links => manage,
require => Package["munin-node"],
notify => Service["munin-node"],
tag => munin-plugin,
We add the following line to our
munin::node class:
File< tag == munin-plugin >
The odd syntax in the
munin::node class realises all the
virtual resources that match the filter, in this case, any that is
tagged
munin-plugin. We've had to define this tag ourself, as
the auto-generated tags don't seem to work. You'll also notice that
we've removed the
munin::node include from the
munin::plugin define, which means that we no longer install
munin-node just by using the plugin define. I've used a similar
technique for logcheck, so additional rules are not installed unless
I've installed logcheck. I'm sure there are several other places where I
can use it to reduce such tight coupling between classes.