3

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
  }
}
Zoredache
  • 128,755
  • 40
  • 271
  • 413

2 Answers2

7

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
Dominic Cleal
  • 3,120
  • 17
  • 16
  • This looks like exactly what I need. I never noticed ths in the docs before. Any idea what version of puppet ths feature requires? – Zoredache Dec 17 '11 at 10:27
  • It's been in Puppet for a long time, at least as far back as 0.24.x! Puppet Labs publish the type documentation for every version so you can check compatibility, change the version number in [this URL](http://docs.puppetlabs.com/references/2.7.6/type.html#schedule). – Dominic Cleal Dec 17 '11 at 10:30
  • So, is this approach recommended over configuring a crontab job from puppet ? – Paul Praet May 27 '15 at 14:34
  • I don't think I'd replace cronjobs with schedules. Keep schedules for circumstances like this, when you want to change configuration resources only at certain times of the day, or a limited number of times. Cronjobs are good at what they do, running commands on a regular interval. – Dominic Cleal May 28 '15 at 07:21
3

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.

sysadmin1138
  • 131,083
  • 18
  • 173
  • 296
  • As much as this feels like using a sledge on a finishing nail, it is the most elegant method I can think of. Doing a run against that environment via cron once a day will probably do exactly what he wants. – Scott Pack Dec 17 '11 at 01:17
  • I am actually already using environments for testing/production. I was kind hoping there was some other method. If no other alternatives are presented, this is what I was probably going to do. – Zoredache Dec 17 '11 at 01:25