Puppet Language Essentials
The course is part of this learning path
Puppet is an IT automation system. If you need to install, configure, and update servers, then Puppet can help you tremendously. Instead of doing all of these tasks manually, you can tell Puppet to configure your servers for you.
Not only will Puppet free you from the drudgery of repetitive tasks, but you will also gain major benefits, such as consistency, reliability, speed of deployment, ease of recovery, and scalability.
Do you often have slightly different configurations on servers that are supposed to be identical? With Puppet, you’ll no longer have to figure out why something works on one server but doesn’t work on another one because Puppet will configure them in the same way. You’ll also have less downtime because there is less that can go wrong when everything is configured the way it’s supposed to be.
Do you always seem to be adding more servers? Provisioning servers is a breeze when Puppet already knows how to configure them.
This course will get you started on bringing these benefits to your network. It’s a hands-on course with exercises every step of the way to give you experience using Puppet. First, I will show you how to install Puppet on a virtual machine on your own desktop. Then you will use it as a test environment to learn how to write Puppet code to automate server configuration.
- Install Puppet server
- Use pre-built Puppet modules
- Use manifests, classes, resources, facts, nodes, and templates
- Create your own Puppet modules
We previously saw we can tell Puppet to copy a static file such as a simple configuration file to a node, but most of the time you will need Puppet to tweak the contents of a file based on the value of certain facts about the node.
For example, if you were writing a module to configure Apache, the config file entry for the location of the ServerRoot would be different for Debian based systems and Red Hat based systems.
Now you could, in theory, just have a different static config file for each OS family. But that would be maintenance nightmare because most of the entries in the config file would be the same for all OS families. So if you ever needed to change any of those lines, you'd have to change them in every single config file. It would be much better to have a single file with variables in it based on the OS family. Puppet calls this type of file a template.
Now I'm going to show you how we can make our motd Apache module more robust by using a template.
Suppose instead of just having the message of the day tell us what the Apache service is called, we also want it to tell us the location of Apache ServerRoot and document root. Although we could do all of this in our module's main manifest, it would make more sense to create a template and just have the main manifest use the template. That way if we need to add more functionality to the module then the main manifest won't be cluttered with config file details.
Before we get started it's important to know Puppet supports two different templating languages: EPP and ERB. EPP wasn't available until Puppet 3.5 so a lot of the Puppet templates out there are written in ERB. However, I strongly recommend that you use EPP instead because EPP uses the Puppet language. It stands for Embedded Puppet. Whereas ERB uses Ruby. It stands for Embedded Ruby. So with EPP the language is consistent between your other Puppet files and your templates. Also, unlike ERB, EPP supports parameters and it has a much cleaner way of accessing variables.
First we have to create a directory for our template because the Puppet module generate command didn't create one. It should be called templates. Let's call our template motd.epp. Although you don't have to use the EPP extension you definitely should so that it will be obvious which templating language it uses.
Let's do something simple first. Let's just write a sentence that says the name of the operating system. Now what fact do we need to insert here? Let's have a look at the list of core facts again. Oh yeah, it's the name element of the OS fact. We saw that one last time.
In an EPP template when you need to insert some Puppet code, you just put some special tags around it. The two main types of tags are Expression-printing and Non-printing tags. Use Expression-printing tags when you want to insert an expression that will be evaluated and printed in the file. Use Non-printing tags when you need to insert some code that won't print anything. In this case, we need to use an Expression-printing tag because we want to print the name of the operating system.
Now we need to go back to the main manifest and tell it to use this template. First we'll erase the selector we put in before. Then we'll change the value of the content attribute to be the template we just created. We do that with the EPP function, which is a built in function that knows how to interpret templates written in EPP. To call a function you just use the function name and follow it with brackets surrounding any arguments you need to pass. In this case the argument is the name of the template.
First we put in a quote, then the name of the module where the template resides, then a slash then the template's file name. Notice that this is not the path name, because it doesn't mention the template's directory. It's just the module name slash the template file name. Then put in a closing quote and closing bracket.
Okay, let's give it a try. Yes, it says that we're running Ubuntu.
Now that our template is working, let's put in the information about Apache's service name, service root, and document root. The three new lines are very similar to the line we already put in about the OS name. I'll skip ahead instead of making you watch me type them in.
You can see that in each case there is a variable surrounded by an Expression-printing tag. I used variables instead of facts because Puppet doesn't have any built-in facts about Apache. So we'll have to set these variables first.
We could use a selector again but since we will be setting three variables for each OS family it might be easier to read if we use a case statement to organize the information by OS family. Since we will be writing code that just sets variables rather than printing anything, we need to use a Non-printing tag. Then we type case followed by an expression that we'll resolve to a value. In this case we want the value to be the name of the OS family. So we'll put in the built-in fact for that. Then we put in an opening brace.
On the next line, we put in one possible value, we'll start with Debian, and we'll put it in quotes because it's a string. Then a colon and another opening brace.
On the next three lines, we'll set the three variables to the appropriate Apache information. I'll just skip ahead again.
Then we add a closing brace and another potential value for the OS family, Red Hat.
I'll skip ahead after filling in the rest of the case statement.
Now we'll put in a closing brace for the whole case statement. Also close off the Non-printing tag. This time we'll use a slightly different closing tag because we don't want this code to produce a black line in the motd file. You would think that a Non-printing tag wouldn't print anything, but it actually prints a new line unless you use a closing tag that strips that out. The closing tag that does this is the same except that it starts with a dash.
Alright let's see if it works. Great, it printed out the right Apache information for Ubuntu.
That's it for this lesson.
About the Author
Guy launched his first training website in 1995 and he's been helping people learn IT technologies ever since. He has been a sysadmin, instructor, sales engineer, IT manager, and entrepreneur. In his most recent venture, he founded and led a cloud-based training infrastructure company that provided virtual labs for some of the largest software vendors in the world. Guy’s passion is making complex technology easy to understand. His activities outside of work have included riding an elephant and skydiving (although not at the same time).