Handling exceptions for modules in Puppet

hierapuppetpuppetmaster

I have an LDAP module in Puppet that is used by 100 servers and edits about 10 files on all servers, before it runs authconfig –updateall to activate the new LDAP configuration.

Most (98) of these servers needs a standard access-1.conf as their access.conf, but 2 servers need access-2.conf. This is part of a big ldap module, so all 100 servers need 99% of that ldap module, but some servers (more in the future based on their role) need an exception for the access.conf.

[root@puppetmaster modules]# cat /etc/puppet/hieradata/environment/prd/webserver-03.yaml
classes:
– webserver
– webserver-apache-02

# Test variables
role: webserver
cluster: apache-02

I am thinking about using something like this in the manifests/init.pp:

$role = hiera('role');

if($role = 'webserver') {
    file { '/etc/security/access.conf':
            owner => 'root',
            group => 'root',
            mode => '644',
            content => template('ldap/access-2.conf'),
    }
else {
    file { '/etc/security/access.conf':
            owner => 'root',
            group => 'root',
            mode => '644',
            content => template('ldap/access-2.conf'),
    }
}

The DRY (Don't Repeat Yourself) principle is important to me, I would rather not clone an entire module. There will be many cases in the future where I will want to use roles to distribute specific files/configurations based on the role of the server, while still sharing a module with other servers.

What do you think of using this role: webserver and an if/else as a solution for handling this exception in the module?

Best Answer

You can use a custom fact to distinguish between them, and resolve a template using that fact:

class foo (
  $role,
  ){
    file { '/etc/security/access.conf':
        owner => 'root',
        group => 'root',
        mode => '644',
        content => template("$role.ldap/access-2.conf"),
    }
}

Using current facter version, it is easy to provide custom facts on your servers:

# cat /etc/facter/facts.d/datacenter.yaml
---
role: webserver
location: Oz

Then, depending on how you have configured your hierarchy, you can have a default role and roles per domain or host, an example:

---
:backends:
  - yaml
:hierarchy:
  - "%{::hostname}"
  - common
:yaml:
  :datadir: "/etc/puppet/hieradata/%{::domain}/%{::location}"

Here, location is also a custom fact, so it is easy to build custom hierarchies as well. To handle exceptions, write a custom fact, and let the common.yaml file hold the default values.