puppet: stop service before overwriting file

Solution 1:

Have a look at the transition module. With that, you can do something like this:

transition { 'stop foo service':
  resource   => Service['foo'],
  attributes => { ensure => stopped },
  prior_to   => File['/etc/foo.conf'],
}

file { '/etc/foo.conf':
  ensure  => file,
  content => epp('my_module/etc/foo.conf.epp'),
}

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

No exec's required.

Solution 2:

You could do something like this:

file { '/etc/foo.conf.tmp':
  ensure  => file,
  content => epp('my_module/etc/foo.conf.epp'),
}

exec { 'stop service':
  command => 'service foo stop',
  refreshonly => true,
  subscribe => File['/etc/foo.conf.tmp']
}

exec { 'update file':
  command => 'cp /etc/foo.conf.tmp /etc/foo.conf',
  subscribe => Exec['stop service'],
  refreshonly => true,
}

exec { 'start service':
  command => 'service foo start',
  subscribe => Exec['update file'],
  refreshonly => true,
}

The refreshonly attribute of the exec resource will ensure the command is only run when it received an event, in this case via the subscribe attribute. In this case, it will only stop the server and copy in the new settings file when your tmp settings file is changed. The tmp file will allow you to manage the your settings on the server without the service overwriting it.

You could combine those three execs into a single command like so

file { '/etc/foo.conf.tmp':
  ensure  => file,
  content => epp('my_module/etc/foo.conf.epp'),
}

exec { 'update settings':
  command => 'service foo stop && cp /etc/foo.conf.tmp /etc/foo.conf && service foo start',
  refreshonly => true,
  subscribe => File['/etc/foo.conf.tmp']
}