preventing duplicate parameter values in puppet types


I am writing a keepalived module for puppet. It will naturally be called: “puppet-keepalived”, and I will be releasing the code in the near future! In any case, if you’re familiar with VRRP, you’ll know that each managed link (eg: resource or VIP) has a common routerid and password which are shared among all members in the group. It is important that these parameters are unique across the type definitions on a single node.

Here is an example of two different instance definitions in puppet:

keepalived::vrrp { 'VI_NET':
    state => ...,
    routerid => 42, # must be unique
    password => 'somelongpassword...',
}

keepalived::vrrp { 'VI_DMZ':
    state => ...,
    routerid => 43, # must be unique
    password => 'somedifferentlongpassword...',
}

Here puppet guarantees that the $name variable is unique. Let’s extend this magic with a trick to make sure that routerid and password are too. Here is an excerpt from the relevant puppet definition:

define keepalived::vrrp(
    $state,
    ...
    $routerid,
    $password
) {
    ...
    file { "/etc/keepalived/${instance}.vrrp":
        content => template('keepalived/keepalived.vrrp.erb'),
        ...
        ensure => present,
        # NOTE: add unnecessary alias names so that if one of those
        # variables appears more than once, an error will be raised.
        alias => ["password-${password}", "routerid-${routerid}"],
    }
    ...
}

As you can see, multiple alias names are specified with an array, and since this file definition is used for each keepalived::vrrp instance, you’ll most assuredly cause a “duplicate alias” issue if there is a duplicate routerid or password used!

This trick will also probably work across define types too. To ensure a common key, just create an object like:

file { '/root/the_unique_key':
    alias => ["token1-${token1}", "token2-${token2}", "token3-${token3}"],
}

The token prefix will guarantee that you don’t accidentally cause a collision between dissimilar parameter values, unless that’s what you want. I’ve used a file in this scenario, but you can use whatever object you like. Because of this reason, it would make sense to create a noop() type if you’re really serious about this. Maybe puppet labs can add a built-in type upstream.

This is the type of thing that’s important to do if you want to write puppet code that acts less like a templating hack and more like a library :)

Happy hacking!

James


You can follow James on Mastodon for more frequent updates and other random thoughts.
You can follow James on Twitter for more frequent updates and other random thoughts.
You can support James on GitHub if you'd like to help sustain this kind of content.
You can support James on Patreon if you'd like to help sustain this kind of content.


Comments

Nothing yet.


Post a comment



(sorry but the spammers were getting too crazy!)

Thank you

Your comment has been submitted and will be published if it gets approved.

Click here to see the patch you generated.

OK