Entries filed under: Blog

Back to Index

Module of the Week: Puppet Module Tool – Part 2

Posted on
By
Kelsey Hightower
in
Blog, DevOps, How to, Module of the Week, Modules, Systems Management
Responses
3 Comments »

This week we’ll wrap up our coverage of the Puppet Module Tool (PMT) by exploring the install, upgrade, and uninstall commands. Lets jump right in.

PMT Install

The install command installs modules from the Forge using the full name of the module (author-module). We can install the “puppetlabs-apache” module like this:

Installing a specific version

We can also install a specific version of a module using the --version (-v) flag:

PMT now enforces SemVer when installing modules. If a module does not meet SemVer requirements it will fail to install.

Automatic dependencies resolution

One of the major enhancements to PMT is the ability to automatically resolve and install module dependencies. Once a manual process is now completely automated:

Notice that the install command grabs the requested module, puppetlabs-bacula, and its depenedencies: puppetlabs-mysql, puppetlabs-sqlite, and puppetlabs-stdlib.

PMT Upgrade

PMT also sports the ability to upgrade installed modules:

From the output we can see that we have upgraded the “puppetlabs-stdlib” module from version 2.2.1 to 2.3.1.

PMT Uninstall

Before this release of PMT, users had to manually remove modules from their module paths. While something like “rm -rf /etc/puppet/modules/stdlib” works, it’s not what we call user friendly. This version of the module tool greatly improves the experience around uninstalling modules.

Be sure to use the full module name when uninstalling modules or you’ll get the following error:

Notice the helpful error message suggesting that maybe you meant “puppetlabs-stdlib”, and in fact we did:

Look before you leap

The uninstall commands also checks for local changes and broken dependenices before uninstalling a module. Check out what happens if I try and uninstall the “puppetlabs-mysql” module:

PMT stops you with an error because uninstalling puppetlabs-mysql would leave the puppetlabs-bacula module with an unmet a dependency. You can by-pass this error by using the --force flag, but you can’t say we didn’t warn you!

Conclusion

PMT has been greatly enhanced to provide a much better experience when consuming modulew from the Puppet Forge. With the new list, search, install, upgrade, and uninstall commands managing modules couldn’t be easier.

Additional Resources

Module of the Week: Puppet Module Tool – Part 1

Posted on
By
Kelsey Hightower
in
Blog, Community, Module of the Week, Modules, Systems Management, Tips
Responses
3 Comments »

This week we’re going to begin our coverage of the Puppet Module Tool (PMT). The PMT is the command-line interface to the Puppet Forge—an online repository for re-usable Puppet modules. As of Puppet 2.7.14 and Puppet Enterprise 2.5 PMT is no longer a separate product; it’s now part of Puppet Core. What this means for you is that PMT is ready-to-go out of the box.

New features

The latest version of PMT offers a few new features over the previous stand-alone tool:

  • Search the Puppet Forge from the command line
  • List, upgrade, and uninstall modules
  • Automatically resolve and install module dependencies

In this post we’ll take a look at the new search and list commands.

PMT Search

The search command searches a repository for modules whose names, descriptions, or keywords match the provided search term. For example, if we search for the term “tomcat”, we would get the following output:

Notice the results include modules that match based on keywords and the module name.

PMT List

The list command lists the installed Puppet modules in our modulepath.

Notice the apache module has a version number of (???). This is because an apache module is installed but does not have a valid metadata file. If you would like to see how the installed modules relate to each other, use the --tree flag:

Highlighting problems

The list command will also report any issues with your module path:

The warning message is telling us that we are missing the puppetlabs-mysql module, which is required by the puppetlabs-bacula module. The PMT list command even lets us know which version of puppetlabs-mysql is required. A lot of work when into making the output communicate effectively. Notice the visual label used to highlight the “UNMET DEPENDENCY” in the tree output.

Conclusion

The new PMT is now bundled with Puppet and is ready to use out of the box. The new list and search commands allow you to search for modules on the Forge, and list currently installed modules. The list command also sports the ability to report issues with our installed modules.

Join us next week as we discover how to streamline the installation and maintenance of modules available on the Puppet Forge. We’ll wrap up our coverage of the PMT by taking look at the new upgrade and uninstall commands. We’ll also explore the enhancements made to the install command which greatly simplifies installing modules and their dependencies.

Additional Resources

Announcing Puppet Labs CTO Nigel Kersten

Posted on
By
Nigel Kersten
in
Blog, Community, Company, General News, Puppet Lore
Responses
13 Comments »

This week I took on the role of CTO at Puppet Labs, and started reflecting on the awesome journey that led me here.

It was 2006, and I was scrambling to make it onto the last bus back to San Francisco from the Apple WWDC Beer Bash down in Cupertino. I’d been to quite a few Beer Bashes and knew the drill: forget the lineup for the campus store, just concentrate on finding beer and the few Apple employees who could fix the OpenDirectory bugs that were making my life hell. Both objectives were completed, leaving me only minutes to avoid having to spend way too much money getting a taxi back up to the city.

Fatefully, I found a seat next to this intensely opinionated sysadmin, Jeff McCune (later to become one of the first pro services guys at Puppet Labs, and now one of our core developers). He recognized me from my WWDC presentation that year and started grilling me about how I ran my university campus, particularly the file-based configuration management system I used, Radmind, and the hacked up framework I’d put in place to try to manage higher level objects than mere files.

