How do I evaluate a class not on every puppet run?
I would like to have a method that only evaluates a particular class once a day at a specific time. Right now I am running my puppet agent from the cron, but I would like to change it to either run as a daemon, or run more frequently. The barrier with increasing the frequency is that there is one class that takes about 4 minutes to process, and doesn't need to happen very often. I am trying to find some method to only evaluate that particular class once a day from cron.
Is there a simple method for me to set an environment variable (FOO=bar;puppet agent ..
), or add a command line option (puppet agent .. --foo bar
) to the crontab that will become a fact I can use in my manifests to include or not include the class?
class foobar {
if 'bar' == $::foo {
# do the slow stuff
}
}
A schedule sounds like it'll provide what you're looking for. First you create a schedule resource that specifies when things can run and how many times in a given period.
schedule { "slow":
range => "1 - 5",
period => daily,
repeat => 1,
}
The example above will only be evaluated or run during the hours of 1am and 5am and a maximum of once. You can remove the range
parameter and it'll run any time of the day, but again, only once.
On resources, you then specify the schedule
meta-parameter to link them to the above schedule:
exec { "example":
command => "/usr/bin/foo",
unless => "/usr/bin/bar",
schedule => "slow",
}
When you run Puppet with --debug
, you'll now see the following if it's already been evaluated the given number of times, or the range isn't applicable:
debug: /Stage[main]//Exec[example]: Not scheduled
If you've got a few resources, you could use resource defaults inside the class you're restricting to affect all resources of the same type:
Exec {
schedule => "slow",
}
You'd need to do this for each resource type - Exec, File, Augeas etc.
Couple of notes on improving this:
- I don't know a way to apply it to all types of resources in the class
- Applying the
schedule
meta-parameter to a class doesn't appear to work, might be worth raising a bug
I believe you can accomplish this via an Environment declaration. You invoke it on the command-line:
puppet agent --environment latetbus
You can use it to specify a different manifest in the puppet.conf file:
[latebus]
manifest = $confdir/latetbus/site.pp
And even can do different modules that way.
There is also a method for adding custom facts to facter. This leverages plugins to make work. You create a custom ruby file to check for something:
# run_latebus.rb
facter.add("latebus_exec") do
setcode do
%x{if [ -e /tmp/run_latebus ] ; then echo "true" ; else echo "false" ; fi}.chomp
end
end
Where the puppet agent invocation script would touch /etc/run_latebus
before starting puppet agent
, which is evaluated by Facter during the puppet run.
The .rb file is placed in a custom module, specifically in the lib/facter
directory of the module itself.