Is it possible to notify a File[] resource in Puppet and trigger resources subscribed to that file

puppet

We're using Puppet to manage an OpenStack installation. OpenStack
consists of a number of loosely connected parts, all communicating via
AMQP. Several of the parts use a common configuration file
(/etc/nova/nova.conf), so a typical service resource looks like
this:

service { 'openstack-nova-network':
  ensure    => running,
  enable    => true,
  subscribe => File['/etc/nova/nova.conf'],
}

This all works great.

Now we're using Puppet to install a hotfix to some of the underlying
Python code. When we replace one of the Python source files, we would
like to restart the services that make use of it. In general, this is
exactly the same set of services that are subscribed to
/etc/nova/nova.conf.

I was hoping I could do this take advantage of the existing
dependencies by notifying the file, like this…

file { '/path/to/some/file':
  source => 'puppet:///.../',
  notify => File['/etc/nova/nova.conf'],
}

…but this didn't appear to work. Other than putting in explicit
notify entries for every service, is there a better way to do this?

UPDATE

You know, I'm beginning to suspect my question wasn't entirely clear. I'd like to apologize for the confusion and try to make my request a little more explicit:

I realize I can do this with a set of explicit dependencies, either as subscribe values on the services or notify values on the installed files. The problem is that this means maintaining an M*N matrix of dependencies. Introducing a new file means either:

  • Updating M service resources, or
  • Updating N file resources

This sort of repetitive copy-and-paste work is prone to errors, especially when multiple people are responsible for the configuration.

One option would be to maintain a central list of services:

$services = [ service1, service2, service ]

Because then I could do this:

file { '/usr/lib/python/glance/notifier/notify_qpid.py':
  notify => Service[$services],
}

But that's not going to work, because the list of services is different on different hosts. Possibly I can flip this around and maintain a list of "hotfix" files:

$hotfix_files = [
  '/usr/lib/python2.6/site-packages/glance/notifier/notify_qpid.py',
  '/root/puppet/modules/openstack/files/nova/impl_qpid.py',
]

And then update all the service definitions once:

service { 'openstack-nova-network':
  ensure    => running,
  enable    => true,
  subscribe => [
    File['/etc/nova/nova.conf'],
    File[$hotfix_files],
  ]
}

But this still requires manually maintaining the list of modified files.

What I really want to do is say, "notify all the services that are subscribed to /etc/nova/nova.conf".

Best Answer

The main thing you are after, "notify all the services that are subscribed to /etc/nova/nova.conf", doesn't seem to be possible with file-resources. But, it works with exec-resources, with refreshonly-parameter. (Just tested similar configuration with Puppet 2.7.11). You must add a dummy exec-resource:

exec {'dummy-nova-refresh':
    command     => "/bin/true",
    refreshonly => true,
}

When the command is run, exec sends notification to all its subscribers. And refreshonly-parameter makes sure that command is run only on refresh.

Subscribe all services to this Exec:

service { 'openstack-nova-network':
    ensure    => running,
    enable    => true,
    subscribe => Exec['dummy-nova-refresh'],
}

And use notify from all file-resources. (Do this also for /etc/nova/nova.conf, or specify it in the subscribe list for each service):

file { '/path/to/some/file':
    source => 'puppet:///.../',
    notify => Exec['dummy-nova-refresh'],
}

And done. A change in any file triggers a refresh in all services subscribed to 'dummy-nova-refresh'.