DevOps Zone is brought to you in partnership with:

A developer and occasional sysadmin based in Cambridge, UK. Normally found using Python or Ruby (or both) to do good, he's also obsessed with automation and development environments. In what some people call spare time he curates the newsletter, organises events for developers and systems administrators in London and hacks on open source projects like vagrant, cloudfountry and tools for django. Gareth is a DZone MVB and is not an employee of DZone and has posted 48 posts at DZone. You can read more from them at their website. View Full User Profile

Setting Puppet Class Using Environment Variables

  • submit to reddit
I’m not sure how novel this approach is but a few folks at work hadn’t seen it before so I thought it worth jotting down.

If you have even a small but dynamic set of servers then a problem arises with how those nodes are defined in puppet. A node remember is defined in puppet like so:

node {
  include web_server

The problem is twofold. If you have a growing infrastructure, that list of nodes is going to get quickly out of hand. The other problem is around provisioning new hosts, the obvious approach to which is something like:

1. Summon new EC2 instance
2. Change the node definition to include the new hostname
3. Install puppet on instance and so the ssl certificate signing dance
4. Run puppet

Step 2 stands out. The others are easily automated, but do you want to automate a change to your puppet manifests and a redeploy to the puppetmaster for a new instance? Probably not.
Puppet has the concept of an external node classifier which can be used to solve this problem, but another simpler approach is to use an environment variable on the new machine.

Lets say we define our nodes something like this instead:

node default {
  case $machine_role {
    frontend:           { include web_server }
    backend:            { include app_server }
    data:               { include db_server }
    monitoring:         { include monitoring_server }
    development:        { include development }
    default:            { include base }

If a machine runs and sets the $machine_role variable to frontend it includes the web_server class, if that variable equals ‘data’ it’s going to include the db_server class instead. Much cleaner and more maintainable in my view. Now to set that variable.

Facter is the tool used by Puppet to get system information like the operating system or processor count. You can use these facter provided variables anywhere in your manifests. And one way of adding a new fact is via an environment variable on the client. Any environment variable prefixed with FACTER_ will be available in Puppet manifests. So in this case we can:

export FACTER_machine_role=frontend

So our steps from above become something like:

1. Summon new machine
2. echo “export FACTER_machine_role=backend” >> /etc/environment
3. Install puppet on instance and so the ssl certificate signing dance
4. Run puppet

Much easier to automate. And if you’re looking at a box and want to know what it’s role is you can check the relevant environment variable.


Published at DZone with permission of Gareth Rushgrove, author and DZone MVB.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)