Starting out with Puppet

Puppet is an open-source automation software for IT. It can be used to control PC like you were controlling them by hand, but in an automated fashion. This is pretty useful in many scenarios, mostly for corporate environments where managing workstations and servers can be a real pain if it’s done manually, but it has its uses even in home scenarios or small businesses.

The present post is created to be used as an example reference for anybody starting out with Puppet. The Puppet documentation is pretty comprehensive and useful so I’m not going to cover installation details or post installation details, nor how Puppet works. This assumes that you have an understanding of Puppet and what’s running in the back and you want an example Puppet configuration that will get you started. Normally, this can be found in the Puppet documentation but the link is long dead.

 

puppet-dir-structure

The configuration that I’ve started with looks like above. The PUPPETROOT is usually located in /etc/puppet for Debian based distributions. We are interested in the manifests/ folder and the modules/ folder. Puppet uses, as default, the site.pp file to send and apply configurations. In other words, every configuration that we want to apply, should reside in this file, somehow. The file can get pretty crowded, but there are ways to separate your commands in a logical way.

I created a test module, where I’ve added some simple commands. You can create the files yourself, but it’s recommended to create them using the module generate command, like below:

puppet module generate <yourname-themodulename>

puppet module generate vat-test

After generating a module, a folder will be created in the modules/ directory, with the appropriate files. We are only interested in the the manifests folder inside the newly created folder. This folder will contain an automatically generated file called init.pp. In the init.pp we will declare the class with same name as the module. In this case “test”.  The first 4 files in the diagram above (site.pp,nodes.pp,init.pp,mysuperclass.pp) and their contents can be found below.

As I wanted to get the feeling on how Puppet works, I created a simple class that does basic tasks. They are explained in comments below. To be noted – the configuration below uses additional modules that can be easily installed by using

puppet module install <module name>

The modules in our case are puppetlabs-firewall and puppetlabs-stdlib.

puppet module install puppetlabs-firewall

puppet module install puppetlabs-stdlib

sdas

  • site.pp

import “nodes.pp”

  • nodes.pp

# changes that apply only to the machine with the hostname “puppet”

node puppet {

# a file name testfile with the contents ‘created by puppet test’ is to be in the /tmp/ directory
file { ‘testfile’:
path => ‘/tmp/testfile’,
ensure => present,
content => ‘created by puppet test’,
}
}

# changes that apply only to the machine with the hostname “ubuntu”

node ubuntu {
include test

include test::mysuperclass
}

  • init.pp

class test {
include stdlib
include firewall

# a folder named “dir” is to be created in /tmp/ with the permmisions below

file { ‘/tmp/dir’:
ensure => directory,
mode => 0644,
}

# a new firewall rule is created, that accepts all ICMP packets

firewall { ‘000 accept all icmp requests’:
proto => ‘icmp’,
action => ‘accept’,
}
}

  • mysuperclass.pp

class test::mysuperclass {
file { ‘superclassfile’:
name => ‘superclassfile’,
ensure => present,
path => ‘/tmp/superclassfile’,
}
}

You can also download the files mentioned above and copy directly to your Puppet root folder, from here. To test the configurations above, you must either have a machine with the hostname of “ubuntu” or “puppet”. If not, change the node declaration above to the one that suits your environment. The configurations can be pushed from the server to the client by running :

puppet agent –test –server=’ubuntu’

Or you could have the client requesting the configurations by running the following on the client machine:

puppet agent –test

 

Problems

Could not retrieve catalog from remote server : error 400 on server : could not find class <> for <> on node <>

Earlier when we have generated the new module, a folder has been created according to the name give – in my case it was “vat-test”. After changing the name to “test” I could have pushed the configuration without any problems and the error stopped from showing. The idea is that the module folder should have the same name as the module and the same name as the main class in the init.pp file (when we are generating a new module. we are required to name it based on a username-modulename, thus naming the folder accordingly).