Passive recipes

Is there a way to have recipes that are activated based on the activation
status of other recipes?

For example, if Apache is installed and Collectd is installed, then I want to
run the “apache-collectd” recipe. But I don’t want to force either Apache or
Collectd to be installed, and I don’t want one servers’ recipe to depend on the
other.

Ideally, the two server recipes would have no knowledge of the other, and the
apache-collectd module would know about both. How to do this without forcing
anything to be installed on all servers?

During recipe runtime, the list of recipes is still being built, so I can’t
trigger a single resource when both are present. At resource execution
(convergence), I know all the recipes, but it’s unclear how you get a resource
in the right place.

There might be a way to do this with scripts on the server, but that’s not a
general solution (and how do I make sure that the script is run after Apache
and Collectd resources are finished?).

-=Dan=-

I've solved this problem in two different ways, and wasn't really happy with
either. They are;

  1. Define a library function in the collectd cookbook which you can use in
    other cookbooks' recipes. This is how the 37signals monit
    cookbookhttp://github.com/37signals/37s_cookbooks/tree/master/cookbooks/monit/works,
    and probably wouldn't work well with collectd because it expects all
    its config to be in a single file (I think). This also means that you
    couldn't use the apache cookbook on a system which didn't have the collectd
    cookbook.

  2. Check the node's variables in the collectd config templates and only
    enable the config you need. I have the following in my
    collectd/templates/default/collectd.conf.erb:

<% if @node[:mysql] -%>
LoadPlugin mysql

Host localhost
User "root"
Password "<%= @node[:mysql][:server_root_password] %>"
Database "yourdb"

<% end -%>

I'm not sure if this would work if I were installing collectd and mysql on a
new box at the same time.

Would love to have a better solution to this problem.

  • Garret

On Wed, Oct 7, 2009 at 11:31 AM, dan@animoto.com wrote:

Is there a way to have recipes that are activated based on the activation
status of other recipes?

For example, if Apache is installed and Collectd is installed, then I want
to
run the "apache-collectd" recipe. But I don't want to force either Apache
or
Collectd to be installed, and I don't want one servers' recipe to depend on
the
other.

Ideally, the two server recipes would have no knowledge of the other, and
the
apache-collectd module would know about both. How to do this without
forcing
anything to be installed on all servers?

During recipe runtime, the list of recipes is still being built, so I can't
trigger a single resource when both are present. At resource execution
(convergence), I know all the recipes, but it's unclear how you get a
resource
in the right place.

There might be a way to do this with scripts on the server, but that's not
a
general solution (and how do I make sure that the script is run after
Apache
and Collectd resources are finished?).

-=Dan=-

On Wed, Oct 7, 2009 at 6:04 PM, Garret Heaton powdahound@gmail.com wrote:

  1. [...]
    This also means that you couldn't use the apache cookbook
    on a system which didn't have the collectd cookbook.

Exactly, but I want my recipes to be modular.

  1. Check the node's variables in the collectd config templates and only
    enable the config you need.
    <% if @node[:mysql] -%>

The problem is that you have no idea if the MySQL recipe is called or
not .. You only have the attributes, which are always defined. So you
will always copy the collectd-mysql config file, even if MySQL is not
going to be installed.

Would love to have a better solution to this problem.

Looks like light weight resources/providers might help, but I'm still
trying to wrap my head around them.

-=Dan=-

On Tue, Oct 13, 2009 at 1:23 PM, Dan DeMaggio dan@animoto.com wrote:

This also means that you couldn't use the apache cookbook
on a system which didn't have the collectd cookbook.

Exactly, but I want my recipes to be modular.

My instinct is to put this stuff in a collectd cookbook, rather than
have the apache cookbook embed collectd resources.

  1. Check the node's variables in the collectd config templates and only
    enable the config you need.
    <% if @node[:mysql] -%>

The problem is that you have no idea if the MySQL recipe is called or
not .. You only have the attributes, which are always defined. So you
will always copy the collectd-mysql config file, even if MySQL is not
going to be installed.

Would love to have a better solution to this problem.

Looks like light weight resources/providers might help, but I'm still
trying to wrap my head around them.

I would set a node attribute in the recipe itself, in an innocuous
enough namespace, and then use that attribute in the
collectd/munin/etc recipes see what should be configured.
Essentially, you're sending a message to yourself, saying "please
monitor/trend this".

Something like:

Apache Recipe

node.set[:monitor][:apache2] = true

Collectd Recipe

if node[:monitor][:apache2]
... do some stuff to enable ...
else
... do some stuff to disable ...
end

if node[:monitor][:mysql]
... do some stuff ...
end

The basic gist is, if the recipe is applied, then you should monitor
it. You can also do this:

if node.recipe?('apache2')
end

And avoid setting an attribute altogether.

In either case, you'll want to make sure that the collectd recipe
comes last in the run list.

Adam

--
Opscode, Inc.
Adam Jacob, CTO
T: (206) 508-7449 E: adam@opscode.com