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
In our previous examples, we used pre-built modules. Now we're going to build a module ourselves.
Suppose you want to be able to look up a computer-related acronym with a simple Linux command. You can do this with the dict command, but it won't work if you just install the dict package in your Linux system. You also need to install the dictd daemon and the dict-vera acronym dictionary, create a config file that tells the dict command what dictionary to use, and start the dictd service.
This sequence of installing packages, creating config files, and starting services is such a common task for Puppet to perform that it is known as the Package, File, Service pattern. So it is extremely useful to learn how to implement this pattern.
Puppet thinks of a host as a collection of resources. Some examples of resources are the apache2 package, the etc/motd file, the httpd daemon, and a user account named fred. A resource is essentially something that Puppet can configure on a host.
Each resource belongs to a resource type. For example, the apache package is a package, the etc/motd file is a file, the httpd daemon is a service, and fred is a user.
Puppet has about 50 built-in resource types, but the ones you will use the most are packages, files and services. It is also possible to create your own custom resource types, but we're not going to cover that in this course.
Before we start declaring resources for our dictionary project, we need to create a directory for our module. First, we need to go to the modules directory. Then we'll run the Puppet module generate command. Remember that we want to use the skip interview option. And we have to put the author and a hyphen before the module name. Let's call this module dict.
Okay, let's edit the init.pp manifest. Now we'll scroll past the comments and start writing our code after the opening line of the class definition. The first thing we need to do is tell Puppet to install the three dict packages.
Let's start with the dict package. First we put in the resource type, which in this case is package. Then we put in a curly brace and the name of the package in quotes, which is referred to as the title of the resource, followed by a colon.
On the next line, we need to set the attributes of this resource. That is, we need to tell Puppet what to do with this resource. What we want is for this package to be installed. The way we do that is to use the ensure attribute. We say ensure followed by a hash rocket, followed by what state we want this package to be in, which is installed.
Finally, we need to put a closing brace on the next line.
What this package declaration tells Puppet is that we want the dict package to be installed. If it's not, then install it. If it's already installed, then don't do anything. In other words, ensure that this package is installed.
The Puppet language is different from a typical programming language, because instead of coding how to do something, we code the state that we want the resource to be in and Puppet makes it happen.
By the way, did you notice we used the same syntax when we declared this package resource as we did when we declared the motd class? That's because we were using the resource syntax to declare the motd class.
Before we write any more code, let's test what we've written so far. First we'll save the file. Before we test it, let's make sure that the dict package isn't already installed. We'll use the dpkg -l command. And pipe it to grep dict. Okay, it didn't find anything, so it's not installed.
Now we'll run Puppet apply. Remember that we have to run this on the init.pp file in the examples directory, not the one we just edited in the manifest directory. It says that it created the dict package. Let's double check. Yes, it's installed now.
Okay, let's add the other two packages. We could just add two more package declarations like the one we did for dict, but there's a faster way. This is kind of an advanced feature I'm going to show you. If you try to put more than one title, that is, package name in this case, in your resource declaration, then you'll get a syntax error. But Puppet will let you do it if you put the strings in an array. The syntax for an array is straightforward, too. You just put square brackets around the list and separate the strings with commas, like this. We'll add dictd and dict-vera, and a closing square bracket.
That's all you have to do to install all three packages. Let's save the file and test it out. It worked.
Now, taking care of the config file will take a bit more work because we need to create the file and put it somewhere first. The standard place to put static files is in a directory called files. The Puppet module generate command doesn't create a files directory, so we'll have to create one.
The config file for dict is, not surprisingly, called dict.conf. So, let's create that in the files directory. The configuration for dict is very simple. You just need to give it a list of dictionary servers. We're only going to put local hosts in our list, so we just need to type server localhost.
Now let's edit the main manifest again and add the dict.conf file. To declare a file resource, you just type file, then a curly brace, then a title, which in this case is etc/dictd/dict.conf. And remember to put the file name in quotes. Then add a colon.
On the next line we need to tell it where to get the file from. The attribute name for that is source. Then you put a hash rocket and the location of the source file. When you've stored your source file in a module directory like we've done, then you need to specify the path with a special Puppet notation. First we start with a quote, and then the word Puppet and a colon, then we use three slashes, not two, then we put modules/ and then the name of the module, in this case dict. Slash, and then the name of the file and a closing quote. You'll notice that this is not the path name to the file, even though it looks like it. Because it doesn't include the files directory. If you did include the files directory between dict and dict.conf, then it won't work. Finally, we put a closing brace on the next line.
Let's give it a try. We'll save the file and run Puppet apply again. You can see that it created the dict.conf file and put some content in it. Let's make sure that I put the right content in. Yes, it worked.
Okay, we're almost done. The final step is to declare the dictd service. By now you can probably guess what the first line should be. Go on, take a guess. Did you say that it should have service, and then a curly brace, and then the service name in quotes, and then a colon? If you did, then you're right.
The attribute we need to use on the next line is also pretty predictable. It's ensure, just like we used for the packages. There is a difference, though. We're going to set it to a different value. For the packages, we set it to the value installed. For a service, that doesn't make sense. We're going to set it to the value running.
Now we just put in the closing brace, and we're done.
Now we'll run Puppet apply again. Hmm, it didn't seem to do anything. Well, that's because when we installed the dictd package, it also started the dictd daemon. To fully test our new code, we need to stop the service first. Now, let's run Puppet apply again Great, as you can see, it changed the state of the dictd service from stopped to running. Let's just double check. Yes, it is indeed running.
Now that the code is working, let's add it to the node definition in the site.pp file so it will run whenever we do a full Puppet run. We just need to include dict in the node definition.
Before we test it, let's stop the dictd service again so Puppet will have something to do. And to make sure the motd setup module still works, let's delete the motd file, too. Okay, now let's do a full Puppet run. We're using Puppet agent -t instead of Puppet apply. Great, it created the motd file, and it started the dictd service.
Hey, I just realized that we haven't actually used the dict command to make sure it works. Hmm, what acronym should we look up to test it? I seem to recall that EMACS is an acronym, so let's try that. Hmm, "Eight Megabytes and Constantly Swapping." Somehow I don't think that's what it really stands for. Oh, I guess it actually stands for "Editing MACros." Well, that might be the real one, but I kinda like the first one better. No offense to all you EMACS fans out there, I like EMACS too. And now, I think it's time to end 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).