Dominic Cleal's Blog

Cron, local time and DST with Puppet

Following on from my sleep(1) based hack to get certain cronjobs running at local times on a system configured for UTC, I've implemented a function to do this elegently from Puppet.

As Puppet's running regularly on the systems, it's possible to use a function that's given the local time and then on each run it performs the timezone conversion back to UTC. When DST arrives, the function output will automatically shift, the crontab gets updated and back again when DST is over.

The function needs RubyGems set up and the tzinfo gem installed (remember, on the puppetmaster, not the clients). This snippet then goes into your module, somewhere like modules/cron/plugins/puppet/parser/functions/tzhour.rb:

require 'rubygems'
require 'tzinfo'

module Puppet::Parser::Functions
    newfunction(:tzhour, :type => :rvalue) do |args|
        tz = TZInfo::Timezone.get(args[0])
        u = Time.now.utc
        localtm = Time.utc(u.year, u.month, u.day, args[1], u.min, u.sec)
        tz.local_to_utc(localtm).hour
    end
end

Next, the function can be used in the cron type:

cron { my-cron:
    command => "/my/cron.sh",
    user    => "root",
    hour    => tzhour("Europe/Amsterdam", 19),
    minute  => 45,
    weekday => [ Mon, Tue, Wed, Thu, Fri ],
}
If you're using multiple environments, watch out for bug #1775. If you get errors on the clients saying that the tzhour function can't be found, check the troubleshooting section on the Puppet wiki.
Archives