He’d been to a talk by Luke Kanies (now the CEO of Puppet Labs) at LISA and was very excited about this guy who had built a tool that worked the way sysadmins actually needed to work with a pragmatic, model-based approach. Even more importantly though, Luke was serious about fostering adoption, and had helped Jeff write some useful extensions for Puppet. Jeff had already gotten religion about idempotent, declarative approaches for sysadmins, and spent pretty much all of the bus ride bending my ear about this new project called “Puppet” and how it was going to change the world of operations.

After WWDC, I flew back to Australia, fully intending to try out this magical Puppet project, but got distracted by the day to day life of running campus IT operations on a shoestring budget for users who were academics and artists.

I was even more distracted a few months later when one of the MacEnterprise community members came out of lurking and told me I should apply for a role at Google in Mountain View. Several of the toughest interviews of my life followed, and within a couple of months, I was moving my young family to the other side of the world to run Mac Operations at Google HQ.

It was clear that tools like Radmind simply weren’t going to work at Google for the many thousands of corporate Macs. Opinionated engineers who demanded a high degree of customization, immense growth, globally distributed offices and a very small team meant that it was completely insane to even think about trying the old methods of file-based config management of the entire system.

We needed a better and more sustainable way, a solution that gave us higher levels of abstraction with meaningful entities such as users, groups, services and packages, and that didn’t require you manage the entire machine.

Jeff and I had kept in contact, and he was presenting on Puppet at WWDC that year. I popped up to San Francisco with some of my coworkers, and made sure we turned up to his talk.

10 minutes into his presentation we were getting pretty excited, and we started experimenting over VPN. By the time Jeff finished his talk, we had a working Puppet master back at Google managing the contents and permissions of a few critical files in /etc, and knew we had a great match.

As it turned out, the Mac deployment was such a rapid success that one of the Linux Ops team started a skunkworks project to manage the internal Linux distro with Puppet, as there had been a few failed CFEngine attempts. This worked so well that Puppet eventually managed all the Google corporate Mac and Linux desktops, laptops and servers.

Puppet was a much younger project in those days. We were building a lot of custom Puppet extensions for Mac OS X that went back into the core, and were having to scale Puppet to manage tens of thousands of nodes, so I spent a lot of time on the mailing lists and IRC channels brainstorming with Luke and the community. I quickly fell in love with the community. It was full of thoughtful sysadmins, people who were frustrated with the unreliable state of operations tools, and knew there was a better way out there than continually reinventing arcane bash/ssh frameworks.

We have some great technology with Puppet, but one of our greatest strengths is our outstanding community.

I ended up at the first ever Puppet Camp, San Francisco, 2009. It was small, but was one of the most exhilarating conferences I’ve ever been to. I love looking back at those photos and seeing how many of that group are now part of the Puppet Labs team. Dan Bode, James Turnbull, Ben Hughes, Gary Larizza, Michael Stahnke, Carl Caum, Deepak Giridharagopal (Little known fact: his last name is actually Tamil for “Grid Computing”).

That’s an awesome group of people to end up working with, let alone all the other great people we have here at Puppet Labs.

I had an amazing couple of years at Google, surrounded by super sharp minds and working on truly interesting operations problems at a scale greater than anything I’d ever touched before, but I was starting to look enviously at friends who left for early stage startups and the breadth of knowledge they were acquiring. Luke had poked me a couple of times about coming to work for him, but I didn’t seriously consider it until late 2010 when he, Teyo and James made a much more concerted effort.

“You’re opinionated about Puppet. Want to put your money where your mouth is?”

One visit to Portland and I knew I wanted to live in this awesome food, beer, and cycling-obsessed city full of people following obscure passions. I jumped ship from Google and we moved north, where I dived headfirst into being responsible for Product at a very quickly growing startup.

