Puppet Design Patterns

Programming and software engineering have never been areas where I would consider myself strong. Quite frankly, it is the exact opposite. Digging into code and troubleshooting is fine, but writing code from scratch is still something I struggle with. As I have jumped onto a team with a dev guy turned ops guy, discussions about how we write puppet code have come up.

Starting with a discussion about where ancillary services get instantiated (I’ll cover that in a separate blog post), I started looking for more details about design patterns in puppet. The more I looked and asked questions, the more I realized there is not much out there. At this point, the only real reference I have found was Simple Puppet Module Structure Redux by R.I. Pienaar. This article does a good job covering a self contained module that sets up a self contained service, but it really lacks some of the more advanced use cases.

My plan at this point is to start the conversation. Below is a list of issues that I think could be well served by design patterns and discussions of anti-patterns. As time goes by my goal is to start writing posts that help to better shed light on what I see as the issue and ways I understand that we can solve it. My hope is that this will start the discussion, because I am definitely not the one to suggest the right way of doing things.

Design Pattern Areas

  • Ancillary Service Configuration (Post is about 50% done)
  • Distinguishing between types of modules. (i.e. Type and Provider, Building Blocks, Roles, etc.)
  • Interaction with environments

Just incase it wasn’t clear, I am lost when it comes time to all of this stuff. My hope is that those that have been there and done that can help shed some light on the right ways to move forward.

Update

So the first response I got to this post in IRC was to take a look at a Designing Puppet – Roles and Profiles by Craig Dunn. This is a great starting point for a lot of the thoughts I have had.

Puppet On Windows: First Thoughts

One of the things I didn’t expect when changing jobs was the amount of Windows Infrastructure I would be responsible for. While not expected, it will be an interesting challenge and is still very much a WebOps and not an enterprise Windows deployment. As we move forward with this infrastructure, there is a huge desire to puppetize it and manage it in a programatic way.

Setting Up a Dev Environment

As a long time Vagrant user and abuser, I started with attempting to setup a base box using Veewee and Vagrant. This was met with disaster. None of the templates I tried worked and, really, vagrant isn’t designed to handle Windows. But failure of this kind always seems to open new doors.

So, I cheated a bit. The veewee template left behind a floppy image with all the of the autounattend.xml stuff rolled inside. I created a new VM in VirtualBox, added a floppy controller, the virtual floppy disk and the Windows 2008 R2 iso. A few minutes later, I had a fully installed Windows 2008 R2 instance.

From there, I shared a folder with my Puppet manifests and modules, installed Puppet and the VirtualBox Guest Additions. At this point, I took a snapshot so I can easily revert back to where I started.

Out with the Package

So, what is the first thing you want to do when setting up a web server? Install the web server software, right? On a Linux box this looks something like:

1
2
3
4
5
6
7
8
package {"httpd":
  ensure => installed,
}

service {"httpd":
  ensure  => running,
  require => Package['httpd'],
}

Simple enough, right? So I set out to figure out how to install IIS. The first thing I looked for was a built-in type to handle setting up server roles and features. Nada. So off to the Forge I went. I found an amazing IIS module written by Simon Dean. The only problem with it, it doesn’t install IIS.

Enter DISM

DISM or Deployment Image Servicing and Management is where the heavy lifting gets done. is the command line tool that allows you to install roles and features, just like you would from the Server Manager GUI. I owe a huge thanks to Mark Bools for helping shine the light on DISM with a blog post. To get started with dism in puppet, Puppet Labs has published the dism module on the forge that has a type and provider to work with. To get a list of things that can be installed with dism you can run, . From there, you can use the dism type to install the needed packages. This looks something like:

1
2
3
4
5
6
7
8
dism { 'IIS-WebServerRole':
  ensure => present,
}

dism { 'IIS-WebServer':
  ensure  => present,
  require => Dism['IIS-WebServerRole'],
}

General Observations

In general, things worked as expected. Puppet does not seem to care whether the manifests have Windows or UNIX line endings which is very nice. The only thing I have found so far that didn’t, “just work,” was the module tool, otherwise things translate just fine. The big issues left to deal with are not ones that are easily solved by puppet. There are reboots that need to take place as part of basic installations that really don’t lend themselves well to configuration management as a whole.