Puppet’s Exec type is lying

Using puppet, you can trigger a command after a file is updated. This works really well where I want to update the sendmail.mc file, run make sendmail.cf and then restart the sendmail process. This is exactly what I want, but it didn’t work the way I expected.

Setup and Configuration

I have puppet configured to do all of the above via these three types:

service { 'sendmail':
     name => $operatingsystem ? {
          Solaris => $kernelrelease ? {
               '5.10' => 'svc:/network/smtp:sendmail',
               default => sendmail,
          },
          default => sendmail,
     },
     ensure => running,
     enable => true,
     pattern => $operatingsystem ? {
          FreeBSD => 'sendmail: accepting connections',
          default => undef,
     },
     subscribe => $operatingsystem ? {
          FreeBSD => [ File['sendmail.cf'], ],
          Solaris => [ File['sendmail.cf'], ],
          default => [ File['sendmail.cf'], File['/etc/sysconfig/sendmail'], ],
     },
     require => $operatingsystem ? {
          Solaris => $kernelrelease ? {
               '5.8' => [ Group['mail'], Pkg['sendmail'], Service['network'], File['sendmail.cf'] ],
               default => [ User['smmsp'], Group['smmsp'], Group['mail'], Pkg['sendmail'], Service['network'], File['sendmail.cf'] ],
          },
          FreeBSD => [ Group['mail'], Pkg['sendmail'], File['sendmail.cf'] ],
          default => [ Group['mail'], Pkg['sendmail'], Service['network'], File['sendmail.cf'] ],
     },
}

file { 'sendmail.mc':
     name => $operatingsystem ? {
          Solaris => '/etc/mail/cf/cf/sendmail.mc',
          default => '/etc/mail/sendmail.mc',
     },
     owner => 'root',
     group => $operatingsystem ? {
          FreeBSD => 'wheel',
          Solaris => 'mail',
          default => 'root',
     },
     mode => $operatingsystem ? {
          Solaris => 444,
          default => 644,
     },
     notify => [ Exec['make sendmail.cf'], ],
     content => template('mail/sendmail.mc.erb'),
     require => [ Pkg['sendmail'], ],
}

exec { 'make sendmail.cf':
     command => $operatingsystem ? {
          OpenSuSE => 'm4 sendmail.mc > sendmail.cf',
          default => 'make sendmail.cf',
     },
     cwd => $operatingsystem ? {
          Solaris => '/etc/mail/cf/cf',
          OpenSuSE => '/etc',
          default => '/etc/mail',
     },
     path => ['/usr/bin', '/usr/sbin', '/usr/ccs/bin'],
     creates => $operatingsystem ? {
         Solaris => '/etc/mail/cf/cf/sendmail.cf',
         OpenSuSE => '/etc/sendmail.cf',
         default => '/etc/mail/sendmail.cf',
     },
     subscribe => [ File['sendmail.mc'], ],
     refreshonly => true,
     notify => [ Service['sendmail'], ],
     require => $operatingsystem ? {
          OpenSuSE => [ File['sendmail.mc'], Pkg['sendmail-cf'], Pkg['m4'], ],
          default => [ File['sendmail.mc'], Pkg['sendmail-cf'], Pkg['make'], ],
     },
}

The Problem

When I update the sendmail.mc.erb template and perform a puppet run (puppet agent --test) I get this output:

...
info: /Stage[main]/Mail::Sendmail::Server/File[sendmail.mc] Filebucketed /etc/mail/sendmail.mc to puppet with sum cebefed3e17bf2a530289e84a7f250e7
notice: /Stage[main]/Mail::Sendmail::Server/File[sendmail.mc]/content content changed '{md5}cebefed3e17bf2a530289e84a7f250e7' to '{md5}b955c571473569ff48c5c392c98edbba'
info: /Stage[main]/Mail::Sendmail::Server/File[sendmail.mc] Scheduling refresh of Exec[make sendmail.cf] info: /Stage[main]/Mail::Sendmail::Server/File[sendmail.mc] Scheduling refresh of Exec[make sendmail.cf]
notice: /Stage[main]/Mail::Sendmail::Server/Exec[make sendmail.cf] Triggered 'refresh' from 2 events
info: /Stage[main]/Mail::Sendmail::Server/Exec[make sendmail.cf] Scheduling refresh of Service[sendmail]
notice: /Stage[main]/Mail::Sendmail::Server/Service[sendmail] Triggered 'refresh' from 1 events
...

If I do a ps, I see the sendmail process has been restarted, but an ls shows the sendmail.cf is older than the sendmail.mc file. Puppet is lying when it said it did the make sendmail.cf. Even using the --debug switch does not show any errors nor does it print out any extra information near the Triggered 'refresh' line.

The Issue and Solution

The other day I needed to create a locate class. I decided to use an exec type to run the updatedb command and used a creates tag. I defined the tag incorrectly on one class of hosts, so every 30 minutes it would rerun the updatedb command. This error triggered an epiphany: I have the creates in the make sendmail.cf exec type. I wondered if the creates tag was the source of my problem. Once I removed:


     creates => $operatingsystem ? {
          Solaris => '/etc/mail/cf/cf/sendmail.cf',
          OpenSuSE => '/etc/sendmail.cf',
          default => '/etc/mail/sendmail.cf', 
     },

… the exec works as I originally expected. The moral of the story is that creates takes precedence over subscribe/notify when triggering the execution of an exec type.