Puppet: Running shell command when file (or package) is updated

puppet

I want to run mysql_tzinfo_to_sql whenever the tzinfo package (on Ubuntu Server) changes. I figured Puppet can take care of this.

I thought that either Puppet would react to a change in the package version, or if not, then to a change in timestamps of a file contained in the package.

The only way I can see to do this is to have a resource with no direct action, and have an exec depending on it.

The questions I have are:

  1. Is it possible to define a file
    that is only used to Notify another resource (such as exec)?
  2. Is it possible to
    define a package resource so that another resource (such as exec) is activated
    when the package changes or updates?
  3. Is it possible to
    define an exec resource that runs a
    shell command line (with pipes and redirection for instance) instead of a
    command from the filesystem?

Taken all together, it seems overwhelming.

FOLLOWUP: Fantastic answers! In the interest of completeness (and for the record), I should note the following:

  1. The complete shell command of interest is
    mysql_tzinfo_to_sql | mysql -u root -p password
    (it loads tzinfo into a MySQL database for MySQL use).
  2. Auditing of /etc/tzinfo would be futile as this is merely the
    local time zone configuration; the goal is to watch for changes
    in the tzinfo data itself (thus the watching of /usr/share/zoneinfo).
  3. Likewise, the contents would be the wrong thing to watch – as they're likely
    not to change; the best would be to watch the mtime or all since the
    filetimes should change after every tzinfo update.

Also, James Turnbull wrote all about auditing when it was introduced. The Metaparameter Reference contains a short description of the workings of the audit parameter.

Best Answer

Use the audit attribute to track the file content or package version number and trigger the change by subscribing to the package resource. A few issues with this, this does not work with --noop because the state.yaml file will update the file md5 checksum/package version in --noop mode. I'm not sure if this is a pending bug since I can't track it down at the moment.

file { '/etc/tzinfo':
  audit => content,
}

exec { '/usr/bin/mysql_tzinfo_to_sql':
  subscribe => File['/etc/tzinfo'],
}

A more reliable method is just to duplicate the file elsewhere and use it to trigger updates (the location isn't important we are just tracking the original tzinfo as source).

file { '/etc/puppet/stage/tzinfo':
  source => '/etc/tzinfo',
}

exec { '/usr/bin/mysql_tzinfo_to_sql':
  subscribe => File['/etc/tzinfo'],
}

The second method of course does not work with packages, but you would avoid the --noop and state.yaml problems.

Regarding the third question, yes, you can use pipe and redirects (use an title and put the command in the command attribute):

exec { 
  '/bin/echo foo | grep foo > /tmp/foo':
}