Search code examples
puppet

validate_cmd in Puppet: supporting older versions


I have the following Puppet code:

file { "/etc/sudoers.d/${name}":
   content      => template('sudo/sudoers.erb'),
   owner        => 'root',
   group        => 'root'
   mode         => '0440',
   validate_cmd => '/usr/sbin/visudo -c -f %',
 }

However, validate_cmd was only added in Puppet > 3.5, and I have to support some systems running 3.2 and older.

Is there some clever way of monkey-patching this into older versions of Puppet, or should I just resign to using the puppetlabs-stdlib validate_cmd statement?

Which does a similar thing, but won't revert the file if it does not validate correctly (the main benefit of the validate_cmd parameter on a fle).

EDIT: Using Felix's overwrite syntax, I ended up with the following code:

file { "/etc/sudoers.d/${name}":
  content      => template('sudo/sudoers.erb'),
  owner        => 'root',
  group        => 'root',
  mode         => '0440',
}
if versioncmp($::puppetversion, '3.5') >= 0 {
  File["/etc/sudoers.d/${name}"] { validate_cmd => '/usr/sbin/visudo -c -f %' }
}
else {
  validate_cmd(template('sudo/sudoers.erb'), '/usr/sbin/visudo -c -f', 'Visudo failed to validate sudoers content')
}

It's a bit fiddly to test in puppet-rspec, I ended up going with this:

if (Puppet.version >= '3.5.0')
  context "validating content with puppet #{Puppet.version}" do
    let(:params) { { :users => ['joe'] } }
    let(:facts) {{ :puppetversion => Puppet.version }}

    it { should contain_file('/etc/sudoers.d/worlddomination').with_validate_cmd('/usr/sbin/visudo -c -f %') }
  end
else
  context "validating content with puppet #{Puppet.version}" do
    let(:params) { { :users => ['joe'] } }
    let(:facts) {{ :puppetversion => Puppet.version }}

    it { should contain_file('/etc/sudoers.d/worlddomination').with_validate_cmd(nil) }
  end
end

Solution

  • Your manifest can adjust its behavior to the agent version.

    file { "/etc/sudoers.d/${name}":
      content      => template('sudo/sudoers.erb'),
      owner        => 'root',
      group        => 'root'
      mode         => '0440',
    }
    
    if versioncmp($puppetversion, '3.5') >= 0 {
      File["/etc/sudoers.d/${name}"] { validate_cmd => '/usr/sbin/visudo -c -f %' }
    }
    else {
      # your workaround here
    }
    

    This will work courtesy of the puppetversion fact, of course.

    The override syntax File[<name>] { ... } can be used like this because the actual resource declaration specifies no value for the validate_cmd attribute.