It’s been an immense 18 months. We started with our first commercial release, Puppet Enterprise 1.0, and followed that up with several great releases, all solving real problems for real users. We’ve brought on the open source MCollective and Hiera projects from the incomparable RI Pienaar, released Puppet 2.7.0, and grown at an amazing pace. We’ve grown from 2 events a year to 15, including the incredibly successful PuppetConf `11 and are building up to an even bigger PuppetConf this year. Nothing like startup speed to quicken the blood.

From the original 20 odd folks I started with in the tiny office in the seedy and urine-drenched Old Town to our shiny digs in the Pearl, with over 80 employees. From a distinct lack of in-house beverages to decent espresso and delicious local beer. From a company that knew the user experience was critical, to one with a growing UX/Design department headed up by Randall of the impenetrable Gandalf gaze.

I love this company. I love what we’ve done already to change the face of operations, I love the ambition we have to change it even more, and I especially love the people I get to do it with.

I’m thrilled to take on the role of CTO, and to concentrate on fostering our culture of technical innovation so that we continue to build applications and platforms that truly advance the state of IT infrastructure. The world of operations is undergoing radical change right now. The cloud, pervasive virtualization, corporate adoption of FOSS, BYOD, IaaS, PaaS and SaaS are all forcing sysadmins to be truly agile and adaptive. Some of the brightest people in our industry work in operations, and it’s going to be incredible to see what they come up with when IT automation gives them space to concentrate on genuinely important matters.

Module of the Week: jmcdonagh/clamav – Manage ClamAV and the freshclam service

Posted on
By
Joe McDonagh
in
Blog, Community, Extending Puppet, guest post, How to, Module of the Week, Modules, Open Source
Responses
0 Comments
Purpose Comprehensive clamav and freshclam classes
Module jmcdonagh/clamav
Puppet Version 2.6+
Platforms Ubuntu 10.04 LTS+

ClamAV is an open-source scanning engine for malware, virus, and trojan detection. It is often used in conjunction with an MTA such as Postfix. It comes with a built-in service for AV signature updates called freshclam.

This module is intended to offer a comprehensive interface for Puppet to configure both freshclam and clamav services. Each class takes many parameters, all of which are down-cased versions of clamav or freshclam configuration options. Both the clamav and clamav::freshclam classes are also intended to be easily removed from a system, by setting their $ensure parameters to ‘absent’.

Installing the module

Complexity Easy
Installation Time 5 minutes

This module is on Puppet Forge and can be installed with puppet’s module sub-command:

puppet module install jmcdonagh/clamav

Note that if you run this as a regular user, the module will be installed in your home directory. If you are root, it will probably go into /etc/puppet/modules.

Module and Resource Overview

First, you should either check out the code from GitHub (https://github.com/thesilentpenguin/puppet-clamav), or install the module with the module tool as outlined above and browse the code with your favorite editor. I recommend having the manifest open while I walk you through the code.

Let’s have a look at the clamav base class in manifests/init.pp. Scroll down to the beginning of the class and you will immediately notice that there are many parameters. These parameters were taken from the clamav man pages on Ubuntu 10.04 LTS systems, and down-cased to maintain status quo code style.

After all the parameters, we’ve got some sanity checks. We’ll fail the catalog compilation (using the fail() function) if we get passed any bizarre values or we’re trying to compile a catalog for an incompatible system. One of my stock checks is a minimum OS version. This is a pretty good practice for numerous reasons. For one, it helps consumers know where your code is intended to be used. That is absolutely crucial if you will be supporting this code. Before someone breaks a Solaris system using a Debian-only manifest, the compilation simply fails and outputs a clear error.

After the sanity checks, various variables are set based on the value of $ensure. This will alleviate the need to use selectors inside resource definitions, which can lead to hard-to-read and thus hard-to-understand code. Here is the code that I am referring to which sets all of these variables based on $ensure:

   if ($ensure == "present") {
  	$file_notify    = Service["clamav-daemon"]
  	$file_require   = Package["clamav-daemon"]
  	$svc_before	= undef
  	$svc_enable	= "true"
  	$svc_ensure	= "running"
  	$svc_require    = Package["clamav-daemon"]
   } else {
  	$file_notify    = undef
  	$file_require   = undef
  	$svc_before	= Package["clamav-daemon"]
  	$svc_enable	= "false"
  	$svc_ensure	= "stopped"
  	$svc_require    = undef
   }

You may have noticed that some of these variables appear to be relationship targets. This is because I always attempt to include the ability to remove all of a class’ resources properly. You’ll notice that, if removing the clamav class by setting $ensure to ‘absent’, the resource requirements go the opposite direction of the way they go with $ensure set to ‘present’. You might get away with using $ensure in this manner and not reversing relationships, but for me it’s not worth taking that chance, and I just do it right the first time.

Now onto the actual resources. The clamav and freshclam classes are what I call FPS classes. That is, File-Package-Service classes. What I mean by this is that there is a Package to install, configuration File(s) to set up, and a Service to manage. The Service and File(s) Require(s) the Package, and the File(s) Notify the Service. This paradigm is likely common to you if you have been using Puppet for some time now.

So first you’ll notice clam’s configuration file. This is a template that references all the class parameters to configure clamav. It uses some of the variables defined above to set up relationships and notify the service.

Next is the Package resources, which include a couple of extras. I include the dev packages because a lot of my work involves the rubygem ecosystem. This means that when I have a requirement for software on a system, I often need the -dev packages to compile extensions. Remember, now that you have parameterized classes at your disposal, it is trivial to add boolean features to your modules such as ‘$dev_packages = “true”’. That could serve as an option to include or not include the management of the -dev packages.

Finally we have the service. Not much here, mostly all configured via the variables defined based on $ensure. All our resources look nice and compact thanks to that variable setting stanza.

The clamav::freshclam class is also an FPS class. It is similar in the sense that it has every freshclam configuration option down-cased as a class parameter. The only noticeable difference between the two classes is the actual clamav and freshclam configuration options.

Testing the module

This module is most easily tested by using ‘include clamav’, which will by default set up clamav on the current system.

puppet apply -e ‘include clamav’ clamav/manifests/init.pp

If you do this on an incompatible system, you should see something like this:

Your OS (Darwin) is not supported by this code! at /etc/puppet/modules/clamav/manifests/init.pp:104 on node goldmember.microcosm.thesilentpenguin.com

After this successfully finishes on a compatible system, you should be able to see the clamav daemon running:

[~] > sudo service clamav-daemon status
 * clamd is running

You can test the config by scanning a test file by using the clamdscan program:

[~] > clamdscan website.erb
/home/jmcdonagh/website.erb: OK
 
----------- SCAN SUMMARY -----------
Infected files: 0
Time: 0.017 sec (0 m 0 s)

The freshclam class can be tested in the same way.

Configuring the module

Complexity Easy
Installation Time 5 minutes

The module configuration should be sane by default. Every parameter available in the Ubuntu 10.04 LTS repo version of clam should be available. The default values for the various parameters should match the defaults in Ubuntu 10.04 LTS. If you need to tweak any setting whatsoever, simply look up the configuration option in the clam man page, down-case all upper-case letters, and pass that as a parameter to the class. For example:

class {
   “clamav”:
      ensure    => “present”,
      logsyslog => “true”;
}

Would set up clamav with the LogSyslog clamav configuration option set to true.

Example usage

The same usage outlined above for testing is a typical use case of clamav. Simply enable those classes in the node definition and you will have a working clam setup, ready to check for malicious content coming in through e-mail. You could even potentially integrate clam with other services, like scanning user uploads to your custom webapp. Freshclam will update from the canonical repo every day with the default settings, ensuring you have the latest virus definitions.

Conclusion

To me, this module is an ideal example of module design. It is small in scope, yet as complete as possible of an interface to the clam configuration. This allows for you to easily set up clamav and freshclam on a node with nearly no tweaking or external dependencies necessary. If you end up needing some tweaking, as you have seen it is trivial to make small changes to clam with this module. It also has some basic compatibility checks to ensure your consumers know where this module will work.

This module would probably work on Debian 6, but I haven’t tested. To add Red Hat support some variables for the package and service name(s) would probably have to be added, and all of my gigs that use clam are on Ubuntu 10.04 LTS.

Additional Resources

Join us for PuppetConf 2012

Posted on
By
jose
in
Blog, Community, Conferences and Workshops, General News, Open Source, Puppet Enterprise, PuppetConf, Tips, Training
Responses
0 Comments

Registration for PuppetConf ’12 is now open. We’re in a new city and a new facility, with new tracks and new programs. Look forward to 5 concurrent tracks over 2 days focusing on all things operations. Our new venue offers one large theater for keynotes, while our second auditorium will be dedicated to Puppet Community presentations and hacking space. We’re introducing a hands-on lab component to the conference, and we’re happy to announce that we’ll be offering the first ever Puppet Admin and Puppet Developer Certification exams at PuppetConf.

With over 70 speakers, 600+ community members, and the Puppet Labs team, PuppetConf is a must-attend event. We’re looking forward to seeing you in San Francisco!

Here’s a quick recap of last year:

All 2011 talks can be viewed on the Puppet Labs YouTube Channel.

Puppet Labs Announces Support for OpenStack

Posted on
By
Dan Bode
in
Cloud, Community, Extending Puppet, Modules, Solutions
Responses
1 Comment »

Coinciding with this week’s OpenStack Summit in San Francisco, today we’re pleased to highlight the great community efforts around the Puppet modules for OpenStack. Working together, Puppet Labs and OpenStack community members Cisco, Red Hat, Rackspace, Morphlabs, and eNovance have designed and developed a collection of modules that allow sysadmins to automatically provision, configure, and manage OpenStack clouds with Puppet open source or Puppet Enterprise. The first of these modules, OpenStack cloud provisioning, is available today for free download from Puppet Forge.

Clouds & Community

Puppet and Puppet Enterprise already help sysadmins automatically provision and configure Amazon and VMware cloud infrastructures and now, together with the community, we’re bringing these capabilities to OpenStack. While OpenStack is a relative cloud newcomer, since its launch in the summer of 2010 it’s grown by leaps and bounds, and now boasts an active community of over 2,600 people representing more than 160 organizations.

These modules are a great demonstration of the benefits of community collaboration. For example, from the get-go the community pushed the project to be cross-platform, to support multiple different operating systems, back-end databases, and hypervisors. In addition, not only have community members been a great sources of innovation, but, in the true spirit of open source, the many eyeballs have made all (well, almost all ;-) bugs shallow.

Join Us!

You can check-out the first fruits of these efforts right now by downloading the OpenStack cloud provisioning module for free from Puppet Forge. In addition, we’re here at the OpenStack conference all week and throwing a special get-together tomorrow night Wednesday, April 18 5pm-8pm (follow us on Twitter @puppetlabs for details). We’d love to hear about your experience with OpenStack and your ideas about how to make Puppet + OpenStack even better!

Puppetize early and often,
- Dan

Learn More

Puppet Labs at AWS Cloud Summit, EucaDay NYC, and Puppet Camp NYC

Posted on
By
jose
in
Blog, Cloud, Community, Conferences and Workshops, General News, Puppet Camp
Responses
1 Comment »

Spring is the time to be in New York. We know it, and apparently so do our partners. Whether you live in or around New York or just happen to be in town visiting over the next two weeks come find us at these awesome events:

Module of the Week: rtyler/jenkins – Continuous Integration Server

Posted on
By
Jeff McCune
in
Blog, Community, Extending Puppet, How to, Module of the Week, Modules, Open Source, Tips
Responses
3 Comments »
Purpose Jenkins is an extensible, open source continuous integration server.
Module rtyler/jenkins
Puppet Version 2.7+
Platforms Enterprise Linux 5 and 6, Debian 6, Ubuntu

This week’s module helps implement and manage Jenkins CI with Puppet. We all need to test our code when we make changes. Saying so is easy, doing so is a lot more difficult. Jenkins makes testing easier. Every time you make a change, Jenkins will test everything still works. It’s easy to get started with Jenkins by using a Puppet module written by R. Tyler Croy. This module automatically installs the Jenkins software, configures the service, and provides an simple way to add functionality by automatically installing any of the 400+ Jenkins plugins. You should give this module a spin if you’re looking for an easy way to try out Jenkins or puppetize an existing Jenkins server. Install it, classify a node with the jenkins class in the Puppet Enterprise Console and Jenkins is running and ready to do your bidding.

Installing the module

Complexity Easy
Installation Time 5 minutes

Installing the Jenkins module is straightforward. The module is published on the Puppet Forge so we’re able to install it directly onto a Puppet Master system with one command. In this example we’re going to use Puppet Enterprise 2.5 to install the module on our Puppet Master. Then we’ll classify a Ubuntu Lucid node with the jenkins class and see how Puppet automatically brings up the Jenkins console web interface.

In this example we’ve installed Puppet Enterprise 2.5 on a CentOS 6.2 machine. (Note: if you don’t have Puppet Enterprise, you can easily install this module using the puppet-module gem or upgrade to Puppet 2.7.13 or later to get the puppet module subcommand.)

root@pe-centos6:~# puppet module install rtyler-jenkins
Preparing to install into /etc/puppetlabs/puppet/modules ...
Downloading from http://forge.puppetlabs.com ...
Installing -- do not interrupt ...
/etc/puppetlabs/puppet/modules
└─┬ rtyler-jenkins (v0.2.2)
  └── puppetlabs-apt (v0.0.2)
root@pe-centos6:~#

Now that we have the Jenkins module installed, we just need to add the jenkins class to the configuration catalog of an agent system. In this example I’m going to use the Puppet Enterprise Console to do this, but you could just as easily accomplish this using a node declaration in your site.pp manifest in Puppet.

First, we’ll add the jenkins class to the Puppet Enterprise Console. To do this we click the “Add Class” button in the bottom left corner of the console, and name it “jenkins”:

Once the jenkins class has been added to the Puppet Enterprise Console we can create a group to associate our Ubuntu Lucid node with the jenkins class. This image shows the “Add group” screen:

Once we click “Create” the jenkins class will be included in the configuration catalog of the Ubuntu Lucid node. Let’s see what this looks like on the Puppet Agent now.

root@pe-ubuntu-lucid:~# puppet agent --test
info: Retrieving plugin
info: Loading facts in /var/opt/lib/pe-puppet/lib/facter/puppet_vardir.rb
info: Loading facts in /var/opt/lib/pe-puppet/lib/facter/facter_dot_d.rb
info: Loading facts in /var/opt/lib/pe-puppet/lib/facter/root_home.rb
info: Caching catalog for pe-ubuntu-lucid.2012-04-09.15837
info: Applying configuration version '1334091722'
notice: /Stage[main]/Jenkins/Package[jre]/ensure: \
  current_value purged, should be 1.7.0 (noop)
notice: Class[Jenkins]: Would have triggered 'refresh' from 1 events
notice: /Stage[main]/Jenkins::Repo::Debian/Apt::Source[jenkins]/\
  Apt::Key[Add key: D50582E6 from Apt::Source jenkins]/\
    Exec[3ae8ac921fb6f9e7a9be3adca21e45c2226e43b2]/returns: \
      executed successfully
notice: /Stage[main]/Jenkins::Repo::Debian/Apt::Source[jenkins]/\
  File[jenkins.list]/ensure: \
    defined content as '{md5}941681fa47a0a1b579f98bce22bbcaf6'
info: /Stage[main]/Jenkins::Repo::Debian/Apt::Source[jenkins]/\
  File[jenkins.list]: Scheduling refresh of Exec[jenkins apt update]
notice: /Stage[main]/Jenkins::Repo::Debian/Apt::Source[jenkins]/\
  Exec[jenkins apt update]: Triggered 'refresh' from 1 events
notice: /Stage[main]/Jenkins::Package/\
  Package[jenkins]/ensure: ensure changed 'purged' to 'present'
notice: Finished catalog run in 150.88 seconds
root@pe-ubuntu-lucid:~#

Once puppet agent finished, the Jenkins service will be available at http://HOSTNAME:8080/ where HOSTNAME is the hostname of the node Puppet configured Jenkins on. You should expect to see something like this:

In the next section we’ll cover some additional resources that make it easier to manage and automate Jenkins plugins.

Resource Overview

The main jenkins class is be the only class you need to add to your node classification. The module contains other classes, but these are automatically managed for you by the jenkins class.

Jenkins is a very extensible CI system. Jenkins-ci.org provides over 400 plugins to customize it to your specific needs. The Jenkins module makes it easy to manage these plugins with Puppet by defining the jenkins::plugin resource type.

Jenkins cannot monitor a Git repository for changes by default, but developers and system administrators often need to have their jobs run when they publish changes to a Git repository. Jenkins helps solve this problem by providing a Git plugin allowing Jenkins to automatically clone Git repositories and poll them for changes.

To have Puppet automatically install and manage the Git plugin, declare a jenkins::plugin resource in the nodes configuration catalog. In this example, I’m going to create a new class named site::jenkins_plugins and declare the necessary resource. We’ll then add this new class and see how Puppet automatically manages the service.

Here’s the copy of /etc/puppetlabs/puppet/modules/site/manifests/jenkins_plugins.pp that defines the class:

# = Class: site::jenkins_plugins
#
#   This class manages the Jenkins plugins we want to use at our site.
#
# = Requires
#
#   puppet module install rtyler-jenkins
#
# = Sample Usage
#
#   include site::jenkins_plugins
#
# (MARKUP: http://links.puppetlabs.com/puppet_manifest_documentation)
class site::jenkins_plugins {
  # This resource default will ensure the Jenkins service
  # restarts automatically after Puppet configures all plugins.
  Jenkins::Plugin { notify => Class[jenkins::service] }
  # Tell Puppet to configure and manage the Jenkins Git Plugin.
  jenkins::plugin { 'git': }
}

With this class in place in a manifest we simply need to classify the Lucid system with this site::jenkins_plugin class like we did before with the jenkins class.

First, add the class to the Puppet Enterprise Console:

Then, update the jenkins group to also contain the site::jenkins_plugins class. This will associate nodes in this group with both the jenkins and the site::jenkins_plugins class.

Finally, run puppet agent on the Lucid node to apply the new configuration with the Git plugin resource.

root@pe-ubuntu-lucid:~# puppet agent --test
info: Retrieving plugin
info: Loading facts in /var/opt/lib/pe-puppet/lib/facter/puppet_vardir.rb
info: Loading facts in /var/opt/lib/pe-puppet/lib/facter/facter_dot_d.rb
info: Loading facts in /var/opt/lib/pe-puppet/lib/facter/root_home.rb
info: Caching catalog for pe-ubuntu-lucid.2012-04-09.15837
info: Applying configuration version '1334094999'
notice: /Stage[main]/Jenkins/Package[jre]/ensure: \
  current_value purged, should be 1.7.0 (noop)
notice: /Stage[main]/Site::Jenkins_plugins/Jenkins::Plugin[git]/\
  Group[jenkins]/ensure: created
notice: /Stage[main]/Site::Jenkins_plugins/Jenkins::Plugin[git]/\
  User[jenkins]/gid: gid changed '65534' to 'jenkins'
notice: /Stage[main]/Site::Jenkins_plugins/Jenkins::Plugin[git]/\
  File[/var/lib/jenkins]/group: group changed 'adm' to 'jenkins'
notice: /Stage[main]/Site::Jenkins_plugins/Jenkins::Plugin[git]/\
  File[/var/lib/jenkins/plugins]/group: group changed 'nogroup' to 'jenkins'
notice: /Stage[main]/Site::Jenkins_plugins/Jenkins::Plugin[git]/\
  Exec[download-git]/returns: executed successfully
info: /Stage[main]/Site::Jenkins_plugins/Jenkins::Plugin[git]/\
  Exec[download-git]: Scheduling refresh of Service[jenkins]
info: Jenkins::Plugin[git]: Scheduling refresh of Class[Jenkins::Service]
notice: Class[Jenkins]: Would have triggered 'refresh' from 1 events
info: Class[Jenkins::Service]: Scheduling refresh of Service[jenkins]
notice: /Stage[main]/Jenkins::Service/Service[jenkins]: \
  Triggered 'refresh' from 2 events
notice: Finished catalog run in 11.37 seconds
root@pe-ubuntu-lucid:~#

After running Puppet, we’re able to see the newly installed plugin in the Jenkins console interface.

The Jenkins module would be pretty darn good if all it did was install the package and manage the Jenkins service automatically. In this section we’ve seen that the module puts forth some extra effort and makes it easy to install and activate additional functionality in Jenkins through the use of a Puppet defined resource type. This combination allows you, as a Puppet user, to easily get started with Jenkins and customize it to your specific needs. All with only a few commands and a couple of lines of Puppet.

Conclusion

In this post we walked through installation and use of R. Tyler’s jenkins module, which allows us to automatically run the Jenkins service and manage the Git plugin. With this configuration, we’re ready to start automatically watching our Git repositories for changes and running automated tests after each change. Not only does this module provide an easy and fast way to configure the Jenkins service on RHEL and Ubuntu systems, it provides an easy way to install any of the 400+ Plugins available on jenkins-ci.org.

If you’re interested in contributing to the Jenkins module some good features would be the ability to manage jobs using Puppet resources and adding additional platform support. Pull requests are always welcome!

Additional Resources

Writing Great Modules: An Introduction

Posted on
By
Ryan Coleman
in
Blog, Community, DevOps, Extending Puppet, How to, Module of the Week, Modules, Open Source, Tips
Responses
1 Comment »

We’re taking a brief break from your regularly scheduled module of the week goodness with a mini series to discuss some of the elements that go into writing great Puppet modules. I’ll try to sum it up in a few sentences:

Your module should be immediately useful to me after I install it. Documentation should be complete and the code itself should adhere to the community style guide. If I need to modify the behavior of your module, you should provide me an interface to do it so I don’t have to modify your modules manifests. If I contribute features or bug fixes, I expect you to explain the process and collaborate with me on improving the module.

I’ll be honest, writing a module isn’t always an easy task, and all the things discussed here will add time and complexity to that module. This multi-part series on writing great modules is all about giving you the knowledge and tools to make your module more reusable, immediately useful to others and easier for your team and the community at large to maintain. My theory is that time spent initially building a more robust module will return you ten-fold the value over the life of that module in your environment.

With that in mind, I hope you find these concepts useful and return to the series next time as I dig deeper, leaving you to build your next great Puppet Forge module!

Before We Begin

If you’re new to Puppet Modules or simply want a refresher, our incredible documentation team has recently created a page on Module Fundamentals.

De-Duplication and Collaboration

To borrow a phrase, “An hour in the Forge can save you days in the editor.” There are over 300 modules in the Puppet Forge now, covering any number of things. When you get that itch for your next Puppet module, try searching the Puppet Forge first. If you find something you like that suits your need, awesome! If you find something that is mostly what you want but need some features, consider contributing to the author’s module instead of creating your own. Here are a couple of great docs to help you in consuming or publishing a Forge module:

Documentation

So you’ve written an awesome module that conjures unicorns from the cloud and you’ve published it to the Puppet Forge. But when I download it, I shouldn’t have to dig into your manifest’s directory and read the code just to figure out how it works. Documentation is key to quality modules that people will use.

There’s really no secret sauce here, just write some text about your module, addressing the following questions:

  • What does your module do?
  • Does your module require anything else to function?
  • How should I declare your class(es)? Include example usage for each piece of functionality.
  • How can the user customize the module’s behavior? (parameters, etc)
  • Where can the user turn for help?
  • Would you like contributors? What’s the process?

At the very least, these questions should be addressed in the module’s README file but it’s also a good idea to place some appropriate documentation as comments above each class definition. Puppet ships with a subcommand called doc which will help you generate those commands into plain text (perhaps providing your README’s content) or can even build a html-filled folder of rdoc goodness.

Take a look at Carl Caum’s Bacula module for example. He clearly spells out what the module claims to do, what its requirements are and how to use it. If you take a look at this modules manifests, each has fairly robust comments in-line explaining usage and implementation decisions. Between the two, both users and contributors have most of the information they’ll need.

Testing

It may sound obvious that you should test your module, but you really should. To start, this means making sure your module does what you claimed it can do in your documentation. This is commonly and pretty simply solved with smoke tests. As an overview, we have a great docs article on writing, running, and reading smoke tests.

On a basic level, this means you test your module’s functionality against the operating systems you claim to support and include the puppet code you used to conduct your tests (usually class declarations) in the tests folder of your module. This convention allows consumers of your module to easily rerun the smoke tests you ran but also serve as great ways for someone to quickly try out its functionality. If a contributor to your module adds new functionality, make sure they include a smoke test for you to use.

Extra Credit: Smoke tests are great, but some members of the Puppet community are building automated tests for their modules. The big two I’m aware of are rspec-puppet and cucumber-puppet. These are advanced techniques that come with a steep learning curve but if you’re curious, there’s a recent blog post on test driven development. Once achieved, these tests make it easy to protect against regressions when merging new code. If you’re investing heavily into Puppet, it may be worth your time to learn.

If you’re particularly interested in rspec-puppet, the project’s author has an awesome tutorial on rspec-puppet.com.

Interfaces

When I download your module, I shouldn’t have to modify your code to do something awesome with it. It’s really tempting to code just for your environment and call it a day but a little extra effort will get you a module others can use and contribute to!

When you come across something that may need tuning depending on the user’s situation, build a way for that user to modify your module’s behavior without touching your manifests directory.

Let’s say for example you have a motd module with a motd class for setting the contents of /etc/motd. You wrote the class to build /etc/motd from a template that includes your company’s name in it. If I want to reuse your module, I’ll have to modify your template or your manifest. This presents a challenge to reusability. Instead, a little extra Puppet code can provide me with a way to modify your module’s behavior.

For example, provide two parameters (source & template) in a parameterized class. With a little bit of extra conditional logic and variables, users can specify their own template in the class declaration like this:

class { 'motd':
  template => template('motd/my_template.erb'),
}

All they’ll need to do is drop their template into the templates folder or they could even specify a template from an entirely different location. As they’re writing the template function, they can even concatenate multiple templates together!

Let’s look an example of how this can be done.

# Static class with hard-coded template
class motd {
 
  file { '/etc/motd':
    ensure  => file,
    mode    => '0644',
    owner   => 'root',
    group   => 'root',
    content => template('motd/my_template.erb'),
  } 
 
}
## Example declaration with the built-in template
include motd
 
## Or specify your own template
class { 'motd':
  template => template('mymodule/mytemplate.erb'),
}
 
## Even specify your own static file
class { 'motd':
  source => 'puppet:///modules/mymodule/myfile',
}
 
# Class with an interface for serving files vs templates
class motd (
  $template = '',
  $source = '',
) {
 
  # Fail gracefully if user tries to supply both source and template
  if $template and $source {
    fail('You cannot supply both template and source to the motd class')
  }
 
  # If nothing is specified, default to our template
  # If something was specfied, set the motd_* variable
  if $template == '' and $source == '' {
    $motd_template = template('motd/default_template.erb')
  } elsif $source != '' {
    $motd_source = $source
  } elsif $template != '' {
    $motd_template = $template
  } 
 
  file { '/etc/motd':
    ensure  => file,
    mode    => '0644',
    owner   => 'root',
    group   => 'root',
    content => $motd_template,
    source  => $motd_source,
  } 
 
}

This is a fairly simple pattern but hopefully it makes sense. Again, we’re just leveraging the tools in Puppet’s language to make it easy for users of our module to use it in their environment without creating code they have to maintain themselves. Please invest some time thinking about this problem when you write your modules.

Versioning

A version number is required when you submit a module to the Forge. Version numbers can be tricky. In a place like the Puppet Forge, the versioning scheme you came up with for your modules may rock and make perfect sense to you and your team but may be completely different than the system I came up with for mine. How are you, as a module consumer, supposed to translate between the two and know at a glance whether functionality will fundamentally change between 1.0.1 and 1.1.0?

My recommendation is to follow the Semantic Versioning specification when you’re publishing that next release. In the author’s words: “Under this scheme, version numbers and the way they change convey meaning about the underlying code and what has been modified from one version to the next.” We strive to follow this approach at Puppet Labs for modules we write and my hope is that each Forge user will as well.

Style

In the same way consistent versioning is important; consistent, clean and usable code is important. When you hear someone ask, “Does this module adhere to The Style Guide?”, they are asking about the latter. We host a document on our website that we call the Style Guide. It’s a collection of stylistic preferences and code structure best practices that was originally written to help our organization develop code that we could all easily read and develop in a uniform manner. It’s even more appropriate for the large, distributed audience consuming and contributing modules to the Puppet Forge.

So read and adhere to the Style Guide. Do it for your teammates, do it for the Forge. To make that task easier, Tim Sharpe (@rodjek) maintains an awesome tool called puppet-lint. Like a dryer dutifully collects dead sock fibers, puppet-lint will scan your manifest code and alert you to certain violations against the Style Guide.

gem install puppet-lint
[root@centos6 modules]# cat helloworld/manifests/init.pp 
class helloworld {
  notify { 'example':
    message => "Hello World!",
  }
}
[root@centos6 modules]# puppet-lint helloworld/manifests/init.pp 
WARNING: double quoted string containing no variables on line 3

Puppet-lint doesn’t replace the Style Guide, so I encourage you to read it and keep it handy. You will find that it covers more than just the code styling that puppet-lint checks for. These are great tools to keep your code consistent, clean and consumable.

Publishing

Once you’re finished writing your module, you’ll want to publish it to the Puppet Forge. I’ll cover that, more on these techniques and more advanced concepts next time. I’ll also discuss updates to the Puppet Module tool which also now ships with Puppet Enterprise. If you’d like to whet your appetite, check out this quick Puppet Module Tool screencast created by one of the developers responsible for the tool updates.

Now What?

The Puppet Forge now has over three hundred modules helping sysadmins solve problems all over the map. You’ve got our Module of the Week blog series continuing to highlight great work and with Puppet Enterprise 2.5, you’ve got a greatly improved command-line Forge experience. Let’s carry this momentum on to over six hundred awesome modules by PuppetConf 2012, and see you next time!

Additional Resources

Puppet Labs is Sustainability at Work Gold Certified

Posted on
By
Nandini Mitra
in
Blog, Community, Company, General News
Responses
1 Comment »

Puppet Labs has been on a roll…and this time it is not our user community, but the physical one we live in that is giving rave reviews! The City of Portland’s Sustainability at Work Program recently announced Puppet Labs as a Gold Certification winner!

It all began with the culture here…they care about their community and take immense pride in doing their bit for the environment. Most of the Puppet Labs employees (80% to be precise) come to work on bikes, public transport, or on foot. They even have an in-house bike rack in their dining/meeting area!

The company is housed in a LEED Gold building, and the employees adopt energy efficient measures in their daily lives. “Daily life” includes bringing dogs to work, eating cupcakes and drinking from the kegorator at weekly meetings, and recycling most of what they throw into the bins. Even the copious coffee habit comes with a green benefit, with buckets of grounds being saved for employees’ gardens. In keeping with the relaxed yet results-driven work environment, I saw people coming up with ways to make the company greener—not because they were looking for an award, but because caring about the environment comes naturally to them.

I should introduce myself: I’m an MBA student from the University of Oregon, and I helped document all the environmentally friendly activities going on at Puppet Labs. I reported the activities to Sustainability at Work in the areas of Energy (e.g. the T8 lighting, the energy star equipment), Water (e.g. we have tap water not bottled water, we have water-saving faucets), Materials and Waste (we do cardboard, glass recycling, we avoid printing out documents) and Transportation. Beyond activities in these four areas, there’s also an internal portal with postings about various volunteering opportunities, sustainable transportation options, green living etc. Once I gathered all the information, we used the Sustainability at Work calculator to report our work to City of Portland. There was another round of reporting where we filled in another checklist of actions. The final round had a City of Portland expert come over for an on-site verification process. Finally, Puppet Labs received the highest possible certification, GOLD!

Puppet Labs is one of the 7 businesses in Portland to be gold certified, and the only software company. This certification holds good for the next three years. The City of Portland’s website has already featured Puppet Labs as a Gold Winner. Mayor Sam Adams (those of you who visited Portland for PuppetConf last year may remember him speaking) had the following statement:

“Congratulations to Puppet Labs, Inc. on becoming Sustainability at Work Gold Certified. We appreciate Puppet Labs, Inc.’s leadership in taking concrete actions to make Portland a better place to live and work. We hope that Puppet Labs, Inc.’s achievement inspires other businesses to make innovative changes that improve profitability and sustainability.”

This is a great achievement for Puppet Labs, and we feel proud to be recognized as a responsible environmental and community steward.